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

Upload page content

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment

Revision 23 as of 2016-09-29 18:07: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

Environment variables

src/main/resources/application.properties

logging.file=/tmp/testout.log
server.port=8443
foo.bar=bohica

   1 import org.springframework.core.env.Environment;
   2 import org.springframework.beans.factory.annotation.Value;
   3 //....................
   4     @Resource
   5     Environment env;
   6     @Value("${foo.bar}")
   7     private String fooBar;
   8 
   9     @RequestMapping(value="/env",produces="application/json")
  10     @ResponseBody
  11     public List<String> getEnv(){
  12       List<String> ret = new ArrayList<String>();
  13       ret.add( env.getProperty("foo.bar") );
  14       ret.add(fooBar);
  15       return ret;
  16     }
  17 //....................
  18 

Override value in application.properties

  • java -jar target/test-spring-boot-0.1.0.jar --foo.bar=snafu

Instead of using @Autowired or @Inject use @Resource (javax.annotation.Resource).

Example JPA RabbitMQ HttpSession Redis

WaitThread.java

package hello;

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.text.MessageFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

@Component
public class WaitThread extends Thread {
  private Logger logger;
  private boolean running;
  private Object monitor;

  @Autowired
  ThreadTimer timerThread;

  public WaitThread() {    
    this.logger = LoggerFactory.getLogger(WaitThread.class);
    logger.info("Created instance of " + this.getClass().getSimpleName());
    this.running = true;
    this.setName(this.getClass().getSimpleName() + "_" + this.getName());
    this.monitor=new Object();
  }

  @PostConstruct
  public void init() {
    this.timerThread.addSubscriber(this);
    logger.info("Starting the thread");
    this.start();
  }

  public void run() {
    while (running) {
      try {
        synchronized(this){
          this.wait();
          logger.info("Notification received.");
        }
      }
      catch (InterruptedException e) {
          logger.info("ThreadTimer interrupted exception:" + e.getMessage() );
      }
      catch (Exception e) {
          logger.info("WaitThread exception:" + e.getMessage() );
          stopRunning();
      }      
    }
    logger.info("Exited " + this.getClass().getSimpleName());
  }

  public void startRunning() {
    this.running = true;
  }

  public void stopRunning() {
    this.running = false;
  }
  
  public void destroy(){
    logger.info("Called destroy");
    this.stopRunning();
    this.interrupt();    
  }
}

ThreadTimer.java

package hello;

import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import java.text.MessageFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;

@Component
public class ThreadTimer extends Thread {
  private int delaySeconds;
  private Logger logger;
  private boolean running;
  private Object monitor=new Object();
  private ArrayList<Object> subscribers;

  public ThreadTimer() {    
    this.logger = LoggerFactory.getLogger(ThreadTimer.class);
    logger.info("Created instance of " + this.getClass().getSimpleName());
    this.running = true;
    this.delaySeconds = 5 * 1000;
    this.setName(this.getClass().getSimpleName() + "_" + this.getName());
    this.subscribers = new ArrayList<Object>();
  }

  public void addSubscriber(Object subscriber){
    this.subscribers.add(subscriber);
  }

  @PostConstruct
  public void init() {
    logger.info("Starting the thread");
    this.start();
  }

  @Override
  public void run() {
    while (running) {
      try {
        Thread.sleep(this.delaySeconds);
        logger.info("Delay " + this.getClass().getSimpleName());

        for(Object o: this.subscribers){
          synchronized(o){
            o.notify();
          }
        }
      }
      catch (InterruptedException e) {
          logger.info("ThreadTimer interrupted exception:" + e.getMessage() );
      }
      catch (Exception e) {
          e.printStackTrace();
          logger.info("ThreadTimer exception:" + e.getMessage() );
          stopRunning();
      }      
    }
    logger.info("Exited " + this.getClass().getSimpleName());
  }

  public void startRunning() {
    this.running = true;
  }

