Upgrade to Pro — share decks privately, control downloads, hide ads and more …

From Zero to Hero with Spring Boot (extended version)

From Zero to Hero with Spring Boot (extended version)

Spring Boot introduction (extended version, 2h format).

Stéphane Nicoll

May 08, 2015
Tweet

More Decks by Stéphane Nicoll

Other Decks in Programming

Transcript

  1. Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software,

    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
  2. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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]
  3. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 3 @snicoll
  4. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  5. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  6. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  7. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  8. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Let’s get started! 8 @snicoll
  9. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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; } }
  10. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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")); } }
  11. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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>
  12. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Add a Speaker entity 12 @snicoll @Entity public class Speaker { @GeneratedValue @Id private Long id; private String firstName; private String lastName; private String twitter; @Column(columnDefinition = "TEXT") private String bio; public Speaker(String firstName, String lastName, String twitter) { // initialize attributes } // getters and setters }
  13. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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); }
  14. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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())); } }
  15. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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>
  16. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ RESTful repository 16 @snicoll public interface SpeakerRepository extends CrudRepository<Speaker, Long> { @RestResource(path = "by-twitter") Speaker findByTwitter(@Param("id") String twitter); Collection<Speaker> findByLastName(@Param("name") String lastName); }
  17. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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>
  18. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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"); } }
  19. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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")); } }
  20. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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>
  21. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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(); } }; }
  22. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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>
  23. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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 { } }
  24. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Create speaker show view 24 @snicoll <html xmlns:th="http://www.thymeleaf.org"> <head> <title th:text="${speaker.firstName} + ' ' + ${speaker.lastName}">View speaker</title> </head> <body> <div class="profile"> <h1 class="name" th:text="${speaker.firstName} + ' ' + ${speaker.lastName}">Stephane Nicoll</h1> <div> <p th:text="${speaker.bio}">Sample Biography.</p> </div> <div> <a th:href="'http://twitter.com/' + ${speaker.twitter}" class="twitter" th:text="'@' + $ {speaker.twitter}">@snicoll</a> </div> </div> </body> </html>
  25. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  26. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Starter POMs ! standard POM / gradle files: define dependencies ! many available: batch, integration, web, ampq… ! starter data-jpa = spring-data-jpa + hibernate 26 @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> compile("org.springframework.boot:spring-boot-starter-web")
  27. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  28. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  29. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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>
  30. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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(); }
  31. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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"); } }
  32. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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(); } }
  33. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  34. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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>
  35. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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(); } }
  36. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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");
 } }
  37. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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 }
  38. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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 {
  39. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Use type-safe properties 39 @snicoll public class ConsoleHelloService implements HelloService { @Autowired private HelloProperties properties; @Override public void run(String... strings) throws Exception { System.out.println(properties.getPrefix() + " " + properties.getTarget()); } }
  40. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Generate properties meta-data ! annotation processor that generates meta-data ! uses Javadoc to build keys descriptions ! default values detected ! manual declaration allowed 40 @snicoll <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
  41. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Document properties 41 @snicoll @ConfigurationProperties("hello") public class HelloProperties { /** * Prefix of welcome message. */ private String prefix = "Hello "; /** * Target of welcome message. */ private String target; // getters and setters }
  42. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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
  43. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Links ! https://projects.spring.io/spring-boot/ ! https://github.com/spring-projects/spring-boot ! https://spring.io/guides ! https://spring.io/blog ! https://spring.io/questions ! https://www.youtube.com/user/SpringSourceDev 43 @snicoll @springboot @springcentral
  44. Unless otherwise indicated, these slides are © 2013-2015 Pivotal Software,

    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