MoinMoin Logo
  • Comments
  • Immutable Page
  • Menu
    • Navigation
    • RecentChanges
    • FindPage
    • Local Site Map
    • Help
    • HelpContents
    • HelpOnMoinWikiSyntax
    • Display
    • Attachments
    • Info
    • Raw Text
    • Print View
    • Edit
    • Load
    • Save
  • Login

Navigation

  • Start
  • Sitemap
Revision 16 as of 2016-09-28 12:11:02
  • Java
  • Spring
  • SpringBoot

SpringBoot

Example

pom.xml

   1 <?xml version="1.0" encoding="UTF-8"?>
   2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   4     <modelVersion>4.0.0</modelVersion>
   5     <groupId>hello</groupId>
   6     <artifactId>test-spring-boot</artifactId>
   7     <version>0.1.0</version>
   8     <parent>
   9         <groupId>org.springframework.boot</groupId>
  10         <artifactId>spring-boot-starter-parent</artifactId>
  11         <version>1.4.0.RELEASE</version>
  12     </parent>
  13     <dependencies>
  14         <dependency>
  15             <groupId>org.springframework.boot</groupId>
  16             <artifactId>spring-boot-starter-thymeleaf</artifactId>
  17         </dependency>
  18         <dependency>
  19             <groupId>org.mariadb.jdbc</groupId>
  20             <artifactId>mariadb-java-client</artifactId>
  21             <version>1.4.4</version>
  22         </dependency>
  23         <dependency>
  24             <groupId>commons-dbcp</groupId>
  25             <artifactId>commons-dbcp</artifactId>
  26             <version>1.4</version>
  27         </dependency>
  28 
  29          <dependency>
  30             <groupId>org.springframework</groupId>
  31             <artifactId>spring-jdbc</artifactId>
  32             <version>4.3.2.RELEASE</version>
  33         </dependency>
  34 
  35     </dependencies>
  36     <properties>
  37         <start-class>hello.Application</start-class>
  38     </properties>
  39     <build>
  40         <plugins>
  41             <plugin>
  42                 <groupId>org.springframework.boot</groupId>
  43                 <artifactId>spring-boot-maven-plugin</artifactId>
  44             </plugin>
  45         </plugins>
  46     </build>
  47     <repositories>
  48         <repository>
  49             <id>spring-milestone</id>
  50             <url>http://repo.spring.io/libs-release</url>
  51         </repository>
  52     </repositories>
  53     <pluginRepositories>
  54         <pluginRepository>
  55             <id>spring-milestone</id>
  56             <url>http://repo.spring.io/libs-release</url>
  57         </pluginRepository>
  58     </pluginRepositories>
  59 </project>

src/main/java/hello/GreetingController.java

   1 package hello;
   2 
   3 import org.springframework.stereotype.Controller;
   4 import org.springframework.ui.Model;
   5 import org.springframework.web.bind.annotation.RequestMapping;
   6 import org.springframework.web.bind.annotation.RequestParam;
   7 
   8 import org.slf4j.Logger;
   9 import org.slf4j.LoggerFactory;
  10 import org.springframework.web.bind.annotation.ResponseBody;
  11 import org.springframework.beans.factory.annotation.Autowired;
  12 
  13 import java.util.List;
  14 import java.util.ArrayList;
  15 
  16 @Controller
  17 public class GreetingController {
  18     private final Logger logger = LoggerFactory.getLogger(GreetingController.class);
  19     @Autowired
  20     DummyDAO dummyDAO;
  21 
  22     public GreetingController(){
  23         logger.debug("Greeting controller created.");
  24     }
  25 
  26     @RequestMapping("/greeting")
  27     // http://localhost:8080/greeting?name=nnnn 
  28     public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model) {
  29         logger.info("Greeting endpoint called.");
  30         model.addAttribute("name", name);
  31         return "greeting";
  32     }
  33 
  34     @RequestMapping(value="/dummy",produces="application/json")
  35     @ResponseBody
  36     // http://localhost:8080/dummy
  37     public List<Dummy> dummy(){
  38       List<Dummy> list= new java.util.ArrayList<Dummy>();
  39       Dummy dummy = new Dummy();
  40       dummy.setFieldA("AAA");
  41       dummy.setFieldB("CCC");
  42       list.add(dummy);
  43 
  44       Dummy dummy2 = new Dummy();
  45       dummy2.setFieldA("AAA2");
  46       dummy2.setFieldB("CCC2");
  47       list.add(dummy2);
  48 
  49       return list;
  50     }
  51 
  52     @RequestMapping(value="/dummyname",produces="application/json")
  53     @ResponseBody
  54     // http://localhost:8080/dummyname
  55     public String getDummyName(){
  56       return dummyDAO.getNameFromDummy();
  57     }
  58 
  59 
  60 }