  public void stopRunning() {
    this.running = false;
  }
  
  public void destroy(){
    logger.info("Called destroy");
    this.stopRunning();
    this.interrupt();    
  }
}

MessageHandler.java

package hello;

import java.nio.charset.StandardCharsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MessageHandler{
    private final Logger logger = LoggerFactory.getLogger(MessageHandler.class);
    
    public void handleMessage(byte[] message){
        String msg = new String(message, StandardCharsets.UTF_8);
        logger.info("Received msg " + msg   );
    }

    public void handleMessage(String message){
        logger.info("Received msg " + message   );
    }

}

GreetingController.java

package hello;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.ArrayList;
import org.springframework.web.bind.annotation.PathVariable;
//import javax.inject.Inject;
import org.springframework.core.env.Environment;
import org.springframework.beans.factory.annotation.Value;
import javax.annotation.Resource;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import javax.servlet.http.HttpSession;

@Controller
public class GreetingController {
    private final Logger logger = LoggerFactory.getLogger(GreetingController.class);
    @Resource
    DummyDAO dummyDAO;

    @Resource
    Environment env;

    @Resource
    RabbitTemplate rabbitTemplate;
 
    @Value("${instance.name}")
    String instanceName;
    
    public GreetingController(){
        logger.debug("Greeting controller created.");
    }

    @RequestMapping("/greeting")
    public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model  ) {        
        model.addAttribute("name", name);
        rabbitTemplate.convertAndSend("topicExchange","myQueue", name  );
        rabbitTemplate.convertAndSend("fanoutExchange","", name  );
        return "greeting";
    }

    @RequestMapping("/setvalue/{value}")
    @ResponseBody
    public String setValue(@PathVariable("value") String value, Model model,HttpSession httpSession) {
        httpSession.setAttribute("name", value );
        return httpSession.getId();
    }

    @RequestMapping("/getvalue")
    @ResponseBody
    public String setValue(Model model,HttpSession httpSession) {
        return (String) httpSession.getAttribute("name");        
    }
    
    @RequestMapping("/instancename")
    @ResponseBody
    public String setValue(Model model) {
        return this.instanceName;        
    }
    
    @RequestMapping("/greeting/add/{name}")
    public String addGreeting(@PathVariable("name") String name, Model model) {
        model.addAttribute("name", name);
        dummyDAO.addName(name);
        return "greeting";
    }
    
    @RequestMapping(value="/dummy",produces="application/json")
    @ResponseBody
    public List<DummyJPA> dummy(){
      return dummyDAO.getAllNames();
    }

    @RequestMapping(value="/dummyname",produces="application/json")
    @ResponseBody
    public String getDummyName(){
      return dummyDAO.getNameFromDummy();
    }

    @Value("${foo.bar}")
    private String fooBar;

    @RequestMapping(value="/env",produces="application/json")
    @ResponseBody
    public List<String> getEnv(){
      List<String> ret = new ArrayList<String>(); 
      ret.add( env.getProperty("foo.bar") );
      ret.add(fooBar);
      return ret;
    }
    
}

DummyJPA.java

package hello;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQuery;
import javax.persistence.NamedQueries;

@Entity
@NamedQueries({
    @NamedQuery(name="DummyJPA.getAll",  query="Select e From DummyJPA e")
})
public class DummyJPA{
  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  private Long id;
  private String dummy;

  public DummyJPA(){
  } 

  public String getDummy(){
    return this.dummy;
  }

  public void setDummy(String dummy){
    this.dummy=dummy;
  }

  @Override
  public String toString(){
    return String.format("Dummy %s", this.dummy);
  }
}

DummyDAO.java

package hello;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import javax.persistence.PersistenceContext;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.Transactional;
import java.util.List;

@Component
public class DummyDAO {
  @Autowired
  @Qualifier("jdbcTemplate")
  private JdbcTemplate jdbcTemplate;
  private Logger logger;

