Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ "Bootiful" Applications with Spring Boot Dave Syer - Stéphane Nicoll Pivotal
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ “Bootiful” Applications with Spring Boot 2 @david_syer | @snicoll @david_syer @snicoll [dsyer,snicoll]@pivotal.io Dave Syer, Stéphane Nicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 4 @david_syer | @snicoll https://spring.io - Boot in production > 18 months! github.com/spring-io/sagan
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Boot: Focus Attention 5 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Introduction to Spring Boot 6 ! Single point of focus (as opposed to large collection of spring-* projects) ! A tool for getting started very quickly with Spring ! Common non-functional requirements for a "real" application ! Exposes a lot of useful features by default ! Gets out of the way quickly if you want to change defaults ! An opportunity for Spring to be opinionated “ Spring Boot lets you pair-program with the Spring team. Josh Long, @starbuxman @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ ಠ_ಠ Spring Boot is NOT ! A prototyping tool ! Only for embedded container apps ! Sub-par Spring experience ! For Spring beginners only 7 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Installation ! Requirements: • Java (>=1.6) + (for Java projects) • Maven 3.2+ or Gradle 1.12+ ! Spring Tool Suite has some nice features for Java projects ! Download: https://start.spring.io/spring.zip ! Unzip the distro (approx. 10MB), and find bin/ directory ! (You can also install Spring Boot CLI with gvm, brew or MacPorts) 8 @david_syer | @snicoll $ spring —help ...
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting Started Really Quickly 9 @david_syer | @snicoll @RestController class Example { @RequestMapping("/") String home() { 'Hello world!' } } $ spring run app.groovy ... application is running at http://localhost:8080
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ What Just Happened? 10 @david_syer | @snicoll import org.springframework.web.bind.annotation.RestController // other imports ... @RestController class Example { @RequestMapping("/") public String hello() { return "Hello World!"; } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ What Just Happened? 11 @david_syer | @snicoll import org.springframework.web.bind.annotation.RestController // other imports ... @Grab(“org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE") @RestController class Example { @RequestMapping("/") public String hello() { return "Hello World!"; } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ What Just Happened? 12 @david_syer | @snicoll import org.springframework.web.bind.annotation.RestController // other imports ... @Grab(“org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE") @EnableAutoConfiguration @RestController class Example { @RequestMapping("/") public String hello() { return "Hello World!"; } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ What Just Happened? 13 @david_syer | @snicoll import org.springframework.web.bind.annotation.RestController // other imports ... @Grab(“org.springframework.boot:spring-boot-starter-web:1.2.1.RELEASE") @EnableAutoConfiguration @RestController class Example { @RequestMapping("/") public String hello() { return "Hello World!"; } public static void main(String[] args) { SpringApplication.run(Example.class, args); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting Started in Java 14 @david_syer | @snicoll ! Create a skeleton project on https://start.spring.io ! Choose the web option and download the project ! Add a simple controller alongside the app @RestController public class HomeController { @RequestMapping("/") public String home() { return "Hello World!"; } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ SpringApplication ! Gets a running Spring ApplicationContext ! Uses EmbeddedWebApplicationContext for web apps ! Can be a single line • SpringApplication.run(MyApplication.class, args) ! Or customized via SpringApplicationBuilder 16 @david_syer | @snicoll SpringApplication app = new SpringApplication(MyApplication.class); app.setShowBanner(false); app.run(args);
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ SpringApplicationBuilder ! Flexible builder style with fluent API for building SpringApplication with more complex requirements. 17 @david_syer | @snicoll new SpringApplicationBuilder(ParentConfiguration.class) .profiles("adminServer", "single") .child(AdminServerApplication.class) .run(args);
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ @EnableAutoConfiguration ! Attempts to auto-configure your application ! Backs off as you define your own beans ! Regular @Configuration classes ! Usually with @ConditionalOnClass and @ConditionalOnMissingBean 18 @david_syer | @snicoll @Configuration @ComponentScan @EnableAutoConfiguration public class MyApplication { } @SpringBootApplication public class MyApplication { }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Testing with Spring Test (and MVC) ! spring-boot-starter-test provides useful test dependencies • spring-test, Mockito, Hamcrest and JUnit ! @SpringApplicationConfiguration • Alternative to the standard spring-test @ContextConfiguration • Does not start the full context by default ! @WebIntegrationTest • Requires a web application context • Can add additional properties to the environment 19 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Packaging For Production ! Easy to understand structure ! No unpacking or start scripts required ! Typical REST app ~10Mb ! Cloud Foundry friendly (works & fast to upload) 21 @david_syer | @snicoll $ java -jar yourapp.jar
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Not a Web Application? ! CommandLineRunner is a hook to run application-specific code after the context is created 22 @david_syer | @snicoll @Component public class Startup implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("Hello World"); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Environment and Profiles ! Every ApplicationContext has an Environment ! Spring Environment available since 3.1 ! Abstraction for key/value pairs from multiple sources ! Used to manage @Profile switching ! Always available: System properties and OS ENV vars 23 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Command Line Arguments ! SpringApplication adds command line arguments to the Spring Environment so you can inject them into beans: ! You can also configure many aspects of Spring Boot itself: 24 @david_syer | @snicoll @Value("${name}") private String name; $ java -jar yourapp.jar --name=BootDragon $ java -jar yourapp.jar --server.port=9000
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Externalizing Configuration to Properties ! Just put application.properties in one of the following locations: • A /config sub-directory of the current directory • The current directory • A classpath /config package • The root classpath ! Properties can be overridden • command line arg > file > classpath • locations higher in the list override lower items 25 @david_syer | @snicoll server.port=9000 name=BootDragon
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Using YAML ! Just include snake-yaml.jar • Already available if you’re using the starters ! Write an application.yml file 26 @david_syer | @snicoll name: BootDragon server: port: 9000
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Data Binding to @ConfigurationProperties ! Spring DataBinder does type coercion and conversion where possible ! Custom ConversionService additionally discovered by bean name (same as ApplicationContext) ! Ditto for validation • configurationPropertiesValidator bean if present • JSR303 if present • ignoreUnkownFields=true (default) • ignoreInvalidFields=false (default) ! Uses a RelaxedDataBinder which accepts common variants of property names (e.g. CAPITALIZED, camelCased or with_underscores) 28 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Configuration Meta-data ! Annotation processor ! Generates a meta-data file while compiling your project • Javadoc on fields are translated to descriptions • Default values are detected (to some extend) • Additional meta-data can be provided for corner cases • META-INF/additional-spring-configuration-metadata.json 29 @david_syer | @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Customizing Configuration Location ! Set • spring.config.name - default application, can be comma-separated list • spring.config.location - a Resource path • Ends with / to define a directory • Otherwise overrides name 30 @david_syer | @snicoll $ java -jar app.jar --spring.config.name=production $ java -jar app.jar --spring.config.location=classpath:/cfg/ $ java -jar app.jar --spring.config.location=classpath:/cfg.yml
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Profiles ! Activate external configuration with a Spring profile • file name convention e.g. application-development.properties • or nested documents in YAML: 31 @david_syer | @snicoll server: address: 192.168.1.100 --- spring: profiles: development server: address: 127.0.0.1 --- spring: profiles: production server: address: 192.168.1.120
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Profiles ! Set the default spring profile(s) in external configuration ! Add some profile(s) to the active profiles rather than replacing them 32 @david_syer | @snicoll spring.profiles.active=default, postgresql $ java -jar yourapp.jar —spring.profiles.active=production spring.profiles.include=another
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Adding some Autoconfigured Behavior ! Extend the demo and see what we can get by just modifying the class path • Create a simple domain object • Expose the repository as a REST endpoint 33 @david_syer | @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Logging ! Spring Boot provides default configuration files for 4 logging frameworks: Logback, Log4j, Log4j2 and java.util.Logging ! Starters (and Samples) use Logback with colour output ! Default log level set to INFO • Debug output can be easily enabled using the --debug option ! Log to console by default • logging.file and logging.path to enable file logging ! Logging levels can be customised through configuration 34 @david_syer | @snicoll logging.level.org.acme=TRACE
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add static resources ! Easiest: use classpath:/static/** ! Many alternatives: • classpath:/public/** • classpath:/resources/** • classpath:/META-INF/resources/** ! Normal servlet context / (root of WAR file, see later) • i.e. src/main/webapp • static/** • public/** • set documentRoot in EmbeddedServletContextFactory 35 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Web template engines ! Spring Boot includes auto-configuration support for Thymeleaf, Groovy, FreeMarker, Velocity and Mustache ! By default, templates will be picked up automatically from classpath:/ templates ! Common configuration, e.g. for Thymeleaf • spring.thymeleaf.prefix (location of templates) • spring.thymeleaf.cache (set to false to live reload templates) • Extend and override, just add beans: • thymeleafViewResolver • SpringTemplateEngine 36 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Error handling ! /error handles all errors in a sensible way • Registered as global error page in the servlet container • Add a view that resolve to ‘error’ to customize the representation ! Default representation • Whitelabel error page for browser if none is found • Standardized JSON format for machine clients ! Customize or extend ErrorAttributes ! Create dedicated error pages via EmbeddedServletContainerCustomizer 37 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Adding some Autoconfigured Behavior ! Secure the web application • Application endpoints secured via security.basic.enabled=true (on by default) ! See how you can ask Boot to back off • Configure a custom AuthenticationManager 38 @david_syer | @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Currently Available Autoconfigured Behaviour ! Data grid: Spring Data Gemfire, Solr and Elasticsearch ! Websocket ! Web services ! Mobile & Social (Facebook, Twitter and LinkedIn) ! Reactor for events and async processing ! Jersey ! JTA ! Email, CRaSH, AOP (AspectJ) ! Actuator features (Security, Audit, Metrics, Trace) 40 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ The Actuator ! Adds common non-functional features to your application and exposes endpoints to interact with them (REST, JMX) • Secure endpoints: /env, /metrics, /trace, /dump, /shutdown, /beans, / autoconfig, /configprops, /mappings • /info • /health • Audit If embedded in a web app or web service can use the same port or a different one (management.port) and/or a different network interface (management.address) and/or context path (management.context-path). 41 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add a remote SSH server ! Add spring-boot-starter-remote-shell to class path ! Application exposed to SSH on port 2000 by default 42 @david_syer | @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-remote-shell</artifactId> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Building a WAR We like launchable JARs, but you can still use WAR format if you prefer. Spring Boot Tools take care of repackaging a WAR to make it executable. If you want a WAR to be deployable (in a "normal" container), then you need to use SpringBootServletInitializer instead of or as well as SpringApplication. 43 @david_syer | @snicoll public class ServletInitializer extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application) { return application.sources(MyApplication.class); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Customizing the Servlet Container ! Some common features exposed with external configuration, e.g. server.port (see ServerProperties bean) • Also container-specific properties, i.e. server.tomcat.* ! Add bean(s) of type EmbeddedServletContainerCustomizer • all instances get a callback to the container ! Add bean of type EmbeddedServletContainerFactory (replacing auto- configured one) 44 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Customizing @EnableAutoConfiguration ! Disable specific feature • @EnableAutoConfiguration(exclude={WebMvcAutoConfiguration.class}) • @SpringBootApplication(exclude={WebMvcAutoConfiguration.class}) ! Write your own… • Create your own @Configuration class • Add the FQN of your configuration class in META-INF/spring.factories • All entries from classpath merged and added to context 45 @david_syer | @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Customizing the CLI ! Uses standard Java META-INF/services scanning ! CompilerAutoConfiguration: add dependencies and imports based on matches in the code ! CommandFactory: add additional commands ! name and description ! usage help ! actual execution based on command line arguments 46 @david_syer | @snicoll