src/main/java/hello/Application.java

   1 package hello;
   2 
   3 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
   4 import org.springframework.boot.SpringApplication;
   5 import org.springframework.context.annotation.ComponentScan;
   6 import org.springframework.context.annotation.Bean;
   7 import org.springframework.beans.factory.annotation.Autowired;
   8 import org.springframework.beans.factory.annotation.Qualifier;
   9 
  10 import org.apache.commons.dbcp.BasicDataSource;
  11 import org.springframework.jdbc.core.JdbcTemplate;
  12 
  13 import org.slf4j.Logger;
  14 import org.slf4j.LoggerFactory;
  15 
  16 @ComponentScan
  17 @EnableAutoConfiguration
  18 public class Application {
  19     private static Logger logger;
  20 
  21     public static void main(String[] args) {
  22         logger = LoggerFactory.getLogger(Application.class);
  23         logger.info("Starting application");
  24         SpringApplication.run(Application.class, args);
  25     }
  26 
  27     @Bean(name="basicDataSource",destroyMethod="close")
  28     public BasicDataSource createBasicDataSource(){
  29       logger.info("Creating basicDataSource");
  30       BasicDataSource bds = new BasicDataSource();
  31       bds.setDriverClassName("org.mariadb.jdbc.Driver");
  32       bds.setUrl("jdbc:mariadb://localhost:3306/springmvchtml");
  33       bds.setUsername("usertest");
  34       bds.setPassword("usertest");
  35       bds.setInitialSize(3);
  36       return bds;
  37     }
  38 /*
  39     @Bean(name="jdbcTemplate")
  40     public JdbcTemplate jdbcTemplate(){
  41       logger.info("Creating jdbcTemplate");
  42       return new JdbcTemplate( basicDataSource() );
  43     }
  44 */
  45     @Bean(name="jdbcTemplate")
  46     public JdbcTemplate createJdbcTemplate(@Autowired @Qualifier("basicDataSource") BasicDataSource bds  ){
  47       logger.info("Creating jdbcTemplate");
  48       return new JdbcTemplate( bds );
  49     }
  50 
  51 }

