Start A Web Application With Spring Boot

a) Easy start up using Spring initializr

Go http://start.spring.io/ & fill in the blank (All the below are using spring boot 1.3.0 M4):

and press the blue color Generate Project button, you will get a download- minioasis-security.zip.

The generated folder structure will be:

minioasis-security               // forder structure
|_ src                            
   |_ main
   |  |_ java
   |  |  |_ org
   |  |     |_ minioasis
   |  |     |_ security
   |  |        |_ MinioasisSecurityApplication.java
   |  |        |_ ServletInitializer.java
   |  |_ resources
   |     |_ static
   |     |_ templates
   |     |_ application.properties
   |_ test
   |  |_ java
   |     |_ org
   |        |_ minioasis
   |           |_ security
   |_ build.gradle

build.gradle,

buildscript {
    ext {
        springBootVersion = '1.3.0.M4'
    }
    repositories {
        mavenCentral()
        maven { url "https://repo.spring.io/snapshot" }
        maven { url "https://repo.spring.io/milestone" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
    }
}

apply plugin: 'java'
apply plugin: 'eclipse-wtp'
apply plugin: 'idea'
apply plugin: 'spring-boot' 
apply plugin: 'war'


war {
    baseName = 'minioasis-security'
    version = '0.0.1-SNAPSHOT'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
    maven { url "https://repo.spring.io/snapshot" }
    maven { url "https://repo.spring.io/milestone" }
}

configurations {
    providedRuntime
}

dependencies {
    compile("org.springframework.cloud:spring-cloud-starter-oauth2")
    compile("org.springframework.cloud:spring-cloud-starter-security")
    compile("org.springframework.boot:spring-boot-starter-data-elasticsearch")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    compile("org.springframework.boot:spring-boot-starter-web")
    runtime("com.h2database:h2")
    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
    testCompile("org.springframework.boot:spring-boot-starter-test") 
}

dependencyManagement {
    imports { 
        mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Brixton.BUILD-SNAPSHOT" 
    }
}


eclipse {
    classpath {
         containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
         containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8'
    }
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

MinioasisSecurityApplication.java,

package org.minioasis.security;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MinioasisSecurityApplication {

    public static void main(String[] args) {
        SpringApplication.run(MinioasisSecurityApplication.class, args);
    }
}

ServletInitializer.java,

package org.minioasis.security;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(MinioasisSecurityApplication.class);
    }

}

MinioasisSecurityApplicationTests.java,

package org.minioasis.security;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MinioasisSecurityApplication.class)
@WebAppConfiguration
public class MinioasisSecurityApplicationTests {

    @Test
    public void contextLoads() {
    }

}

After import the Gradle project minioasis-security into Eclipse (gradle will take few minutes to download those dependencies if your line are slow),

b) Run the application

Create 2 files,

src\main\resources\templates\index.html

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">
    <head lang="en">
        <title>Minioasis Security</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
        <h1>Hello</h1>
        <h2>Minioasis Security !</h2>
    </body>
</html>

src\main\java\org\minioasis\security\controller\IndexController.java (create a new package - controller)


package org.minioasis.security.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {

    @RequestMapping("/")
    String index(){
        return "index";
    }
}

Quick Note : A default behavior of Spring Boot when using the @SpringBootApplication annotation is to perform a package scan on its package (and all sub packages). Because the Spring Boot application resides in the package org.minioasis.security, the annotated Spring Components in the child packages are automatically found by Spring (since the IndexController are inside the package). If they were in a different package tree, we would need to tell Spring Boot to scan that package explicitly, this is important to know for beginner.

Run the application by pointing the mouse to the class MinioasisSecurityApplication , right click --> Run As --> Java Application, This will start the application with an embeded tomcat server. Go to the browser, http://localhost:8080/, you will see

why there is a login page ? Because we added Spring Security into our build, Spring Boot has configured Spring Security for our use. The default behavior is to require basic auth for all endpoints.

To login, you can use


username : user
password : bbe3fead-907b-4436-a6f9-5d2d8be928b2

the password can be found in the following place :

After login, you will see :

it's done, we have a simple web application !

Notes :

1) To avoid spring basic authentication login, add the following configuration class,

