Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ From Zero to Hero with Spring Boot Stéphane Nicoll Pivotal
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Hello! 2 @snicoll https://github.com/snicoll @snicoll [email protected]
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 4 @snicoll “ Spring Boot lets you pair-program with the Spring team. Josh Long, @starbuxman
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Introduction to Spring Boot ! 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 5 @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 6 @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Installation ! Requirements: • JDK6+ • Maven 3.2+ / Gradle 1.12+ ! Tools: • Spring Tool Suite (STS) - IntelliJ IDEA - Netbeans • Spring CLI (from https://start.spring.io or gvm) 7 @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Let’s get started! 8 @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting Started Really Quickly 9 @snicoll @RestController public class HomeController { @Value("${conference.name:jsug}") private String conference; @RequestMapping("/") public String home() { return "Hello " + conference; } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ First integration test 10 @snicoll @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = DemoApplication.class) @WebIntegrationTest(randomPort = true) public class HomeControllerIntegrationTest { @Value("${local.server.port}") private int port; @Test public void runAndInvokeHome() { String url = "http://localhost:" + port + "/"; String body = new RestTemplate() .getForObject(url, String.class); assertThat(body, is("Hello jsug")); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add Spring Data JPA 11 @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add a Speaker Repository 13 @snicoll public interface SpeakerRepository extends CrudRepository<Speaker, Long> { Speaker findByTwitter(String twitter); Collection<Speaker> findByLastName(String lastName); }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Test that repository 14 @snicoll @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = DemoApplication.class) public class SpeakerRepositoryTest { @Autowired private SpeakerRepository speakerRepository; @Test public void testFindByTwitter() throws Exception { Speaker stephane = speakerRepository.save( new Speaker("Stephane", "Nicoll", "snicoll")); assertThat(speakerRepository.findByTwitter("snicoll").getId(), is(stephane.getId())); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add Spring Data REST 15 @snicoll <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/ Add Spring Security 17 @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/ Spring Security config 18 @snicoll @Configuration public class SecurityConfig extends GlobalAuthenticationConfigurerAdapter { @Override public void init(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("hero").password("hero").roles("HERO", "USER").and() .withUser("user").password("user").roles("USER"); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Fix our test 19 @snicoll @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = DemoApplication.class) @WebIntegrationTest(randomPort = true) public class HomeControllerIntegrationTest { @Value("${local.server.port}") private int port; @Test public void runAndInvokeHome() { String url = "http://localhost:" + port + "/"; String body = new TestRestTemplate("user", "user") .getForObject(url, String.class); assertThat(body, is("Hello jsug")); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add Spring Boot actuator 20 @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add a health indicator 21 @snicoll @Bean public HealthIndicator jsugHealthIndicator() { return () -> { if (new Random().nextBoolean()) { return Health.up().build(); } else { return Health.down().withDetail("Boooo",42).build(); } }; }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add remote shell 22 @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-remote-shell</artifactId> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add a speaker controller 23 @snicoll @Controller public class SpeakerController { private final SpeakerRepository speakerRepository; @Autowired public SpeakerController(SpeakerRepository speakerRepository) { this.speakerRepository = speakerRepository; } @RequestMapping("/ui/speakers/{id}") public String show(@PathVariable Long id, ModelMap model) { Speaker speaker = speakerRepository.findOne(id); if (speaker == null) { throw new SpeakerNotFoundException(); } model.put("speaker", speaker); return "speakers/show"; } @ResponseStatus(HttpStatus.NOT_FOUND) public static class SpeakerNotFoundException extends RuntimeException { } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Best experience with PaaS ! Spring Boot features get a lot done for 12factor.net ! PaaS friendly: fast startup, devops oriented 25 @snicoll $ mvn package $ cf push jsug -p target/jsug-0.0.1-SNAPSHOT.jar $ cf scale jsug -i 4
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Writing your own starter ! Add support for X in Boot with a PR! ! Distribute a client lib in your company ! Standardize usage of component X in a platform ! [your use case here] 27 @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Let’s write our own starter! 28 @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ New auto-config project ! Create a new hello-service-auto-configuration project ! Only one mandatory dependency ! Should contain specific dependencies and auto-configuration classes 29 @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add custom service interface ! This is the part that we’re trying to auto-configure ! In a typical use case, this interface comes from a 3rd party lib 30 @snicoll public interface HelloService { String sayHello(); }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Create a default implementation ! This default implementation will be shipped with the auto-config project but should not be used if the application provides one. 31 @snicoll public class ConsoleHelloService implements HelloService { public String sayHello() { System.out.println("Hello Console"); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Auto-configuration example 32 @snicoll @Configuration @ConditionalOnClass(HelloService.class) public class HelloServiceAutoConfiguration { @ConditionalOnMissingBean @Bean public HelloService helloService() { return new ConsoleHelloService(); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Declare the auto-configuration 33 @snicoll org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ demo.hello.HelloServiceAutoConfiguration // one can order AutoConfigurations // with those annotations @AutoConfigureBefore @AutoConfigureAfter
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add a dependency to our auto-configuration ! Add our auto-config project as a dependency in our main project 34 @snicoll <dependency> <groupId>org.test.jsug</groupId> <artifactId>hello-service-auto-configuration</artifactId> <version>...</version> </dependency>
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Invoke our service when the application starts ! A Hello Service implementation is used on startup ! Running this will use the default implementation 35 @snicoll @Component public class Startup implements CommandLineRunner { @Autowired private HelloService helloService; @Override public void run(String... args) throws Exception { helloService.sayHello(); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Override default (auto-configured) implementation ! Add a @Bean definition in our DemoApplication class ! We provide our own implementation, so the default one won’t be created 36 @snicoll @Bean public HelloService helloService() { return () -> LoggerFactory.getLogger(DemoApplication.class) .info("Hello from logs"); } }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add type-safe properties 37 @snicoll @ConfigurationProperties("hello") public class HelloProperties { private String prefix = "Hello "; private String target; // getters and setters }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Enable properties support 38 @snicoll @EnableConfigurationProperties(HelloProperties.class) @Configuration @ConditionalOnClass(HelloService.class) public class HelloServiceAutoConfiguration {
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ https://spring.io powered by 42 @snicoll github.com/spring-io/sagan
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 44 Learn More. Stay Connected. ! Start your project at start.spring.io ! Getting started guides ! Follow @springboot ! StackOverflow - #spring-boot Twitter: twitter.com/springcentral YouTube: spring.io/video LinkedIn: spring.io/linkedin Google Plus: spring.io/gplus @snicoll