src/main/java/hello/ThreadTimer.java

   1 package hello;
   2 
   3 import org.springframework.stereotype.Component;
   4 import javax.annotation.PostConstruct;
   5 import org.springframework.beans.factory.annotation.Autowired;
   6 import java.text.MessageFormat;
   7 import org.slf4j.Logger;
   8 import org.slf4j.LoggerFactory;
   9 import java.util.ArrayList;
  10 
  11 @Component
  12 public class ThreadTimer extends Thread {
  13   private int delaySeconds;
  14   private Logger logger;
  15   private boolean running;
  16   private Object monitor=new Object();
  17   private ArrayList<Object> subscribers;
  18 
  19   //@Autowired
  20   //WaitThread waitThread;
  21 
  22   public ThreadTimer() {
  23     this.logger = LoggerFactory.getLogger(ThreadTimer.class);
  24     logger.info("Created instance of " + this.getClass().getSimpleName());
  25     this.running = true;
  26     this.delaySeconds = 5 * 1000;
  27     this.setName(this.getClass().getSimpleName() + "_" + this.getName());
  28     this.subscribers = new ArrayList<Object>();
  29   }
  30 
  31   public void addSubscriber(Object subscriber){
  32     this.subscribers.add(subscriber);
  33   }
  34 
  35   @PostConstruct
  36   public void init() {
  37     logger.info("Starting the thread");
  38     this.start();
  39   }
  40 
  41   @Override
  42   public void run() {
  43     while (running) {
  44       try {
  45         Thread.sleep(this.delaySeconds);
  46         logger.info("Delay " + this.getClass().getSimpleName());
  47 
  48         for(Object o: this.subscribers){
  49           synchronized(o){
  50             o.notify();
  51           }
  52         }
  53       }
  54       catch (InterruptedException e) {
  55           logger.info("ThreadTimer interrupted exception:" + e.getMessage() );
  56       }
  57       catch (Exception e) {
  58           e.printStackTrace();
  59           logger.info("ThreadTimer exception:" + e.getMessage() );
  60           stopRunning();
  61       }
  62     }
  63     logger.info("Exited " + this.getClass().getSimpleName());
  64   }
  65 
  66   public void startRunning() {
  67     this.running = true;
  68   }
  69 
  70   public void stopRunning() {
  71     this.running = false;
  72   }
  73 
  74   public void destroy(){
  75     logger.info("Called destroy");
  76     this.stopRunning();
  77     this.interrupt();
  78   }
  79 }

src/main/java/hello/WaitThread.java

   1 package hello;
   2 
   3 import org.springframework.stereotype.Component;
   4 import javax.annotation.PostConstruct;
   5 import java.text.MessageFormat;
   6 import org.slf4j.Logger;
   7 import org.slf4j.LoggerFactory;
   8 import org.springframework.beans.factory.annotation.Autowired;
   9 
  10 @Component
  11 public class WaitThread extends Thread {
  12   private Logger logger;
  13   private boolean running;
  14   private Object monitor;
  15 
  16   @Autowired
  17   ThreadTimer timerThread;
  18 
  19   public WaitThread() {
  20     this.logger = LoggerFactory.getLogger(WaitThread.class);
  21     logger.info("Created instance of " + this.getClass().getSimpleName());
  22     this.running = true;
  23     this.setName(this.getClass().getSimpleName() + "_" + this.getName());
  24     this.monitor=new Object();
  25   }
  26 
  27   @PostConstruct
  28   public void init() {
  29     this.timerThread.addSubscriber(this);
  30     logger.info("Starting the thread");
  31     this.start();
  32   }
  33 
  34   public void run() {
  35     while (running) {
  36       try {
  37         synchronized(this){
  38           this.wait();
  39           logger.info("Notification received.");
  40         }
  41       }
  42       catch (InterruptedException e) {
  43           logger.info("ThreadTimer interrupted exception:" + e.getMessage() );
  44       }
  45       catch (Exception e) {
  46           logger.info("WaitThread exception:" + e.getMessage() );
  47           stopRunning();
  48       }
  49     }
  50     logger.info("Exited " + this.getClass().getSimpleName());
  51   }
  52 
  53   public void startRunning() {
  54     this.running = true;
  55   }
  56 
  57   public void stopRunning() {
  58     this.running = false;
  59   }
  60 
  61   public void destroy(){
  62     logger.info("Called destroy");
  63     this.stopRunning();
  64     this.interrupt();
  65   }
  66 }

src/main/java/hello/Dummy.java

   1 package hello;
   2 
   3 public class Dummy{
   4   private String fieldA;
   5   private String fieldB;
   6 
   7   public Dummy(){
   8   }
   9 
  10   public String getFieldA(){
  11     return fieldA;
  12   }
  13 
  14   public String getFieldB(){
  15     return fieldB;
  16   }
  17 
  18   public void setFieldA(String arg){
  19     fieldA = arg;
  20   }
  21 
  22   public void setFieldB(String arg){
  23     fieldB = arg;
  24   }
  25 }