src\main\java\org\minioasis\security\config\SecurityConfiguration.java

package org.minioasis.security.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests().antMatchers("/").permitAll();
    }

}

2) Static resources with Spring Boot ( Manage it using WebJars )

Spring Boot will automatically serve static resources from the path /resources/static. By a generally accepted convention, we typically put x into y

x                           y
-----------------------------------------------
CSS files           ---> /resources/static/css,
Javascript files    ---> /resources/static/js,
Images in           ---> /resources/static/images.

After many times we create folders css, js, images and copied Bootstrap, CSS or JQuery files into the resource folder, then managed the lifecycle of their versions, we will tire. WebJars is a cool project to handle this problem.

step 1 : Add WebJars dependencies to build.gradle

compile("org.webjars:bootstrap:3.3.4")
compile("org.webjars:jquery:2.1.4")

step 2 : Create file "minioasis.css" to /resources/static/css

body {
    background-color: #F3FAB6;
}

step 3: Add codes below to index.html

    <link
        href="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.4/css/bootstrap.min.css"
        th:href="@{/webjars/bootstrap/3.3.4/css/bootstrap.min.css}"
        rel="stylesheet" media="screen" />

    <script 
        src="http://cdn.jsdelivr.net/webjars/jquery/2.1.4/jquery.min.js"
        th:src="@{/webjars/jquery/2.1.4/jquery.min.js}"></script>

    <link 
        href="../static/css/minioasis.css" th:href="@{css/minioasis.css}"
        rel="stylesheet" media="screen" />
  • folder css, js or images still have to create yourself, because WebJars are not using them.
  • th: is a thymeleaf namespace.

3) Using the H2 Database Console in Spring Boot Application

step 1 : Modify build.gradle

runtime("com.h2database:h2") -->  compile("com.h2database:h2")        // change to compile scope

step 2 : Spring Configuration

Normally, we configure the H2 database in the web.xml file as a servlet, but Spring Boot is going to use an embedded instance of Tomcat, so we don’t have access to the web.xml file. Spring Boot provide us a ServletRegistrationBean for the registration of the H2 servlet.

WebConfiguration.java

package org.minioasis.security.config;

import org.h2.server.web.WebServlet;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebConfiguration {
    @Bean
    ServletRegistrationBean h2servletRegistration(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean( new WebServlet());
        registrationBean.addUrlMappings("/console/*");
        return registrationBean;
    }
}

If you are not using Spring Security with the H2 database console, this is all you need to do. When you run your Spring Boot application, you’ll now be able to access the H2 database console at http://localhost:8080/console.

step 3 : Spring Security Configuration - Modify SecurityConfiguration.java

If you’ve enabled Spring Security in your Spring Boot application, you will not be able to access the H2 database console. With its default settings under Spring Boot, Spring Security will block access to H2 database console.

To enable access to the H2 database console under Spring Security you need to change three things:

  • Allow all access to the url path /console/*.
  • Disable CRSF (Cross-Site Request Forgery). By default, Spring Security will protect against CRSF attacks.
  • Since the H2 database console runs inside a frame, you need to enable this in in Spring Security.
package org.minioasis.security.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        // allow all requests to the root url (“/”)
        httpSecurity.authorizeRequests().antMatchers("/").permitAll()
                    .and()
        // allow all requests to the H2 database console url (“/console/*”)
                    .authorizeRequests().antMatchers("/console/**").permitAll();
        // disable CSRF protection            
        httpSecurity.csrf().disable();
        // disable X-Frame-Options in Spring Security
        httpSecurity.headers().frameOptions().disable();
    }

}

You’ll now be able to access the H2 database console at http://localhost:8080/console even spring security are on.

Notes :

  1. Where are the database files stored ?

    If JDBC URL : jdbc:h2:~/test , this will create a database file in C:\Users\xxx\test.mv.db

  2. It will be an in-memory database if JDBC URL : jdbc:h2:mem:test.
  3. Where to show a "Gradle Tasks" perspective ? Window > Show View > Other

Ref:

  1. Spring Boot Web Application – Part 2 – Using Thymeleaf
  2. Using the H2 Database Console in Spring Boot with Spring Security