  @PersistenceContext(unitName="default")
  EntityManager em;

  public DummyDAO() {
    logger = LoggerFactory.getLogger(DummyDAO.class);
    logger.info("Created " + this.getClass().getSimpleName());
  }

  public String getNameFromDummy() {
    return this.jdbcTemplate.queryForObject("select name from dummy limit 1", String.class);
  }

  @Transactional
  public void addName(String name){
    DummyJPA djpa = new DummyJPA();
    djpa.setDummy(name);
    em.persist(djpa);
  }

  @Transactional
  public List<DummyJPA> getAllNames(){
    return em.createNamedQuery("DummyJPA.getAll",DummyJPA.class).getResultList();
  }

}

Dummy.java

package hello;

public class Dummy{
  private String fieldA;
  private String fieldB;
  
  public Dummy(){
  }

  public String getFieldA(){
    return fieldA;
  }
  
  public String getFieldB(){
    return fieldB;
  }
  
  public void setFieldA(String arg){
    fieldA = arg;
  }
  
  public void setFieldB(String arg){
    fieldB = arg;
  }
}

ConfigHttpSession.java

/* 
http://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot.html

pkg install redis #freebsd
add redis_enable="YES" to /etc/rc.conf
/usr/local/etc/rc.d/redis start

/usr/local/etc/redis.conf
requirepass 12345678

keys *
hgetall <hashkey>

Same as in application.properties spring.redis.password=12345678

https://localhost:8443/setvalue/valx
147569e4-9e6d-4363-a373-b20261513f11

https://localhost:8443/getvalue
SESSION=147569e4-9e6d-4363-a373-b20261513f11

2 instances of spring boot using the same redis server
curl -k -v --cookie "SESSION=147569e4-9e6d-4363-a373-b20261513f11" https://localhost:8443/getvalue
curl -k -v --cookie "SESSION=147569e4-9e6d-4363-a373-b20261513f11" https://localhost:8444/getvalue 
*/
package hello;

import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@EnableRedisHttpSession
public class ConfigHttpSession{
    // springSessionRepositoryFilterbean is responsible for replacing the HttpSession with a custom implementation that is backed by Spring Session.    
}

BroadcastMessageHandler.java

package hello;

import java.nio.charset.StandardCharsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BroadcastMessageHandler{
    private final Logger logger = LoggerFactory.getLogger(BroadcastMessageHandler.class);
    
    public void handleMessage(byte[] message){
        String msg = new String(message, StandardCharsets.UTF_8);
        logger.info("Received msg " + msg   );
    }

    public void handleMessage(String message){
        logger.info("Received msg " + message   );
    }
}

Application.java

package hello;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.domain.EntityScan;
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 javax.annotation.Resource;
import org.springframework.util.ResourceUtils;
import org.springframework.core.env.Environment;

//-- rabbit
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.AnonymousQueue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import java.net.URI;
//-- rabbit

@ComponentScan
@EnableAutoConfiguration
@EntityScan(basePackages="hello")
public class Application {
    @Resource
    Environment env;

    private static Logger logger;

    public static void main(String[] args) {
        logger = LoggerFactory.getLogger(Application.class);
        logger.info("Starting application");
        SpringApplication.run(Application.class, args);
    }

    @Bean(name="basicDataSource",destroyMethod="close") 
    public BasicDataSource createBasicDataSource(){
      logger.info("Creating basicDataSource");
      BasicDataSource bds = new BasicDataSource();
      // get config data from application.properties
      bds.setDriverClassName(env.getProperty("db.driverclass") );
      bds.setUrl(env.getProperty("db.jdbcurl") );
      bds.setUsername( env.getProperty("db.username") );
      bds.setPassword( env.getProperty("db.password") );
      bds.setInitialSize( Integer.parseInt( env.getProperty("db.initialsizeconnpool")) );
      return bds;
    }