src/main/java/hello/DummyDAO.java

   1 package hello;
   2 
   3 import org.slf4j.Logger;
   4 import org.slf4j.LoggerFactory;
   5 
   6 import org.springframework.beans.factory.annotation.Autowired;
   7 import org.springframework.beans.factory.annotation.Qualifier;
   8 import org.springframework.jdbc.core.JdbcTemplate;
   9 import org.springframework.stereotype.Component;
  10 
  11 @Component
  12 public class DummyDAO {
  13   @Autowired
  14   @Qualifier("jdbcTemplate")
  15   private JdbcTemplate jdbcTemplate;
  16   private Logger logger;
  17 
  18   public DummyDAO() {
  19     logger = LoggerFactory.getLogger(DummyDAO.class);
  20     logger.info("Created " + this.getClass().getSimpleName());
  21   }
  22 
  23   public String getNameFromDummy() {
  24     return this.jdbcTemplate.queryForObject("select name from dummy limit 1", String.class);
  25   }
  26 }

src/main/resources/templates/greeting.html

   1 <!DOCTYPE HTML>
   2 <html xmlns:th="http://www.thymeleaf.org">
   3 <head>
   4     <title>Getting Started: Serving Web Content</title>
   5     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
   6 </head>
   7 <body>
   8     <p th:text="'Hello, ' + ${name} + '!'" />
   9 </body>
  10 </html>

src/main/resources/application.properties

   1 logging.file=/tmp/testout.log

src/main/resources/logback-spring.xml

   1 <?xml version="1.0" encoding="UTF-8"?>
   2 <configuration>
   3 <!--
   4     <include resource="org/springframework/boot/logging/logback/defaults.xml" />
   5     <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/>
   6     <include resource="org/springframework/boot/logging/logback/file-appender.xml" />
   7 -->
   8     <!-- override spring logback default behaviour -->
   9     <appender name="FILE" class="ch.qos.logback.core.FileAppender">
  10         <file>${filelog}</file>
  11         <encoder>
  12                 <pattern>%date{ISO8601} [%thread] %-5level %logger{35} - %msg%n</pattern>
  13         </encoder>
  14     </appender>
  15 
  16     <appender name="GREETFILE" class="ch.qos.logback.core.FileAppender">
  17         <file>/tmp/greet.log</file>
  18         <encoder>
  19                 <pattern>%date{ISO8601} [%thread] %-5level %logger{35} - %msg%n</pattern>
  20         </encoder>
  21     </appender>
  22 
  23     <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
  24         <layout class="ch.qos.logback.classic.PatternLayout">
  25                 <Pattern>%yellow(%date{ISO8601}) %green([%thread]) %highlight(%-5level) %cyan(%logger{35}) - %white(%msg%n) </Pattern>
  26         </layout>
  27     </appender>
  28 
  29     <root level="INFO">
  30         <appender-ref ref="FILE" />
  31         <appender-ref ref="CONSOLE"/>
  32     </root>
  33 
  34     <logger name="hello.GreetingController" level="debug" additivity="false">
  35         <appender-ref ref="GREETFILE"/>
  36         <appender-ref ref="CONSOLE" />
  37     </logger>
  38 
  39 </configuration>

src/main/resources/test.sql

   1 --JDBC URL: jdbc:mariadb://localhost:3306/springmvchtml
   2 --mysql -u root -p
   3 create database springmvchtml;
   4 create user 'usertest'@'%' identified by '????????';
   5 create user 'usertest'@'localhost' identified by '????????';
   6 grant all on springmvchtml.* to 'usertest'@'%';
   7 grant all on springmvchtml.* to 'usertest'@'localhost';
   8 show grants for 'usertest'@'%';
   9 show grants for 'usertest'@'localhost';
  10 create table springmvchtml.dummy (name varchar(255) ) ;
  11 insert into springmvchtml.dummy (name) values('aaaa');
  12 insert into springmvchtml.dummy (name) values('bbbb');
  13 commit;
  14 -- mysql -u usertest -p
  15 

