WebJars in Spring Boot Application - Bootstrap and JQuery

In this post, we will discuss how to use Webjars in JSP as well as Thymeleaf with sample code examples.

What is WebJars?

WebJars are client-side web libraries (e.g. jQuery & Bootstrap) packaged into JAR (Java Archive) files.
Read more at official documentation at https://www.webjars.org/.

Why Use WebJars?

This question has a very simple answer – because it's easy to use and maintain.

Manually adding and managing client-side dependencies often results in difficult to maintain codebases.

Also, most Java developers prefer to use Maven and Gradle as build and dependency management tools.

The main problem WebJars solves is making client-side dependencies available on Maven Central and usable in any standard Maven project.

Here are a few interesting advantages of WebJars:
  • We can explicitly and easily manage the client-side dependencies in JVM-based web applications
  • We can use them with any commonly used build tool, eg: Maven, Gradle, etc
  • WebJars behave like any other Maven dependency – which means that we get transitive dependencies as well.
Read more at official documentation at https://www.webjars.org/.

Adding WebJars to Pom.xml

Below snippet shows how to add Twitter Bootstrap and jQuery to pom.xml:
<!-- bootstrap and jquery -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>
        <dependency>
             <groupId>org.webjars</groupId>
             <artifactId>jquery</artifactId>
             <version>3.2.1</version>
        </dependency>

Now Twitter Bootstrap and jQuery are available on the project classpath; we can simply reference them and use them in our application.

Using WebJars in JSP Pages

Now we can use Twitter Bootstrap and jQuery in the JSP pages:
<script src="/webjars/bootstrap/3.3.7-1/js/bootstrap.min.js"></script>
For a version-agnostic approach:
<script src="/webjars/bootstrap/js/bootstrap.min.js"></script>
Add jQuery:
<script src="/webjars/jquery/3.1.1/jquery.min.js"></script>
And the version-agnostic approach:
<script src="/webjars/jquery/jquery.min.js"></script>
Here is a sample snippet code example:

<!DOCTYPE html>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="webjars/bootstrap/3.3.7/css/bootstrap.min.css" />
 <script type="text/javascript" src="webjars/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<c:url value="/css/main.css" var="jstlCss" />
<link href="${jstlCss}" rel="stylesheet" />
</head>
<body>
 <div class="container">
  <header>
   <h1>Spring MVC + JSP + JPA + Spring Boot 2</h1>
  </header>
  <div class="starter-template">
   <h1>Users List</h1>
   <table
    class="table table-striped table-hover table-condensed table-bordered">
    <tr>
     <th>Id</th>
     <th>Name</th>
    </tr>
    <c:forEach var="user" items="${users}">
     <tr>
      <td>${user.id}</td>
      <td>${user.name}</td>
     </tr>
    </c:forEach>
   </table>
  </div>
 </div>
</body>
</html>
Check out step by step complete example at Spring MVC + Spring Boot2 + JSP + JPA + Hibernate 5 + MySQL Example.

Using WebJars in Thymeleaf Pages

Using bootstrap CSS file in Thymeleaf templates:
<link rel="stylesheet" type="text/css"
 th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.min.css}" />

Using bootstrap and JQuery js files in Thymeleaf templates:
 <script type="text/javascript"
  th:src="@{/webjars/jquery/3.2.1/jquery.min.js/}"></script>
 <script type="text/javascript"
  th:src="@{/webjars/bootstrap/3.3.7/js/bootstrap.min.js}"></script>

Here is a complete code using WebJars in Thymeleaf templates:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

<link rel="stylesheet" type="text/css"
 th:href="@{/webjars/bootstrap/3.3.7/css/bootstrap.min.css}" />

