Size: 3893
Comment:
|
Size: 71863
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 2: | Line 2: |
<<TableOfContents(2)>> == Common properties for spring boot == * https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html {{{#!highlight sh # disable web container/server spring.main.web-environment=false spring.jmx.enabled=false #spring.main.banner-mode=off spring.main.banner-mode=console spring.banner.location=classpath:banner.txt }}} |
|
Line 6: | Line 19: |
{{{ | {{{#!highlight xml |
Line 69: | Line 82: |
{{{ | {{{#!highlight java |
Line 96: | Line 109: |
// http://localhost:8080/greeting?name=nnnn | |
Line 104: | Line 118: |
// http://localhost:8080/dummy | |
Line 121: | Line 136: |
// http://localhost:8080/dummyname | |
Line 128: | Line 144: |
=== src/main/java/hello/Application.java === {{{#!highlight 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; @ComponentScan @EnableAutoConfiguration public class Application { 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(); bds.setDriverClassName("org.mariadb.jdbc.Driver"); bds.setUrl("jdbc:mariadb://localhost:3306/springmvchtml"); bds.setUsername("usertest"); bds.setPassword("usertest"); bds.setInitialSize(3); return bds; } /* @Bean(name="jdbcTemplate") public JdbcTemplate jdbcTemplate(){ logger.info("Creating jdbcTemplate"); return new JdbcTemplate( basicDataSource() ); } */ @Bean(name="jdbcTemplate") public JdbcTemplate createJdbcTemplate(@Autowired @Qualifier("basicDataSource") BasicDataSource bds ){ logger.info("Creating jdbcTemplate"); return new JdbcTemplate( bds ); } } }}} === src/main/java/hello/ThreadTimer.java === {{{#!highlight 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; //@Autowired //WaitThread waitThread; 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(); } } }}} === src/main/java/hello/WaitThread.java === {{{#!highlight 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(); } } }}} === src/main/java/hello/Dummy.java === {{{#!highlight 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; } } }}} === src/main/java/hello/DummyDAO.java === {{{#!highlight 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; @Component public class DummyDAO { @Autowired @Qualifier("jdbcTemplate") private JdbcTemplate jdbcTemplate; private Logger logger; 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); } } }}} === src/main/resources/templates/greeting.html === {{{#!highlight 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> }}} === src/main/resources/application.properties === {{{#!highlight sh logging.file=/tmp/testout.log }}} === src/main/resources/logback-spring.xml === {{{#!highlight xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/> <include resource="org/springframework/boot/logging/logback/file-appender.xml" /> --> <!-- override spring logback default behaviour --> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${filelog}</file> <encoder> <pattern>%date{ISO8601} [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="GREETFILE" class="ch.qos.logback.core.FileAppender"> <file>/tmp/greet.log</file> <encoder> <pattern>%date{ISO8601} [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%yellow(%date{ISO8601}) %green([%thread]) %highlight(%-5level) %cyan(%logger{35}) - %white(%msg%n) </Pattern> </layout> </appender> <root level="INFO"> <appender-ref ref="FILE" /> <appender-ref ref="CONSOLE"/> </root> <logger name="hello.GreetingController" level="debug" additivity="false"> <appender-ref ref="GREETFILE"/> <appender-ref ref="CONSOLE" /> </logger> </configuration> }}} === src/main/resources/test.sql === {{{#!highlight 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 }}} === JAR files list === {{{#!highlight sh 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 {{{#!highlight sh #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 {{{#!highlight java // 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 {{{#!highlight 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 }}} {{{#!highlight java import javax.annotation.Resource; import org.springframework.core.env.Environment; import org.springframework.beans.factory.annotation.Value; //.................... @Resource Environment env; @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; } //.................... }}} Override value in application.properties {{{#!highlight sh java -jar target/test-spring-boot-0.1.0.jar --foo.bar=snafu }}} It's also possible to override values with environment variables as for example * FOO_BAR=snafu java -jar target/test-spring-boot-0.1.0.jar The *.* should be replaced by *_* and the lowercase characters must be capitalized. Instead of using @Autowired or @Inject use @Resource (javax.annotation.Resource). == Example JPA RabbitMQ HttpSession Redis == Structure {{{ . ./pom.xml ./src ./src/main ./src/main/java ./src/main/java/hello ./src/main/java/hello/GreetingController.java ./src/main/java/hello/Application.java ./src/main/java/hello/ThreadTimer.java ./src/main/java/hello/WaitThread.java ./src/main/java/hello/Dummy.java ./src/main/java/hello/DummyDAO.java ./src/main/java/hello/DummyJPA.java ./src/main/java/hello/MessageHandler.java ./src/main/java/hello/BroadcastMessageHandler.java ./src/main/java/hello/ConfigHttpSession.java ./src/main/resources ./src/main/resources/templates ./src/main/resources/templates/greeting.html ./src/main/resources/application.properties ./src/main/resources/logback-spring.xml ./src/main/resources/test.sql ./src/main/resources/META-INF ./src/main/resources/META-INF/persistence.xml }}} WaitThread.java {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 {{{#!highlight 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 }}} logback-spring.xml {{{#!highlight xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <!-- <include resource="org/springframework/boot/logging/logback/defaults.xml" /> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}spring.log}"/> <include resource="org/springframework/boot/logging/logback/file-appender.xml" /> --> <!-- override spring logback default behaviour --> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>${filelog}</file> <encoder> <pattern>%date{ISO8601} [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="GREETFILE" class="ch.qos.logback.core.FileAppender"> <file>/tmp/greet.log</file> <encoder> <pattern>%date{ISO8601} [%thread] %-5level %logger{35} - %msg%n</pattern> </encoder> </appender> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <Pattern>%yellow(%date{ISO8601}) %green([%thread]) %highlight(%-5level) %cyan(%logger{35}) - %white(%msg%n) </Pattern> </layout> </appender> <root level="INFO"> <appender-ref ref="FILE" /> <appender-ref ref="CONSOLE"/> </root> <logger name="hello.GreetingController" level="debug" additivity="false"> <appender-ref ref="GREETFILE"/> <appender-ref ref="CONSOLE" /> </logger> </configuration> }}} application.properties {{{ logging.file=/tmp/testout.log server.port=8443 foo.bar=bohica instance.name=node1 keystore.file=springboot.p12 keystore.password=???? keystore.type=PKCS12 keystore.alias=springboot db.driverclass=org.mariadb.jdbc.Driver db.jdbcurl=jdbc:mariadb://localhost:3306/springmvchtml db.username=usertest db.password=???? db.initialsizeconnpool=3 #rabbimq parameters rabbitmq.uri=amqp://????:????@localhost:5672 #redis spring.redis.host=localhost spring.redis.password=???????? spring.redis.port=6379 }}} pom.xml {{{#!highlight xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>hello</groupId> <artifactId>test-spring-boot</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.0.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.mariadb.jdbc</groupId> <artifactId>mariadb-java-client</artifactId> <version>1.4.4</version> </dependency> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency> <!-- http session redis --> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> <version>1.2.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- http session redis --> </dependencies> <properties> <start-class>hello.Application</start-class> </properties> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestone</id> <url>http://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestone</id> <url>http://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project> }}} Libs {{{#!highlight sh -rw-r--r-- 1 vitor vitor 37M Sep 29 15:49 test-spring-boot-0.1.0.jar jar tf test-spring-boot-0.1.0.jar | grep BOOT | grep jar BOOT-INF/lib/spring-session-1.2.2.RELEASE.jar BOOT-INF/lib/spring-boot-starter-data-redis-1.4.0.RELEASE.jar BOOT-INF/lib/jackson-core-2.8.1.jar BOOT-INF/lib/javassist-3.20.0-GA.jar BOOT-INF/lib/jul-to-slf4j-1.7.21.jar BOOT-INF/lib/groovy-2.4.7.jar BOOT-INF/lib/spring-amqp-1.6.1.RELEASE.jar BOOT-INF/lib/hibernate-validator-5.2.4.Final.jar BOOT-INF/lib/classmate-1.3.1.jar BOOT-INF/lib/hibernate-commons-annotations-5.0.1.Final.jar BOOT-INF/lib/tomcat-embed-el-8.5.4.jar BOOT-INF/lib/jedis-2.8.2.jar BOOT-INF/lib/httpcore-4.4.5.jar BOOT-INF/lib/antlr-2.7.7.jar BOOT-INF/lib/xml-apis-1.4.01.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/http-client-1.0.0.RELEASE.jar BOOT-INF/lib/httpclient-4.5.2.jar BOOT-INF/lib/spring-boot-starter-logging-1.4.0.RELEASE.jar BOOT-INF/lib/tomcat-jdbc-8.5.4.jar BOOT-INF/lib/spring-beans-4.3.2.RELEASE.jar BOOT-INF/lib/spring-jdbc-4.3.2.RELEASE.jar BOOT-INF/lib/spring-boot-starter-jdbc-1.4.0.RELEASE.jar BOOT-INF/lib/spring-boot-starter-amqp-1.4.0.RELEASE.jar BOOT-INF/lib/spring-aspects-4.3.2.RELEASE.jar BOOT-INF/lib/commons-dbcp-1.4.jar BOOT-INF/lib/spring-data-commons-1.12.2.RELEASE.jar BOOT-INF/lib/spring-context-support-4.3.2.RELEASE.jar BOOT-INF/lib/spring-data-keyvalue-1.1.2.RELEASE.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/commons-logging-1.2.jar BOOT-INF/lib/spring-tx-4.3.2.RELEASE.jar BOOT-INF/lib/validation-api-1.1.0.Final.jar BOOT-INF/lib/spring-core-4.3.2.RELEASE.jar BOOT-INF/lib/spring-boot-starter-aop-1.4.0.RELEASE.jar BOOT-INF/lib/spring-data-jpa-1.10.2.RELEASE.jar BOOT-INF/lib/commons-pool2-2.4.2.jar BOOT-INF/lib/dom4j-1.6.1.jar BOOT-INF/lib/tomcat-juli-8.5.4.jar BOOT-INF/lib/jcl-over-slf4j-1.7.21.jar BOOT-INF/lib/log4j-over-slf4j-1.7.21.jar BOOT-INF/lib/aspectjweaver-1.8.9.jar BOOT-INF/lib/spring-data-redis-1.7.2.RELEASE.jar BOOT-INF/lib/spring-web-4.3.2.RELEASE.jar BOOT-INF/lib/unbescape-1.1.0.RELEASE.jar BOOT-INF/lib/mariadb-java-client-1.4.4.jar BOOT-INF/lib/amqp-client-3.6.3.jar BOOT-INF/lib/spring-oxm-4.3.2.RELEASE.jar BOOT-INF/lib/tomcat-embed-core-8.5.4.jar BOOT-INF/lib/spring-orm-4.3.2.RELEASE.jar BOOT-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar BOOT-INF/lib/commons-pool-1.6.jar BOOT-INF/lib/thymeleaf-spring4-2.1.5.RELEASE.jar BOOT-INF/lib/hibernate-core-5.0.9.Final.jar BOOT-INF/lib/spring-context-4.3.2.RELEASE.jar BOOT-INF/lib/thymeleaf-2.1.5.RELEASE.jar BOOT-INF/lib/commons-codec-1.10.jar BOOT-INF/lib/spring-boot-starter-web-1.4.0.RELEASE.jar BOOT-INF/lib/spring-webmvc-4.3.2.RELEASE.jar BOOT-INF/lib/slf4j-api-1.7.21.jar BOOT-INF/lib/javax.inject-1.jar BOOT-INF/lib/jackson-annotations-2.8.1.jar BOOT-INF/lib/jandex-2.0.0.Final.jar BOOT-INF/lib/spring-messaging-4.3.2.RELEASE.jar BOOT-INF/lib/ognl-3.0.8.jar BOOT-INF/lib/hibernate-entitymanager-5.0.9.Final.jar BOOT-INF/lib/spring-boot-starter-thymeleaf-1.4.0.RELEASE.jar BOOT-INF/lib/spring-retry-1.1.3.RELEASE.jar BOOT-INF/lib/javax.transaction-api-1.2.jar BOOT-INF/lib/logback-classic-1.1.7.jar BOOT-INF/lib/spring-boot-starter-data-jpa-1.4.0.RELEASE.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/jackson-databind-2.8.1.jar BOOT-INF/lib/spring-rabbit-1.6.1.RELEASE.jar BOOT-INF/lib/spring-aop-4.3.2.RELEASE.jar BOOT-INF/lib/jboss-logging-3.3.0.Final.jar }}} == springTestApp == === pom.xml === {{{#!highlight xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.allowed.bitarus</groupId> <artifactId>springTestApp</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.2.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <properties> <start-class>org.allowed.bitarus.springTestApp.Application</start-class> </properties> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-releases</id> <url>http://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-releases</id> <url>http://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project> }}} === src/main/java/org/allowed/bitarus/springTestApp/Application.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import java.util.concurrent.Future; import java.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @ComponentScan @EnableAutoConfiguration @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean(name="tasksFutures") public ArrayList<Future<Integer>> createTasksFutures(){ System.out.println("Creating tasksFutures"); return new ArrayList<Future<Integer>>(); } @Bean(name="executors") public ExecutorService createExecutors(){ return Executors.newFixedThreadPool(5); } } }}} === src/main/java/org/allowed/bitarus/springTestApp/Tasker.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import org.springframework.stereotype.Component; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @Component("tasker") public class Tasker { private ExecutorService _es; public Tasker(@Qualifier("executors") ExecutorService es){ System.out.println("Created Tasker !!!!"); _es = es; } public Future<Integer> addTask(TaskX taskx){ Future<Integer> f = _es.submit( taskx ); return f; } } }}} === src/main/java/org/allowed/bitarus/springTestApp/Receiver.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import org.springframework.stereotype.Component; import java.util.concurrent.Future; import java.util.ArrayList; import org.springframework.beans.factory.annotation.Qualifier; import javax.annotation.PostConstruct; @Component public class Receiver { private Tasker _t; private ArrayList<Future<Integer>> _tasks; public Receiver(@Qualifier("tasker")Tasker t, @Qualifier("tasksFutures") ArrayList<Future<Integer>> tasks ){ System.out.println("Created receiver !!!!"); _t = t; _tasks = tasks; // wait for all tasks ... /* boolean loop=true; while(loop){ boolean allDone=true; for(Future<Integer> f : tasks){ if(f.isDone()==false){ allDone=false; } } if(allDone){ loop=false; } try{ Thread.sleep(1000); } catch(Exception ex){ } } for(Future<Integer> f : tasks){ try{ Integer res = f.get(); System.out.println(res); } catch(Exception ex){ } } */ } @PostConstruct public void init(){ System.out.println("Init post construct"); for(int i=0;i<10;i++){ _tasks.add( _t.addTask( new TaskX(5,6) ) ); } } } }}} === TaskX.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import java.util.concurrent.Callable; public class TaskX implements Callable<Integer>{ private int _x; private int _y; public TaskX(int x,int y){ _x=x; _y=y; } public Integer call() { try { Thread.sleep(5000); } catch(Exception ex){ } int sum = _x+_y; System.out.println("TID:"+Thread.currentThread().getId() + " sumVal:" + sum ); return sum; } } }}} == Example with MongoDB == Think about using '''spring.data.mongodb.uri'''. === pom.xml === {{{#!highlight xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.allowed.bitarus</groupId> <artifactId>springTestApp</artifactId> <version>0.1.0</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.2.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.9.6.RELEASE</version> </dependency> </dependencies> <properties> <start-class>org.allowed.bitarus.springTestApp.Application</start-class> </properties> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-releases</id> <url>http://repo.spring.io/libs-release</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-releases</id> <url>http://repo.spring.io/libs-release</url> </pluginRepository> </pluginRepositories> </project> }}} === src/main/resources/application.properties === {{{#!highlight bash # disable web container/server spring.main.web-environment=false threadpool.nrExecutors=5 mongox.host=127.0.0.1 mongox.port=27017 mongox.database=mydatabase }}} === src/main/java/org/allowed/bitarus/springTestApp/Application.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import java.util.concurrent.Future; import java.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.mongodb.core.MongoTemplate; import com.mongodb.Mongo; import org.springframework.core.env.Environment; import javax.annotation.Resource; @ComponentScan @EnableAutoConfiguration @SpringBootApplication @EnableMongoRepositories // search for MongoDB reps public class Application { @Resource Environment _env; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean(name="tasksFutures") public ArrayList<Future<Integer>> createTasksFutures(){ System.out.println("Creating tasksFutures"); return new ArrayList<Future<Integer>>(); } @Bean(name="executors") public ExecutorService createExecutors(){ System.out.println("Creating executors"); System.out.println(_env.getProperty("threadpool.nrExecutors")); return Executors.newFixedThreadPool(5); } @Bean(name="mongoTemplate") public MongoTemplate mongoTemplate() throws Exception { System.out.println("Creating mongoTemplate"); System.out.println(_env.getProperty("mongox.host")); System.out.println(_env.getProperty("mongox.port")); System.out.println(_env.getProperty("mongox.database")); Mongo mongo = new Mongo( _env.getProperty("mongox.host"), Integer.parseInt(_env.getProperty("mongox.port") ) ); return new MongoTemplate(mongo, _env.getProperty("mongox.database") ); } } }}} === src/main/java/org/allowed/bitarus/springTestApp/Tasker.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import org.springframework.stereotype.Component; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @Component("tasker") public class Tasker { private ExecutorService _es; public Tasker(@Qualifier("executors") ExecutorService es){ System.out.println("Created Tasker !!!!"); _es = es; } public Future<Integer> addTask(TaskX taskx){ Future<Integer> f = _es.submit( taskx ); return f; } } }}} === src/main/java/org/allowed/bitarus/springTestApp/Result.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import org.springframework.data.annotation.Id; public class Result { @Id private String id; private int sumResult; public Result(){} public int getSumResult(){return this.sumResult;} public void setSumResult(int sumResult){this.sumResult=sumResult;} public String getId(){return this.id;} public void setId(String id){this.id=id;} } }}} === src/main/java/org/allowed/bitarus/springTestApp/Receiver.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import org.springframework.stereotype.Component; import java.util.concurrent.Future; import java.util.ArrayList; import java.util.List; import org.springframework.beans.factory.annotation.Qualifier; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.MongoTemplate; @Component public class Receiver { private Tasker _t; private ArrayList<Future<Integer>> _tasks; private ResultRepository _repository; public Receiver(@Qualifier("tasker")Tasker t, @Qualifier("tasksFutures") ArrayList<Future<Integer>> tasks, ResultRepository repository ){ System.out.println("Created receiver !!!!"); _t = t; _tasks = tasks; _repository = repository; } @Autowired private MongoTemplate mongoTemplate; @PostConstruct public void init(){ System.out.println("Init post construct"); for(int i=0;i<10;i++){ _tasks.add( _t.addTask( new TaskX(5,6) ) ); } // wait for all tasks ... boolean loop=true; while(loop){ boolean allDone=true; for(Future<Integer> f : _tasks){ if(f.isDone()==false){ allDone=false; } } if(allDone){ loop=false; } try{ Thread.sleep(1000); } catch(Exception ex){ } } for(Future<Integer> f : _tasks){ try{ Integer res = f.get(); System.out.println(res); Result r = new Result(); r.setSumResult(res); _repository.save(r); } catch(Exception ex){ } } System.out.println( _repository.count() ); List<Result> res = _repository.findBySumResult(11); for(Result r : res){ r.setSumResult((int)System.currentTimeMillis()); _repository.save(r); } System.out.println("mongoTemplateCount " + mongoTemplate.count(new Query() ,Result.class) ); } } }}} === src/main/java/org/allowed/bitarus/springTestApp/ResultRepository.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import java.util.List; import org.springframework.data.mongodb.repository.MongoRepository; /* Result -> class to store String -> id in collection type Collection result in database mydatabase { "_id" : ObjectId("58828e2822e1a609d96a5e52"), "_class" : "org.allowed.bitarus.springTestApp.Result", "sumResult" : 11 } */ public interface ResultRepository extends MongoRepository<Result, String> { public List<Result> findBySumResult(int sumResult); } }}} === src/main/java/org/allowed/bitarus/springTestApp/TaskX.java === {{{#!highlight java package org.allowed.bitarus.springTestApp; import java.util.concurrent.Callable; public class TaskX implements Callable<Integer>{ private int _x; private int _y; public TaskX(int x,int y){ _x=x; _y=y; } public Integer call() { try { Thread.sleep(5000); } catch(Exception ex){ } int sum = _x+_y; System.out.println("TID:"+Thread.currentThread().getId() + " sumVal:" + sum ); return sum; } } }}} == Integration tests == Integration tests setup and start Spring context before running the tests. {{{#!highlight java // <groupId>org.springframework.boot</groupId> // <artifactId>spring-boot-starter-test</artifactId> @Test // test case @RunWith(SpringRunner.class) @MockBean // inject mocked beans // Mockito, given , willReturn Mocks simulates real objects @SpyBean // create proxy for a real object @SpringBootTest // test application context @ActiveProfiles("test") // use application properties for test profile @WebFluxTest // web flux controllers tests @WebMvcTest // web tests // application-<profile>.properties // application-<profile>.yml application-test.properties application-test.yml // Utility class for working with the reflection API and handling reflection exceptions. // allows changes to be made on member variables autowired or with value annotation ReflectionUtils }}} == JPARepository == * https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html Captures the domain type to manage as well as the domain type's id type. * https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/stereotype/Repository.html Mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects. Specialization of @Component. {{{#!highlight java import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public Repo implements JpaRepository<EntityX,Long>{ } }}} == ConfigurationProperties == * https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/context/properties/ConfigurationProperties.html * Annotation for externalized configuration. {{{#!highlight sh @ConfigurationProperties(prefix = "server") public class ServerProperties { private Map<String, String> app; private Map<String, List<String>> config; }}} |
SpringBoot
Contents
Common properties for spring boot
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
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
1 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
1 #create keystore with key springboot
2 keytool -genkey -alias springboot -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore springboot.p12 -validity 3650
3
4 #Enter keystore password: 12345678
5 #Re-enter new password: 12345678
6 #What is your first and last name?
7 # [Unknown]: Spring Boot
8 #What is the name of your organizational unit?
9 # [Unknown]: Boot
10 #What is the name of your organization?
11 # [Unknown]: Boot
12 #What is the name of your City or Locality?
13 # [Unknown]: Lisbon
14 #What is the name of your State or Province?
15 # [Unknown]: Estremadura
16 #What is the two-letter country code for this unit?
17 # [Unknown]: PT
18 #Is CN=Spring Boot, OU=Boot, O=Boot, L=Lisbon, ST=Estremadura, C=PT correct?
19 # [no]: yes
20
21 #list keys
22 keytool -list -v -keystore springboot.p12 -storetype pkcs12
Code to add in Application class/configuration
1 // import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
2 // import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
3 // import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
4 // import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
5 // import java.io.FileNotFoundException;
6 // import org.apache.catalina.connector.Connector;
7 // import org.springframework.beans.factory.annotation.Value;
8 // import javax.inject.Inject;
9 // import org.springframework.util.ResourceUtils;
10
11 public class TCC implements TomcatConnectorCustomizer{
12 private String keystoreFile;
13 private String keystorePassword;
14 private String keystoreType;
15 private String keystoreAlias;
16
17 public TCC(String keystoreFile, String keystorePassword, String keystoreType, String keystoreAlias){
18 this.keystoreFile=keystoreFile;
19 this.keystorePassword=keystorePassword;
20 this.keystoreType=keystoreType;
21 this.keystoreAlias=keystoreAlias;
22 }
23
24 public void customize(Connector connector){
25 connector.setSecure(true);
26 connector.setScheme("https");
27 connector.setAttribute("keystoreFile", keystoreFile);
28 connector.setAttribute("keystorePass", keystorePassword);
29 connector.setAttribute("keystoreType", keystoreType);
30 connector.setAttribute("keyAlias", keystoreAlias);
31 connector.setAttribute("clientAuth", "false");
32 connector.setAttribute("sslProtocol", "TLS");
33 connector.setAttribute("SSLEnabled", true);
34 }
35 }
36
37 public class ESCC implements EmbeddedServletContainerCustomizer{
38 private String keystoreFile;
39 private String keystorePassword;
40 private String keystoreType;
41 private String keystoreAlias;
42
43 public ESCC(String keystoreFile, String keystorePassword, String keystoreType, String keystoreAlias){
44 this.keystoreFile=keystoreFile;
45 this.keystorePassword=keystorePassword;
46 this.keystoreType=keystoreType;
47 this.keystoreAlias=keystoreAlias;
48 }
49
50 public void customize(ConfigurableEmbeddedServletContainer container){
51 TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;
52
53 TomcatConnectorCustomizer tcc = new TCC(keystoreFile,keystorePassword,keystoreType,keystoreAlias);
54 containerFactory.addConnectorCustomizers(tcc);
55 }
56 }
57
58 @Bean
59 @Inject
60 public EmbeddedServletContainerCustomizer containerCustomizer(
61 @Value("${keystore.file}") String keystoreFile,
62 @Value("${keystore.password}") String keystorePassword,
63 @Value("${keystore.type}") String keystoreType,
64 @Value("${keystore.alias}") String keystoreAlias) throws FileNotFoundException
65 {
66 final String absoluteKeystoreFile = ResourceUtils.getFile(keystoreFile).getAbsolutePath();
67 EmbeddedServletContainerCustomizer escc = new ESCC(absoluteKeystoreFile,keystorePassword,keystoreType,keystoreAlias);
68 return escc;
69 }
pom.xml
- 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
Environment variables
src/main/resources/application.properties
logging.file=/tmp/testout.log server.port=8443 foo.bar=bohica
1 import javax.annotation.Resource;
2 import org.springframework.core.env.Environment;
3 import org.springframework.beans.factory.annotation.Value;
4 //....................
5 @Resource
6 Environment env;
7 @Value("${foo.bar}")
8 private String fooBar;
9
10 @RequestMapping(value="/env",produces="application/json")
11 @ResponseBody
12 public List<String> getEnv(){
13 List<String> ret = new ArrayList<String>();
14 ret.add( env.getProperty("foo.bar") );
15 ret.add(fooBar);
16 return ret;
17 }
18 //....................
19
Override value in application.properties
1 java -jar target/test-spring-boot-0.1.0.jar --foo.bar=snafu
It's also possible to override values with environment variables as for example
- FOO_BAR=snafu java -jar target/test-spring-boot-0.1.0.jar
The *.* should be replaced by *_* and the lowercase characters must be capitalized.
Instead of using @Autowired or @Inject use @Resource (javax.annotation.Resource).
Example JPA RabbitMQ HttpSession Redis
Structure
. ./pom.xml ./src ./src/main ./src/main/java ./src/main/java/hello ./src/main/java/hello/GreetingController.java ./src/main/java/hello/Application.java ./src/main/java/hello/ThreadTimer.java ./src/main/java/hello/WaitThread.java ./src/main/java/hello/Dummy.java ./src/main/java/hello/DummyDAO.java ./src/main/java/hello/DummyJPA.java ./src/main/java/hello/MessageHandler.java ./src/main/java/hello/BroadcastMessageHandler.java ./src/main/java/hello/ConfigHttpSession.java ./src/main/resources ./src/main/resources/templates ./src/main/resources/templates/greeting.html ./src/main/resources/application.properties ./src/main/resources/logback-spring.xml ./src/main/resources/test.sql ./src/main/resources/META-INF ./src/main/resources/META-INF/persistence.xml
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 }
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 public ThreadTimer() {
20 this.logger = LoggerFactory.getLogger(ThreadTimer.class);
21 logger.info("Created instance of " + this.getClass().getSimpleName());
22 this.running = true;
23 this.delaySeconds = 5 * 1000;
24 this.setName(this.getClass().getSimpleName() + "_" + this.getName());
25 this.subscribers = new ArrayList<Object>();
26 }
27
28 public void addSubscriber(Object subscriber){
29 this.subscribers.add(subscriber);
30 }
31
32 @PostConstruct
33 public void init() {
34 logger.info("Starting the thread");
35 this.start();
36 }
37
38 @Override
39 public void run() {
40 while (running) {
41 try {
42 Thread.sleep(this.delaySeconds);
43 logger.info("Delay " + this.getClass().getSimpleName());
44
45 for(Object o: this.subscribers){
46 synchronized(o){
47 o.notify();
48 }
49 }
50 }
51 catch (InterruptedException e) {
52 logger.info("ThreadTimer interrupted exception:" + e.getMessage() );
53 }
54 catch (Exception e) {
55 e.printStackTrace();
56 logger.info("ThreadTimer exception:" + e.getMessage() );
57 stopRunning();
58 }
59 }
60 logger.info("Exited " + this.getClass().getSimpleName());
61 }
62
63 public void startRunning() {
64 this.running = true;
65 }
66
67 public void stopRunning() {
68 this.running = false;
69 }
70
71 public void destroy(){
72 logger.info("Called destroy");
73 this.stopRunning();
74 this.interrupt();
75 }
76 }
MessageHandler.java
1 package hello;
2
3 import java.nio.charset.StandardCharsets;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6
7 public class MessageHandler{
8 private final Logger logger = LoggerFactory.getLogger(MessageHandler.class);
9
10 public void handleMessage(byte[] message){
11 String msg = new String(message, StandardCharsets.UTF_8);
12 logger.info("Received msg " + msg );
13 }
14
15 public void handleMessage(String message){
16 logger.info("Received msg " + message );
17 }
18
19 }
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 import org.springframework.web.bind.annotation.PathVariable;
16 //import javax.inject.Inject;
17 import org.springframework.core.env.Environment;
18 import org.springframework.beans.factory.annotation.Value;
19 import javax.annotation.Resource;
20
21 import org.springframework.amqp.rabbit.core.RabbitTemplate;
22 import javax.servlet.http.HttpSession;
23
24 @Controller
25 public class GreetingController {
26 private final Logger logger = LoggerFactory.getLogger(GreetingController.class);
27 @Resource
28 DummyDAO dummyDAO;
29
30 @Resource
31 Environment env;
32
33 @Resource
34 RabbitTemplate rabbitTemplate;
35
36 @Value("${instance.name}")
37 String instanceName;
38
39 public GreetingController(){
40 logger.debug("Greeting controller created.");
41 }
42
43 @RequestMapping("/greeting")
44 public String greeting(@RequestParam(value="name", required=false, defaultValue="World") String name, Model model ) {
45 model.addAttribute("name", name);
46 rabbitTemplate.convertAndSend("topicExchange","myQueue", name );
47 rabbitTemplate.convertAndSend("fanoutExchange","", name );
48 return "greeting";
49 }
50
51 @RequestMapping("/setvalue/{value}")
52 @ResponseBody
53 public String setValue(@PathVariable("value") String value, Model model,HttpSession httpSession) {
54 httpSession.setAttribute("name", value );
55 return httpSession.getId();
56 }
57
58 @RequestMapping("/getvalue")
59 @ResponseBody
60 public String setValue(Model model,HttpSession httpSession) {
61 return (String) httpSession.getAttribute("name");
62 }
63
64 @RequestMapping("/instancename")
65 @ResponseBody
66 public String setValue(Model model) {
67 return this.instanceName;
68 }
69
70 @RequestMapping("/greeting/add/{name}")
71 public String addGreeting(@PathVariable("name") String name, Model model) {
72 model.addAttribute("name", name);
73 dummyDAO.addName(name);
74 return "greeting";
75 }
76
77 @RequestMapping(value="/dummy",produces="application/json")
78 @ResponseBody
79 public List<DummyJPA> dummy(){
80 return dummyDAO.getAllNames();
81 }
82
83 @RequestMapping(value="/dummyname",produces="application/json")
84 @ResponseBody
85 public String getDummyName(){
86 return dummyDAO.getNameFromDummy();
87 }
88
89 @Value("${foo.bar}")
90 private String fooBar;
91
92 @RequestMapping(value="/env",produces="application/json")
93 @ResponseBody
94 public List<String> getEnv(){
95 List<String> ret = new ArrayList<String>();
96 ret.add( env.getProperty("foo.bar") );
97 ret.add(fooBar);
98 return ret;
99 }
100
101 }
DummyJPA.java
1 package hello;
2
3 import javax.persistence.Entity;
4 import javax.persistence.GeneratedValue;
5 import javax.persistence.GenerationType;
6 import javax.persistence.Id;
7 import javax.persistence.NamedQuery;
8 import javax.persistence.NamedQueries;
9
10 @Entity
11 @NamedQueries({
12 @NamedQuery(name="DummyJPA.getAll", query="Select e From DummyJPA e")
13 })
14 public class DummyJPA{
15 @Id
16 @GeneratedValue(strategy=GenerationType.AUTO)
17 private Long id;
18 private String dummy;
19
20 public DummyJPA(){
21 }
22
23 public String getDummy(){
24 return this.dummy;
25 }
26
27 public void setDummy(String dummy){
28 this.dummy=dummy;
29 }
30
31 @Override
32 public String toString(){
33 return String.format("Dummy %s", this.dummy);
34 }
35 }
DummyDAO.java
1 package hello;
2
3 import org.slf4j.Logger;
4 import org.slf4j.LoggerFactory;
5 import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.beans.factory.annotation.Qualifier;
7 import org.springframework.jdbc.core.JdbcTemplate;
8 import org.springframework.stereotype.Component;
9 import javax.persistence.PersistenceContext;
10 import javax.persistence.EntityManager;
11 import javax.persistence.Query;
12 import javax.transaction.Transactional;
13 import java.util.List;
14
15 @Component
16 public class DummyDAO {
17 @Autowired
18 @Qualifier("jdbcTemplate")
19 private JdbcTemplate jdbcTemplate;
20 private Logger logger;
21
22 @PersistenceContext(unitName="default")
23 EntityManager em;
24
25 public DummyDAO() {
26 logger = LoggerFactory.getLogger(DummyDAO.class);
27 logger.info("Created " + this.getClass().getSimpleName());
28 }
29
30 public String getNameFromDummy() {
31 return this.jdbcTemplate.queryForObject("select name from dummy limit 1", String.class);
32 }
33
34 @Transactional
35 public void addName(String name){
36 DummyJPA djpa = new DummyJPA();
37 djpa.setDummy(name);
38 em.persist(djpa);
39 }
40
41 @Transactional
42 public List<DummyJPA> getAllNames(){
43 return em.createNamedQuery("DummyJPA.getAll",DummyJPA.class).getResultList();
44 }
45
46 }
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 }
ConfigHttpSession.java
1 /*
2 http://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot.html
3
4 pkg install redis #freebsd
5 add redis_enable="YES" to /etc/rc.conf
6 /usr/local/etc/rc.d/redis start
7
8 /usr/local/etc/redis.conf
9 requirepass 12345678
10
11 keys *
12 hgetall <hashkey>
13
14 Same as in application.properties spring.redis.password=12345678
15
16 https://localhost:8443/setvalue/valx
17 147569e4-9e6d-4363-a373-b20261513f11
18
19 https://localhost:8443/getvalue
20 SESSION=147569e4-9e6d-4363-a373-b20261513f11
21
22 2 instances of spring boot using the same redis server
23 curl -k -v --cookie "SESSION=147569e4-9e6d-4363-a373-b20261513f11" https://localhost:8443/getvalue
24 curl -k -v --cookie "SESSION=147569e4-9e6d-4363-a373-b20261513f11" https://localhost:8444/getvalue
25 */
26 package hello;
27
28 import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
29
30 @EnableRedisHttpSession
31 public class ConfigHttpSession{
32 // springSessionRepositoryFilterbean is responsible for replacing the HttpSession with a custom implementation that is backed by Spring Session.
33 }
1 package hello;
2
3 import java.nio.charset.StandardCharsets;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6
7 public class BroadcastMessageHandler{
8 private final Logger logger = LoggerFactory.getLogger(BroadcastMessageHandler.class);
9
10 public void handleMessage(byte[] message){
11 String msg = new String(message, StandardCharsets.UTF_8);
12 logger.info("Received msg " + msg );
13 }
14
15 public void handleMessage(String message){
16 logger.info("Received msg " + message );
17 }
18 }
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 import org.apache.commons.dbcp.BasicDataSource;
10 import org.springframework.jdbc.core.JdbcTemplate;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13 import org.springframework.boot.autoconfigure.domain.EntityScan;
14 import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
15 import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
16 import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
17 import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
18 import java.io.FileNotFoundException;
19 import org.apache.catalina.connector.Connector;
20 import org.springframework.beans.factory.annotation.Value;
21 import javax.inject.Inject;
22 import javax.annotation.Resource;
23 import org.springframework.util.ResourceUtils;
24 import org.springframework.core.env.Environment;
25
26 //-- rabbit
27 import org.springframework.amqp.core.Binding;
28 import org.springframework.amqp.core.BindingBuilder;
29 import org.springframework.amqp.core.Queue;
30 import org.springframework.amqp.core.TopicExchange;
31 import org.springframework.amqp.core.FanoutExchange;
32 import org.springframework.amqp.core.AnonymousQueue;
33 import org.springframework.amqp.rabbit.connection.ConnectionFactory;
34 import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
35 import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
36 import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
37 import java.net.URI;
38 //-- rabbit
39
40 @ComponentScan
41 @EnableAutoConfiguration
42 @EntityScan(basePackages="hello")
43 public class Application {
44 @Resource
45 Environment env;
46
47 private static Logger logger;
48
49 public static void main(String[] args) {
50 logger = LoggerFactory.getLogger(Application.class);
51 logger.info("Starting application");
52 SpringApplication.run(Application.class, args);
53 }
54
55 @Bean(name="basicDataSource",destroyMethod="close")
56 public BasicDataSource createBasicDataSource(){
57 logger.info("Creating basicDataSource");
58 BasicDataSource bds = new BasicDataSource();
59 // get config data from application.properties
60 bds.setDriverClassName(env.getProperty("db.driverclass") );
61 bds.setUrl(env.getProperty("db.jdbcurl") );
62 bds.setUsername( env.getProperty("db.username") );
63 bds.setPassword( env.getProperty("db.password") );
64 bds.setInitialSize( Integer.parseInt( env.getProperty("db.initialsizeconnpool")) );
65 return bds;
66 }
67
68 @Bean(name="jdbcTemplate")
69 public JdbcTemplate createJdbcTemplate(@Autowired @Qualifier("basicDataSource") BasicDataSource bds ){
70 logger.info("Creating jdbcTemplate");
71 return new JdbcTemplate( bds );
72 }
73
74 //---
75 public class TCC implements TomcatConnectorCustomizer{
76 Environment env;
77
78 public TCC(Environment env){
79 this.env=env;
80 }
81
82 public void customize(Connector connector){
83 String absoluteKeystoreFile = "";
84 logger.info(String.format("Keystore file: %s" , env.getProperty("keystore.file") ));
85
86 try{
87 absoluteKeystoreFile = ResourceUtils.getFile(env.getProperty("keystore.file")).getAbsolutePath();
88 logger.info(String.format("Absolute path keystore: %s" , absoluteKeystoreFile ) );
89 }
90 catch(Exception ex){
91 logger.error( ex.getMessage() );
92 }
93
94 connector.setSecure(true);
95 connector.setScheme("https");
96 connector.setAttribute("keystoreFile", absoluteKeystoreFile);
97 connector.setAttribute("keystorePass", env.getProperty("keystore.password"));
98 connector.setAttribute("keystoreType", env.getProperty("keystore.type"));
99 connector.setAttribute("keyAlias", env.getProperty("keystore.alias") );
100 connector.setAttribute("clientAuth", "false");
101 connector.setAttribute("sslProtocol", "TLS");
102 connector.setAttribute("SSLEnabled", true);
103 }
104 }
105
106 public class ESCC implements EmbeddedServletContainerCustomizer{
107 Environment env;
108
109 public ESCC(Environment env){
110 this.env=env;
111 }
112
113 public void customize(ConfigurableEmbeddedServletContainer container){
114 TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;
115 TomcatConnectorCustomizer tcc = new TCC(env);
116 containerFactory.addConnectorCustomizers(tcc);
117 }
118 }
119
120 @Bean(name="containerCustomizer")
121 public EmbeddedServletContainerCustomizer containerCustomizer()
122 throws FileNotFoundException {
123 logger.info("Creating containerCustomizer");
124 EmbeddedServletContainerCustomizer escc = new ESCC(env);
125 return escc;
126 }
127 //---
128
129 //---- rabbit
130
131 //import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
132 @Bean(name="cachingConnectionFactory")
133 CachingConnectionFactory createCachingConnectionFactory(){
134 logger.info("Creating cachingConnectionFactory");
135 String uri = env.getProperty("rabbitmq.uri");
136 URI rabbitmqUri=null;
137
138 try{
139 rabbitmqUri = new URI(uri);
140 }
141 catch(Exception ex){
142 ex.printStackTrace();
143 }
144
145 CachingConnectionFactory ret = new CachingConnectionFactory(rabbitmqUri);
146 logger.info(String.format("Created cachingConnectionFactory with hashCode %d" , ret.hashCode() ) );
147 return ret;
148 }
149
150 @Bean(name="myQueue")
151 Queue createMyQueue() {
152 logger.info("Creating myQueue");
153 return new Queue("myQueue", false);
154 }
155
156 @Bean(name="topicExchange")
157 TopicExchange createTopicExchange() {
158 logger.info("Creating topicExchange");
159 return new TopicExchange("topicExchange");
160 }
161
162 @Bean(name="bindingQueue")
163 Binding binding(@Qualifier("myQueue")Queue queue, @Qualifier("topicExchange")TopicExchange exchange) {
164 logger.info("Creating bindingQueue");
165 return BindingBuilder.bind(queue).to(exchange).with(queue.getName());
166 }
167
168 @Bean(name="workQueueContainer")
169 SimpleMessageListenerContainer createWorkQueueContainer(ConnectionFactory connectionFactory, @Autowired @Qualifier("listenerAdapter") MessageListenerAdapter listenerAdapter,@Qualifier("myQueue") Queue queue) {
170 logger.info("Creating createWorkQueueContainer for work queue");
171 logger.info(String.format("Using ConnectionFactory with hashCode %d" , connectionFactory.hashCode() ) );
172
173 SimpleMessageListenerContainer smlc = new SimpleMessageListenerContainer();
174 smlc.setConnectionFactory(connectionFactory);
175 smlc.setQueueNames(queue.getName() );
176 smlc.setMessageListener(listenerAdapter);
177 return smlc;
178 }
179
180 @Bean(name="listenerAdapter")
181 MessageListenerAdapter listenerAdapter(@Autowired @Qualifier("messageHandler")MessageHandler messageHandler) {
182 logger.info("Creating listenerAdapter");
183 return new MessageListenerAdapter(messageHandler);
184 }
185
186 @Bean(name="messageHandler")
187 MessageHandler createMessageHandler() {
188 logger.info("Creating messageHandler");
189 return new MessageHandler();
190 }
191
192 //--------
193 @Bean(name="fanoutExchange")
194 FanoutExchange createFanoutExchange() {
195 logger.info("Creating fanoutExchange");
196 return new FanoutExchange("fanoutExchange");
197 }
198
199 @Bean(name="anonymousQueue1")
200 AnonymousQueue createAnonymousQueue1() {
201 logger.info("Creating anonQueue1");
202 return new AnonymousQueue();
203 }
204
205 @Bean(name="bindingTopic")
206 Binding bindingTopic(@Qualifier("anonymousQueue1")AnonymousQueue queue, @Qualifier("fanoutExchange")FanoutExchange exchange) {
207 logger.info("Creating bindingTopic");
208 return BindingBuilder.bind(queue).to(exchange);
209 }
210
211 @Bean(name="broadcastMessageHandler")
212 BroadcastMessageHandler createBroadcastMessageHandler() {
213 logger.info("Creating broadcastMessageHandlermessageHandler");
214 return new BroadcastMessageHandler();
215 }
216
217 @Bean(name="broadcastListenerAdapter")
218 MessageListenerAdapter createBroadcastlistenerAdapter(@Autowired @Qualifier("broadcastMessageHandler")BroadcastMessageHandler broadcastMessageHandler) {
219 logger.info("Creating broadcastListenerAdapter");
220 return new MessageListenerAdapter(broadcastMessageHandler);
221 }
222
223 @Bean(name="topicContainer")
224 SimpleMessageListenerContainer createTopicContainer(ConnectionFactory connectionFactory, @Autowired @Qualifier("broadcastListenerAdapter") MessageListenerAdapter listenerAdapter, @Qualifier("anonymousQueue1") AnonymousQueue anonQueue) {
225 logger.info("Creating container for topic");
226 logger.info(String.format("Using ConnectionFactory with hashCode %d" , connectionFactory.hashCode() ) );
227
228 SimpleMessageListenerContainer smlc = new SimpleMessageListenerContainer();
229 smlc.setConnectionFactory(connectionFactory);
230 smlc.setQueueNames( anonQueue.getName() );
231 smlc.setMessageListener(listenerAdapter);
232 return smlc;
233 }
234
235 //----
236 //---- rabbit
237 }
persistence.xml
1 <persistence>
2 <persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
3 <jta-data-source>basicDataSource</jta-data-source>
4 <properties>
5 <!-- <property name="hibernate.hbm2ddl.auto" value="create-drop" /> -->
6 <property name="hibernate.hbm2ddl.auto" value="update" />
7 <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
8 <property name="hibernate.show_sql" value="false" />
9 </properties>
10 </persistence-unit>
11 </persistence>
greeting.html
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
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>
application.properties
logging.file=/tmp/testout.log server.port=8443 foo.bar=bohica instance.name=node1 keystore.file=springboot.p12 keystore.password=???? keystore.type=PKCS12 keystore.alias=springboot db.driverclass=org.mariadb.jdbc.Driver db.jdbcurl=jdbc:mariadb://localhost:3306/springmvchtml db.username=usertest db.password=???? db.initialsizeconnpool=3 #rabbimq parameters rabbitmq.uri=amqp://????:????@localhost:5672 #redis spring.redis.host=localhost spring.redis.password=???????? spring.redis.port=6379
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 <dependency>
29 <groupId>org.springframework</groupId>
30 <artifactId>spring-jdbc</artifactId>
31 <version>4.3.2.RELEASE</version>
32 </dependency>
33 <dependency>
34 <groupId>org.springframework.boot</groupId>
35 <artifactId>spring-boot-starter-data-jpa</artifactId>
36 </dependency>
37 <dependency>
38 <groupId>org.springframework.boot</groupId>
39 <artifactId>spring-boot-starter-amqp</artifactId>
40 </dependency>
41 <dependency>
42 <groupId>javax.inject</groupId>
43 <artifactId>javax.inject</artifactId>
44 <version>1</version>
45 </dependency>
46 <!-- http session redis -->
47 <dependency>
48 <groupId>org.springframework.session</groupId>
49 <artifactId>spring-session</artifactId>
50 <version>1.2.2.RELEASE</version>
51 </dependency>
52 <dependency>
53 <groupId>org.springframework.boot</groupId>
54 <artifactId>spring-boot-starter-data-redis</artifactId>
55 </dependency>
56 <!-- http session redis -->
57 </dependencies>
58 <properties>
59 <start-class>hello.Application</start-class>
60 </properties>
61 <build>
62 <plugins>
63 <plugin>
64 <groupId>org.springframework.boot</groupId>
65 <artifactId>spring-boot-maven-plugin</artifactId>
66 </plugin>
67 </plugins>
68 </build>
69 <repositories>
70 <repository>
71 <id>spring-milestone</id>
72 <url>http://repo.spring.io/libs-release</url>
73 </repository>
74 </repositories>
75 <pluginRepositories>
76 <pluginRepository>
77 <id>spring-milestone</id>
78 <url>http://repo.spring.io/libs-release</url>
79 </pluginRepository>
80 </pluginRepositories>
81 </project>
Libs
1 -rw-r--r-- 1 vitor vitor 37M Sep 29 15:49 test-spring-boot-0.1.0.jar
2 jar tf test-spring-boot-0.1.0.jar | grep BOOT | grep jar
3 BOOT-INF/lib/spring-session-1.2.2.RELEASE.jar
4 BOOT-INF/lib/spring-boot-starter-data-redis-1.4.0.RELEASE.jar
5 BOOT-INF/lib/jackson-core-2.8.1.jar
6 BOOT-INF/lib/javassist-3.20.0-GA.jar
7 BOOT-INF/lib/jul-to-slf4j-1.7.21.jar
8 BOOT-INF/lib/groovy-2.4.7.jar
9 BOOT-INF/lib/spring-amqp-1.6.1.RELEASE.jar
10 BOOT-INF/lib/hibernate-validator-5.2.4.Final.jar
11 BOOT-INF/lib/classmate-1.3.1.jar
12 BOOT-INF/lib/hibernate-commons-annotations-5.0.1.Final.jar
13 BOOT-INF/lib/tomcat-embed-el-8.5.4.jar
14 BOOT-INF/lib/jedis-2.8.2.jar
15 BOOT-INF/lib/httpcore-4.4.5.jar
16 BOOT-INF/lib/antlr-2.7.7.jar
17 BOOT-INF/lib/xml-apis-1.4.01.jar
18 BOOT-INF/lib/spring-boot-starter-tomcat-1.4.0.RELEASE.jar
19 BOOT-INF/lib/thymeleaf-layout-dialect-1.4.0.jar
20 BOOT-INF/lib/spring-boot-autoconfigure-1.4.0.RELEASE.jar
21 BOOT-INF/lib/snakeyaml-1.17.jar
22 BOOT-INF/lib/http-client-1.0.0.RELEASE.jar
23 BOOT-INF/lib/httpclient-4.5.2.jar
24 BOOT-INF/lib/spring-boot-starter-logging-1.4.0.RELEASE.jar
25 BOOT-INF/lib/tomcat-jdbc-8.5.4.jar
26 BOOT-INF/lib/spring-beans-4.3.2.RELEASE.jar
27 BOOT-INF/lib/spring-jdbc-4.3.2.RELEASE.jar
28 BOOT-INF/lib/spring-boot-starter-jdbc-1.4.0.RELEASE.jar
29 BOOT-INF/lib/spring-boot-starter-amqp-1.4.0.RELEASE.jar
30 BOOT-INF/lib/spring-aspects-4.3.2.RELEASE.jar
31 BOOT-INF/lib/commons-dbcp-1.4.jar
32 BOOT-INF/lib/spring-data-commons-1.12.2.RELEASE.jar
33 BOOT-INF/lib/spring-context-support-4.3.2.RELEASE.jar
34 BOOT-INF/lib/spring-data-keyvalue-1.1.2.RELEASE.jar
35 BOOT-INF/lib/spring-boot-starter-1.4.0.RELEASE.jar
36 BOOT-INF/lib/tomcat-embed-websocket-8.5.4.jar
37 BOOT-INF/lib/commons-logging-1.2.jar
38 BOOT-INF/lib/spring-tx-4.3.2.RELEASE.jar
39 BOOT-INF/lib/validation-api-1.1.0.Final.jar
40 BOOT-INF/lib/spring-core-4.3.2.RELEASE.jar
41 BOOT-INF/lib/spring-boot-starter-aop-1.4.0.RELEASE.jar
42 BOOT-INF/lib/spring-data-jpa-1.10.2.RELEASE.jar
43 BOOT-INF/lib/commons-pool2-2.4.2.jar
44 BOOT-INF/lib/dom4j-1.6.1.jar
45 BOOT-INF/lib/tomcat-juli-8.5.4.jar
46 BOOT-INF/lib/jcl-over-slf4j-1.7.21.jar
47 BOOT-INF/lib/log4j-over-slf4j-1.7.21.jar
48 BOOT-INF/lib/aspectjweaver-1.8.9.jar
49 BOOT-INF/lib/spring-data-redis-1.7.2.RELEASE.jar
50 BOOT-INF/lib/spring-web-4.3.2.RELEASE.jar
51 BOOT-INF/lib/unbescape-1.1.0.RELEASE.jar
52 BOOT-INF/lib/mariadb-java-client-1.4.4.jar
53 BOOT-INF/lib/amqp-client-3.6.3.jar
54 BOOT-INF/lib/spring-oxm-4.3.2.RELEASE.jar
55 BOOT-INF/lib/tomcat-embed-core-8.5.4.jar
56 BOOT-INF/lib/spring-orm-4.3.2.RELEASE.jar
57 BOOT-INF/lib/hibernate-jpa-2.1-api-1.0.0.Final.jar
58 BOOT-INF/lib/commons-pool-1.6.jar
59 BOOT-INF/lib/thymeleaf-spring4-2.1.5.RELEASE.jar
60 BOOT-INF/lib/hibernate-core-5.0.9.Final.jar
61 BOOT-INF/lib/spring-context-4.3.2.RELEASE.jar
62 BOOT-INF/lib/thymeleaf-2.1.5.RELEASE.jar
63 BOOT-INF/lib/commons-codec-1.10.jar
64 BOOT-INF/lib/spring-boot-starter-web-1.4.0.RELEASE.jar
65 BOOT-INF/lib/spring-webmvc-4.3.2.RELEASE.jar
66 BOOT-INF/lib/slf4j-api-1.7.21.jar
67 BOOT-INF/lib/javax.inject-1.jar
68 BOOT-INF/lib/jackson-annotations-2.8.1.jar
69 BOOT-INF/lib/jandex-2.0.0.Final.jar
70 BOOT-INF/lib/spring-messaging-4.3.2.RELEASE.jar
71 BOOT-INF/lib/ognl-3.0.8.jar
72 BOOT-INF/lib/hibernate-entitymanager-5.0.9.Final.jar
73 BOOT-INF/lib/spring-boot-starter-thymeleaf-1.4.0.RELEASE.jar
74 BOOT-INF/lib/spring-retry-1.1.3.RELEASE.jar
75 BOOT-INF/lib/javax.transaction-api-1.2.jar
76 BOOT-INF/lib/logback-classic-1.1.7.jar
77 BOOT-INF/lib/spring-boot-starter-data-jpa-1.4.0.RELEASE.jar
78 BOOT-INF/lib/spring-boot-1.4.0.RELEASE.jar
79 BOOT-INF/lib/spring-expression-4.3.2.RELEASE.jar
80 BOOT-INF/lib/logback-core-1.1.7.jar
81 BOOT-INF/lib/jackson-databind-2.8.1.jar
82 BOOT-INF/lib/spring-rabbit-1.6.1.RELEASE.jar
83 BOOT-INF/lib/spring-aop-4.3.2.RELEASE.jar
84 BOOT-INF/lib/jboss-logging-3.3.0.Final.jar
springTestApp
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5 http://maven.apache.org/xsd/maven-4.0.0.xsd">
6 <modelVersion>4.0.0</modelVersion>
7 <groupId>org.allowed.bitarus</groupId>
8 <artifactId>springTestApp</artifactId>
9 <version>0.1.0</version>
10 <parent>
11 <groupId>org.springframework.boot</groupId>
12 <artifactId>spring-boot-starter-parent</artifactId>
13 <version>1.4.2.RELEASE</version>
14 </parent>
15 <dependencies>
16 <dependency>
17 <groupId>org.springframework.boot</groupId>
18 <artifactId>spring-boot-starter-web</artifactId>
19 </dependency>
20 </dependencies>
21 <properties>
22 <start-class>org.allowed.bitarus.springTestApp.Application</start-class>
23 </properties>
24 <build>
25 <plugins>
26 <plugin>
27 <artifactId>maven-compiler-plugin</artifactId>
28 <version>2.3.2</version>
29 </plugin>
30 <plugin>
31 <groupId>org.springframework.boot</groupId>
32 <artifactId>spring-boot-maven-plugin</artifactId>
33 </plugin>
34 </plugins>
35 </build>
36 <repositories>
37 <repository>
38 <id>spring-releases</id>
39 <url>http://repo.spring.io/libs-release</url>
40 </repository>
41 </repositories>
42 <pluginRepositories>
43 <pluginRepository>
44 <id>spring-releases</id>
45 <url>http://repo.spring.io/libs-release</url>
46 </pluginRepository>
47 </pluginRepositories>
48 </project>
src/main/java/org/allowed/bitarus/springTestApp/Application.java
1 package org.allowed.bitarus.springTestApp;
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.boot.autoconfigure.SpringBootApplication;
7 import org.springframework.context.annotation.Bean;
8 import java.util.concurrent.Future;
9 import java.util.ArrayList;
10 import java.util.concurrent.ExecutorService;
11 import java.util.concurrent.Executors;
12
13 @ComponentScan
14 @EnableAutoConfiguration
15 @SpringBootApplication
16 public class Application {
17
18 public static void main(String[] args) {
19 SpringApplication.run(Application.class, args);
20 }
21
22 @Bean(name="tasksFutures")
23 public ArrayList<Future<Integer>> createTasksFutures(){
24 System.out.println("Creating tasksFutures");
25 return new ArrayList<Future<Integer>>();
26 }
27
28 @Bean(name="executors")
29 public ExecutorService createExecutors(){
30 return Executors.newFixedThreadPool(5);
31 }
32 }
src/main/java/org/allowed/bitarus/springTestApp/Tasker.java
1 package org.allowed.bitarus.springTestApp;
2
3 import org.springframework.stereotype.Component;
4 import java.util.concurrent.ExecutorService;
5 import java.util.concurrent.Future;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.beans.factory.annotation.Qualifier;
8
9 @Component("tasker")
10 public class Tasker {
11 private ExecutorService _es;
12
13 public Tasker(@Qualifier("executors") ExecutorService es){
14 System.out.println("Created Tasker !!!!");
15 _es = es;
16 }
17
18 public Future<Integer> addTask(TaskX taskx){
19 Future<Integer> f = _es.submit( taskx );
20 return f;
21 }
22 }
src/main/java/org/allowed/bitarus/springTestApp/Receiver.java
1 package org.allowed.bitarus.springTestApp;
2
3 import org.springframework.stereotype.Component;
4 import java.util.concurrent.Future;
5 import java.util.ArrayList;
6 import org.springframework.beans.factory.annotation.Qualifier;
7 import javax.annotation.PostConstruct;
8
9 @Component
10 public class Receiver {
11 private Tasker _t;
12 private ArrayList<Future<Integer>> _tasks;
13
14 public Receiver(@Qualifier("tasker")Tasker t, @Qualifier("tasksFutures") ArrayList<Future<Integer>> tasks ){
15 System.out.println("Created receiver !!!!");
16 _t = t;
17 _tasks = tasks;
18 // wait for all tasks ...
19 /*
20 boolean loop=true;
21 while(loop){
22 boolean allDone=true;
23 for(Future<Integer> f : tasks){
24 if(f.isDone()==false){
25 allDone=false;
26 }
27 }
28
29 if(allDone){
30 loop=false;
31 }
32
33 try{
34 Thread.sleep(1000);
35 }
36 catch(Exception ex){
37 }
38 }
39
40 for(Future<Integer> f : tasks){
41 try{
42 Integer res = f.get();
43 System.out.println(res);
44 }
45 catch(Exception ex){
46 }
47 } */
48 }
49
50 @PostConstruct
51 public void init(){
52 System.out.println("Init post construct");
53 for(int i=0;i<10;i++){
54 _tasks.add( _t.addTask( new TaskX(5,6) ) );
55 }
56 }
57 }
TaskX.java
1 package org.allowed.bitarus.springTestApp;
2
3 import java.util.concurrent.Callable;
4
5 public class TaskX implements Callable<Integer>{
6 private int _x;
7 private int _y;
8
9 public TaskX(int x,int y){
10 _x=x;
11 _y=y;
12 }
13
14 public Integer call() {
15 try {
16 Thread.sleep(5000);
17 }
18 catch(Exception ex){
19 }
20 int sum = _x+_y;
21 System.out.println("TID:"+Thread.currentThread().getId() + " sumVal:" + sum );
22 return sum;
23 }
24 }
Example with MongoDB
Think about using spring.data.mongodb.uri.
pom.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5 http://maven.apache.org/xsd/maven-4.0.0.xsd">
6 <modelVersion>4.0.0</modelVersion>
7 <groupId>org.allowed.bitarus</groupId>
8 <artifactId>springTestApp</artifactId>
9 <version>0.1.0</version>
10 <parent>
11 <groupId>org.springframework.boot</groupId>
12 <artifactId>spring-boot-starter-parent</artifactId>
13 <version>1.4.2.RELEASE</version>
14 </parent>
15 <dependencies>
16 <dependency>
17 <groupId>org.springframework.boot</groupId>
18 <artifactId>spring-boot-starter-web</artifactId>
19 </dependency>
20 <dependency>
21 <groupId>org.springframework.data</groupId>
22 <artifactId>spring-data-mongodb</artifactId>
23 <version>1.9.6.RELEASE</version>
24 </dependency>
25 </dependencies>
26 <properties>
27 <start-class>org.allowed.bitarus.springTestApp.Application</start-class>
28 </properties>
29 <build>
30 <plugins>
31 <plugin>
32 <artifactId>maven-compiler-plugin</artifactId>
33 <version>2.3.2</version>
34 </plugin>
35 <plugin>
36 <groupId>org.springframework.boot</groupId>
37 <artifactId>spring-boot-maven-plugin</artifactId>
38 </plugin>
39 </plugins>
40 </build>
41 <repositories>
42 <repository>
43 <id>spring-releases</id>
44 <url>http://repo.spring.io/libs-release</url>
45 </repository>
46 </repositories>
47 <pluginRepositories>
48 <pluginRepository>
49 <id>spring-releases</id>
50 <url>http://repo.spring.io/libs-release</url>
51 </pluginRepository>
52 </pluginRepositories>
53 </project>
src/main/resources/application.properties
src/main/java/org/allowed/bitarus/springTestApp/Application.java
1 package org.allowed.bitarus.springTestApp;
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.boot.autoconfigure.SpringBootApplication;
7 import org.springframework.context.annotation.Bean;
8 import java.util.concurrent.Future;
9 import java.util.ArrayList;
10 import java.util.concurrent.ExecutorService;
11 import java.util.concurrent.Executors;
12 import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
13 import org.springframework.data.mongodb.core.MongoTemplate;
14 import com.mongodb.Mongo;
15 import org.springframework.core.env.Environment;
16 import javax.annotation.Resource;
17
18 @ComponentScan
19 @EnableAutoConfiguration
20 @SpringBootApplication
21 @EnableMongoRepositories // search for MongoDB reps
22 public class Application {
23 @Resource
24 Environment _env;
25
26 public static void main(String[] args) {
27 SpringApplication.run(Application.class, args);
28 }
29
30 @Bean(name="tasksFutures")
31 public ArrayList<Future<Integer>> createTasksFutures(){
32 System.out.println("Creating tasksFutures");
33 return new ArrayList<Future<Integer>>();
34 }
35
36 @Bean(name="executors")
37 public ExecutorService createExecutors(){
38 System.out.println("Creating executors");
39 System.out.println(_env.getProperty("threadpool.nrExecutors"));
40 return Executors.newFixedThreadPool(5);
41 }
42
43 @Bean(name="mongoTemplate")
44 public MongoTemplate mongoTemplate() throws Exception {
45 System.out.println("Creating mongoTemplate");
46 System.out.println(_env.getProperty("mongox.host"));
47 System.out.println(_env.getProperty("mongox.port"));
48 System.out.println(_env.getProperty("mongox.database"));
49 Mongo mongo = new Mongo( _env.getProperty("mongox.host"), Integer.parseInt(_env.getProperty("mongox.port") ) );
50 return new MongoTemplate(mongo, _env.getProperty("mongox.database") );
51 }
52 }
src/main/java/org/allowed/bitarus/springTestApp/Tasker.java
1 package org.allowed.bitarus.springTestApp;
2
3 import org.springframework.stereotype.Component;
4 import java.util.concurrent.ExecutorService;
5 import java.util.concurrent.Future;
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.beans.factory.annotation.Qualifier;
8
9 @Component("tasker")
10 public class Tasker {
11 private ExecutorService _es;
12
13 public Tasker(@Qualifier("executors") ExecutorService es){
14 System.out.println("Created Tasker !!!!");
15 _es = es;
16 }
17
18 public Future<Integer> addTask(TaskX taskx){
19 Future<Integer> f = _es.submit( taskx );
20 return f;
21 }
22 }
src/main/java/org/allowed/bitarus/springTestApp/Result.java
1 package org.allowed.bitarus.springTestApp;
2
3 import org.springframework.data.annotation.Id;
4
5 public class Result {
6 @Id
7 private String id;
8 private int sumResult;
9
10 public Result(){}
11 public int getSumResult(){return this.sumResult;}
12 public void setSumResult(int sumResult){this.sumResult=sumResult;}
13 public String getId(){return this.id;}
14 public void setId(String id){this.id=id;}
15 }
src/main/java/org/allowed/bitarus/springTestApp/Receiver.java
1 package org.allowed.bitarus.springTestApp;
2
3 import org.springframework.stereotype.Component;
4 import java.util.concurrent.Future;
5 import java.util.ArrayList;
6 import java.util.List;
7 import org.springframework.beans.factory.annotation.Qualifier;
8 import javax.annotation.PostConstruct;
9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.data.mongodb.core.query.Query;
11 import org.springframework.data.mongodb.core.MongoTemplate;
12
13 @Component
14 public class Receiver {
15 private Tasker _t;
16 private ArrayList<Future<Integer>> _tasks;
17 private ResultRepository _repository;
18
19 public Receiver(@Qualifier("tasker")Tasker t, @Qualifier("tasksFutures") ArrayList<Future<Integer>> tasks, ResultRepository repository ){
20 System.out.println("Created receiver !!!!");
21 _t = t;
22 _tasks = tasks;
23 _repository = repository;
24 }
25 @Autowired
26 private MongoTemplate mongoTemplate;
27
28 @PostConstruct
29 public void init(){
30 System.out.println("Init post construct");
31 for(int i=0;i<10;i++){
32 _tasks.add( _t.addTask( new TaskX(5,6) ) );
33 }
34
35 // wait for all tasks ...
36 boolean loop=true;
37 while(loop){
38 boolean allDone=true;
39 for(Future<Integer> f : _tasks){
40 if(f.isDone()==false){
41 allDone=false;
42 }
43 }
44
45 if(allDone){
46 loop=false;
47 }
48
49 try{
50 Thread.sleep(1000);
51 }
52 catch(Exception ex){
53 }
54 }
55
56 for(Future<Integer> f : _tasks){
57 try{
58 Integer res = f.get();
59 System.out.println(res);
60 Result r = new Result();
61 r.setSumResult(res);
62 _repository.save(r);
63 }
64 catch(Exception ex){
65 }
66 }
67
68 System.out.println( _repository.count() );
69 List<Result> res = _repository.findBySumResult(11);
70 for(Result r : res){
71 r.setSumResult((int)System.currentTimeMillis());
72 _repository.save(r);
73 }
74
75 System.out.println("mongoTemplateCount " + mongoTemplate.count(new Query() ,Result.class) );
76 }
77 }
src/main/java/org/allowed/bitarus/springTestApp/ResultRepository.java
1 package org.allowed.bitarus.springTestApp;
2
3 import java.util.List;
4 import org.springframework.data.mongodb.repository.MongoRepository;
5 /*
6 Result -> class to store
7 String -> id in collection type
8 Collection result in database mydatabase
9 { "_id" : ObjectId("58828e2822e1a609d96a5e52"), "_class" : "org.allowed.bitarus.springTestApp.Result", "sumResult" : 11 }
10 */
11 public interface ResultRepository extends MongoRepository<Result, String> {
12 public List<Result> findBySumResult(int sumResult);
13 }
src/main/java/org/allowed/bitarus/springTestApp/TaskX.java
1 package org.allowed.bitarus.springTestApp;
2
3 import java.util.concurrent.Callable;
4
5 public class TaskX implements Callable<Integer>{
6 private int _x;
7 private int _y;
8
9 public TaskX(int x,int y){
10 _x=x;
11 _y=y;
12 }
13
14 public Integer call() {
15 try {
16 Thread.sleep(5000);
17 }
18 catch(Exception ex){
19 }
20 int sum = _x+_y;
21 System.out.println("TID:"+Thread.currentThread().getId() + " sumVal:" + sum );
22
23 return sum;
24 }
25 }
Integration tests
Integration tests setup and start Spring context before running the tests.
1 // <groupId>org.springframework.boot</groupId>
2 // <artifactId>spring-boot-starter-test</artifactId>
3 @Test // test case
4 @RunWith(SpringRunner.class)
5 @MockBean // inject mocked beans
6 // Mockito, given , willReturn Mocks simulates real objects
7 @SpyBean
8 // create proxy for a real object
9 @SpringBootTest // test application context
10 @ActiveProfiles("test") // use application properties for test profile
11 @WebFluxTest // web flux controllers tests
12 @WebMvcTest // web tests
13
14 // application-<profile>.properties
15 // application-<profile>.yml
16 application-test.properties
17 application-test.yml
18
19 // Utility class for working with the reflection API and handling reflection exceptions.
20 // allows changes to be made on member variables autowired or with value annotation
21 ReflectionUtils
JPARepository
Captures the domain type to manage as well as the domain type's id type.
Mechanism for encapsulating storage, retrieval, and search behavior which emulates a collection of objects. Specialization of @Component.
ConfigurationProperties
- Annotation for externalized configuration.