    @Bean(name="jdbcTemplate")
    public JdbcTemplate createJdbcTemplate(@Autowired @Qualifier("basicDataSource") BasicDataSource bds  ){
      logger.info("Creating jdbcTemplate");
      return new JdbcTemplate( bds );
    }

//---  
    public class TCC implements TomcatConnectorCustomizer{
        Environment env;

        public TCC(Environment env){ 
            this.env=env;  
        }  

        public void customize(Connector connector){
            String absoluteKeystoreFile = "";
            logger.info(String.format("Keystore file: %s" , env.getProperty("keystore.file")   )); 

            try{ 
                absoluteKeystoreFile = ResourceUtils.getFile(env.getProperty("keystore.file")).getAbsolutePath(); 
                logger.info(String.format("Absolute path keystore: %s" , absoluteKeystoreFile )  );
            }
            catch(Exception ex){
              logger.error( ex.getMessage() );
            }

            connector.setSecure(true);
            connector.setScheme("https");
            connector.setAttribute("keystoreFile", absoluteKeystoreFile);
            connector.setAttribute("keystorePass", env.getProperty("keystore.password"));
            connector.setAttribute("keystoreType", env.getProperty("keystore.type"));
            connector.setAttribute("keyAlias", env.getProperty("keystore.alias")  );
            connector.setAttribute("clientAuth", "false");
            connector.setAttribute("sslProtocol", "TLS");
            connector.setAttribute("SSLEnabled", true);
        } 
    }

    public class ESCC implements EmbeddedServletContainerCustomizer{
        Environment env;

        public ESCC(Environment env){ 
            this.env=env;  
        }

        public void customize(ConfigurableEmbeddedServletContainer container){
            TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;            
            TomcatConnectorCustomizer tcc = new TCC(env);
            containerFactory.addConnectorCustomizers(tcc);
        }
    }