<title>Registration</title>
</head>
<body>
 <nav class="navbar navbar-inverse navbar-fixed-top">
  <div class="container">
   <div class="navbar-header">
    <button type="button" class="navbar-toggle collapsed"
     data-toggle="collapse" data-target="#navbar" aria-expanded="false"
     aria-controls="navbar">
     <span class="sr-only">Toggle navigation</span> <span
      class="icon-bar"></span> <span class="icon-bar"></span> <span
      class="icon-bar"></span>
    </button>
    <a class="navbar-brand" href="#" th:href="@{/}">Registration and
     Login Module</a>
   </div>
  </div>
 </nav>
 <br>
 <br>
 <div class="container">
  <div class="row">
   <div class="col-md-6 col-md-offset-3">

    <div th:if="${param.success}">
     <div class="alert alert-info">You've successfully registered
      to our awesome app!</div>
    </div>

    <h1>Registration</h1>
    <form th:action="@{/registration}" th:object="${user}" method="post">

     <p class="error-message" th:if="${#fields.hasGlobalErrors()}"
      th:each="error : ${#fields.errors('global')}" th:text="${error}">Validation
      error</p>

     <div class="form-group"
      th:classappend="${#fields.hasErrors('firstName')}? 'has-error':''">
      <label for="firstName" class="control-label">First name</label> <input
       id="firstName" class="form-control" th:field="*{firstName}" />
      <p class="error-message"
       th:each="error: ${#fields.errors('firstName')}"
       th:text="${error}">Validation error</p>
     </div>
     <div class="form-group"
      th:classappend="${#fields.hasErrors('lastName')}? 'has-error':''">
      <label for="lastName" class="control-label">Last name</label> <input
       id="lastName" class="form-control" th:field="*{lastName}" />
      <p class="error-message"
       th:each="error : ${#fields.errors('lastName')}"
       th:text="${error}">Validation error</p>
     </div>
     <div class="form-group"
      th:classappend="${#fields.hasErrors('email')}? 'has-error':''">
      <label for="email" class="control-label">E-mail</label> <input
       id="email" class="form-control" th:field="*{email}" />
      <p class="error-message"
       th:each="error : ${#fields.errors('email')}" th:text="${error}">Validation
       error</p>
     </div>
     <div class="form-group"
      th:classappend="${#fields.hasErrors('confirmEmail')}? 'has-error':''">
      <label for="confirmEmail" class="control-label">Confirm
       e-mail</label> <input id="confirmEmail" class="form-control"
       th:field="*{confirmEmail}" />
      <p class="error-message"
       th:each="error : ${#fields.errors('confirmEmail')}"
       th:text="${error}">Validation error</p>
     </div>
     <div class="form-group"
      th:classappend="${#fields.hasErrors('password')}? 'has-error':''">
      <label for="password" class="control-label">Password</label> <input
       id="password" class="form-control" type="password"
       th:field="*{password}" />
      <p class="error-message"
       th:each="error : ${#fields.errors('password')}"
       th:text="${error}">Validation error</p>
     </div>
     <div class="form-group"
      th:classappend="${#fields.hasErrors('confirmPassword')}? 'has-error':''">
      <label for="confirmPassword" class="control-label">Confirm
       password</label> <input id="confirmPassword" class="form-control"
       type="password" th:field="*{confirmPassword}" />
      <p class="error-message"
       th:each="error : ${#fields.errors('confirmPassword')}"
       th:text="${error}">Validation error</p>
     </div>
     <div class="form-group"
      th:classappend="${#fields.hasErrors('terms')}? 'has-error':''">
      <input id="terms" type="checkbox" th:field="*{terms}" />   <label
       class="control-label" for="terms"> I agree with the <a
       href="#">terms and conditions</a> for Registration.
      </label>
      <p class="error-message"
       th:each="error : ${#fields.errors('terms')}" th:text="${error}">Validation
       error</p>
     </div>
     <div class="form-group">
      <button type="submit" class="btn btn-success">Register</button>
      <span>Already registered? <a href="/" th:href="@{/login}">Login
        here</a></span>
     </div>
    </form>
   </div>
  </div>
 </div>

 <script type="text/javascript"
  th:src="@{/webjars/jquery/3.2.1/jquery.min.js/}"></script>
 <script type="text/javascript"
  th:src="@{/webjars/bootstrap/3.3.7/js/bootstrap.min.js}"></script>
</body>
</html>

Above HTML Code produces below screens


After successful registration, the user is redirected to http://localhost:8080/registration?success

Check out step by step complete example at User Registration Module using Spring Boot + Spring MVC + Spring Security + Hibernate 5 + Thymeleaf + MySQL.

Comments