JAR files list

  • jar tf target/test-spring-boot-0.1.0.jar | grep "\.jar"

BOOT-INF/lib/jackson-core-2.8.1.jar
BOOT-INF/lib/spring-web-4.3.2.RELEASE.jar
BOOT-INF/lib/unbescape-1.1.0.RELEASE.jar
BOOT-INF/lib/javassist-3.20.0-GA.jar
BOOT-INF/lib/mariadb-java-client-1.4.4.jar
BOOT-INF/lib/jul-to-slf4j-1.7.21.jar
BOOT-INF/lib/groovy-2.4.7.jar
BOOT-INF/lib/hibernate-validator-5.2.4.Final.jar
BOOT-INF/lib/classmate-1.3.1.jar
BOOT-INF/lib/tomcat-embed-el-8.5.4.jar
BOOT-INF/lib/tomcat-embed-core-8.5.4.jar
BOOT-INF/lib/commons-pool-1.6.jar
BOOT-INF/lib/thymeleaf-spring4-2.1.5.RELEASE.jar
BOOT-INF/lib/spring-context-4.3.2.RELEASE.jar
BOOT-INF/lib/thymeleaf-2.1.5.RELEASE.jar
BOOT-INF/lib/spring-boot-starter-tomcat-1.4.0.RELEASE.jar
BOOT-INF/lib/thymeleaf-layout-dialect-1.4.0.jar
BOOT-INF/lib/spring-boot-autoconfigure-1.4.0.RELEASE.jar
BOOT-INF/lib/snakeyaml-1.17.jar
BOOT-INF/lib/spring-boot-starter-web-1.4.0.RELEASE.jar
BOOT-INF/lib/spring-boot-starter-logging-1.4.0.RELEASE.jar
BOOT-INF/lib/spring-webmvc-4.3.2.RELEASE.jar
BOOT-INF/lib/spring-beans-4.3.2.RELEASE.jar
BOOT-INF/lib/slf4j-api-1.7.21.jar
BOOT-INF/lib/spring-jdbc-4.3.2.RELEASE.jar
BOOT-INF/lib/jackson-annotations-2.8.1.jar
BOOT-INF/lib/commons-dbcp-1.4.jar
BOOT-INF/lib/ognl-3.0.8.jar
BOOT-INF/lib/spring-boot-starter-1.4.0.RELEASE.jar
BOOT-INF/lib/tomcat-embed-websocket-8.5.4.jar
BOOT-INF/lib/spring-boot-starter-thymeleaf-1.4.0.RELEASE.jar
BOOT-INF/lib/spring-tx-4.3.2.RELEASE.jar
BOOT-INF/lib/logback-classic-1.1.7.jar
BOOT-INF/lib/spring-boot-1.4.0.RELEASE.jar
BOOT-INF/lib/spring-expression-4.3.2.RELEASE.jar
BOOT-INF/lib/logback-core-1.1.7.jar
BOOT-INF/lib/validation-api-1.1.0.Final.jar
BOOT-INF/lib/spring-core-4.3.2.RELEASE.jar
BOOT-INF/lib/jackson-databind-2.8.1.jar
BOOT-INF/lib/jcl-over-slf4j-1.7.21.jar
BOOT-INF/lib/log4j-over-slf4j-1.7.21.jar
BOOT-INF/lib/spring-aop-4.3.2.RELEASE.jar
BOOT-INF/lib/jboss-logging-3.3.0.Final.jar

Add HTTPS/SSL support

Keystore creation

#create keystore with key springboot
keytool -genkey -alias springboot -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore springboot.p12 -validity 3650