    @Bean(name="containerCustomizer")
    public EmbeddedServletContainerCustomizer containerCustomizer() 
    throws FileNotFoundException {
        logger.info("Creating containerCustomizer");
        EmbeddedServletContainerCustomizer escc = new ESCC(env);
        return escc;
    }
//---

//---- rabbit

//import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
    @Bean(name="cachingConnectionFactory")
    CachingConnectionFactory createCachingConnectionFactory(){
        logger.info("Creating cachingConnectionFactory");
        String uri = env.getProperty("rabbitmq.uri");
        URI rabbitmqUri=null;
        
        try{
            rabbitmqUri = new URI(uri);
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
        
        CachingConnectionFactory ret = new CachingConnectionFactory(rabbitmqUri);
        logger.info(String.format("Created cachingConnectionFactory with hashCode %d" , ret.hashCode() ) );
        return ret;
    }
    
    @Bean(name="myQueue")
    Queue createMyQueue() {
        logger.info("Creating myQueue");
        return new Queue("myQueue", false);
    }

    @Bean(name="topicExchange")
    TopicExchange createTopicExchange() {
        logger.info("Creating topicExchange");
        return new TopicExchange("topicExchange");
    }

    @Bean(name="bindingQueue")
    Binding binding(@Qualifier("myQueue")Queue queue, @Qualifier("topicExchange")TopicExchange exchange) {
        logger.info("Creating bindingQueue");
        return BindingBuilder.bind(queue).to(exchange).with(queue.getName());
    }

    @Bean(name="workQueueContainer")
    SimpleMessageListenerContainer createWorkQueueContainer(ConnectionFactory connectionFactory, @Autowired @Qualifier("listenerAdapter") MessageListenerAdapter listenerAdapter,@Qualifier("myQueue") Queue queue) {
        logger.info("Creating createWorkQueueContainer for work queue");
        logger.info(String.format("Using ConnectionFactory with hashCode %d" , connectionFactory.hashCode() ) );
        
        SimpleMessageListenerContainer smlc = new SimpleMessageListenerContainer();
        smlc.setConnectionFactory(connectionFactory);
        smlc.setQueueNames(queue.getName() );
        smlc.setMessageListener(listenerAdapter);
        return smlc;
    }
    
    @Bean(name="listenerAdapter")    
    MessageListenerAdapter listenerAdapter(@Autowired @Qualifier("messageHandler")MessageHandler messageHandler) {
        logger.info("Creating listenerAdapter");
        return new MessageListenerAdapter(messageHandler);
    }

    @Bean(name="messageHandler")
    MessageHandler createMessageHandler() {
        logger.info("Creating messageHandler");
        return new MessageHandler();
    }
    
    //--------    
    @Bean(name="fanoutExchange")
    FanoutExchange createFanoutExchange() {
        logger.info("Creating fanoutExchange");
        return new FanoutExchange("fanoutExchange");
    }

    @Bean(name="anonymousQueue1")
    AnonymousQueue createAnonymousQueue1() {
        logger.info("Creating anonQueue1");
        return new AnonymousQueue();
    }

    @Bean(name="bindingTopic")
    Binding bindingTopic(@Qualifier("anonymousQueue1")AnonymousQueue queue, @Qualifier("fanoutExchange")FanoutExchange exchange) {
        logger.info("Creating bindingTopic");
        return BindingBuilder.bind(queue).to(exchange);
    }

    @Bean(name="broadcastMessageHandler")
    BroadcastMessageHandler createBroadcastMessageHandler() {
        logger.info("Creating broadcastMessageHandlermessageHandler");
        return new BroadcastMessageHandler();
    }
    
    @Bean(name="broadcastListenerAdapter")    
    MessageListenerAdapter createBroadcastlistenerAdapter(@Autowired @Qualifier("broadcastMessageHandler")BroadcastMessageHandler broadcastMessageHandler) {
        logger.info("Creating broadcastListenerAdapter");
        return new MessageListenerAdapter(broadcastMessageHandler);
    }

    @Bean(name="topicContainer")
    SimpleMessageListenerContainer createTopicContainer(ConnectionFactory connectionFactory, @Autowired @Qualifier("broadcastListenerAdapter") MessageListenerAdapter listenerAdapter, @Qualifier("anonymousQueue1")  AnonymousQueue anonQueue) {
        logger.info("Creating container for topic");
        logger.info(String.format("Using ConnectionFactory with hashCode %d" , connectionFactory.hashCode() ) );
        
        SimpleMessageListenerContainer smlc = new SimpleMessageListenerContainer();
        smlc.setConnectionFactory(connectionFactory);
        smlc.setQueueNames( anonQueue.getName() );
        smlc.setMessageListener(listenerAdapter);
        return smlc;
    }
    
    //----
//---- rabbit
}

persistence.xml

<persistence>
    <persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
        <jta-data-source>basicDataSource</jta-data-source>
        <properties>
            <!-- <property name="hibernate.hbm2ddl.auto" value="create-drop" /> -->
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.show_sql" value="false" />
        </properties>
    </persistence-unit>
</persistence>

greeting.html

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

test.sql

--JDBC URL: jdbc:mariadb://localhost:3306/springmvchtml
--mysql -u root -p
create database springmvchtml;
create user 'usertest'@'%' identified by '????';
create user 'usertest'@'localhost' identified by '????';
grant all on springmvchtml.* to 'usertest'@'%';
grant all on springmvchtml.* to 'usertest'@'localhost';
show grants for 'usertest'@'%';
show grants for 'usertest'@'localhost'; 
create table springmvchtml.dummy (name varchar(255) ) ;
insert into springmvchtml.dummy (name) values('aaaa');
insert into springmvchtml.dummy (name) values('bbbb');
commit;
-- mysql -u usertest -p
  • MoinMoin Powered
  • Python Powered
  • GPL licensed
  • Valid HTML 4.01