Enter keystore password: 12345678
Re-enter new password: 12345678
What is your first and last name?
  [Unknown]:  Spring Boot
What is the name of your organizational unit?
  [Unknown]:  Boot
What is the name of your organization?
  [Unknown]:  Boot
What is the name of your City or Locality?
  [Unknown]:  Lisbon
What is the name of your State or Province?
  [Unknown]:  Estremadura
What is the two-letter country code for this unit?
  [Unknown]:  PT
Is CN=Spring Boot, OU=Boot, O=Boot, L=Lisbon, ST=Estremadura, C=PT correct?
  [no]:  yes

#list keys 
keytool -list -v -keystore springboot.p12 -storetype pkcs12  

Code to add in Application class/configuration

// import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
// import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
// import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
// import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
// import java.io.FileNotFoundException;
// import org.apache.catalina.connector.Connector;
// import org.springframework.beans.factory.annotation.Value;
// import javax.inject.Inject;
// import org.springframework.util.ResourceUtils;

public class TCC implements TomcatConnectorCustomizer{
    private String keystoreFile;
    private String keystorePassword;
    private String keystoreType;
    private String keystoreAlias;

    public TCC(String keystoreFile, String keystorePassword, String keystoreType, String keystoreAlias){
        this.keystoreFile=keystoreFile;
        this.keystorePassword=keystorePassword;
        this.keystoreType=keystoreType;
        this.keystoreAlias=keystoreAlias;
    }

    public void customize(Connector connector){
        connector.setSecure(true);
        connector.setScheme("https");
        connector.setAttribute("keystoreFile", keystoreFile);
        connector.setAttribute("keystorePass", keystorePassword);
        connector.setAttribute("keystoreType", keystoreType);
        connector.setAttribute("keyAlias", keystoreAlias);
        connector.setAttribute("clientAuth", "false");
        connector.setAttribute("sslProtocol", "TLS");
        connector.setAttribute("SSLEnabled", true);
    }
}

public class ESCC implements EmbeddedServletContainerCustomizer{
    private String keystoreFile;
    private String keystorePassword;
    private String keystoreType;
    private String keystoreAlias;

    public ESCC(String keystoreFile, String keystorePassword, String keystoreType, String keystoreAlias){
        this.keystoreFile=keystoreFile;
        this.keystorePassword=keystorePassword;
        this.keystoreType=keystoreType;
        this.keystoreAlias=keystoreAlias;
    }

    public void customize(ConfigurableEmbeddedServletContainer container){
        TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;

        TomcatConnectorCustomizer tcc = new TCC(keystoreFile,keystorePassword,keystoreType,keystoreAlias);
        containerFactory.addConnectorCustomizers(tcc);
    }
}

@Bean
@Inject
public EmbeddedServletContainerCustomizer containerCustomizer(
    @Value("${keystore.file}") String keystoreFile,
    @Value("${keystore.password}") String keystorePassword,
    @Value("${keystore.type}") String keystoreType,
    @Value("${keystore.alias}") String keystoreAlias) throws FileNotFoundException
{
    final String absoluteKeystoreFile = ResourceUtils.getFile(keystoreFile).getAbsolutePath();
    EmbeddedServletContainerCustomizer escc = new ESCC(absoluteKeystoreFile,keystorePassword,keystoreType,keystoreAlias);
    return escc;
}

pom.xml

<!-- Add dependency to support @Inject annotation -->
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
  • Add server.port=8443 to application.properties or use system property -Dserver.port=8443
  • Run java -Dfilelog=/tmp/out.log -Dkeystore.file=springboot.p12 -Dkeystore.password=12345678 -Dkeystore.type=PKCS12 -Dkeystore.alias=springboot -jar target/test-spring-boot-0.1.0.jar
  • Access https://localhost:8443/greeting?name=x

  • MoinMoin Powered
  • Python Powered
  • GPL licensed
  • Valid HTML 4.01