Download as pdf or txt
Download as pdf or txt
You are on page 1of 44

From Zero to Hero with Spring Boot

Stphane Nicoll
Pivotal
Unless otherwise indicated, these slides are 2013-2014Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Hello!

@snicoll
https://github.com/snicoll
snicoll@pivotal.io

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Spring Boot lets you pair-program with the Spring team.

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

Josh Long, @starbuxman

@snicoll

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

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

_ Spring Boot is NOT

!
!
!
!

A prototyping tool
Only for embedded container apps
Sub-par Spring experience
For Spring beginners only

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

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)

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Lets get started!

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Getting Started Really Quickly

@RestController
public class HomeController {
@Value("${conference.name:jsug}")
private String conference;
@RequestMapping("/")
public String home() {
return "Hello " + conference;
}
}
9

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

First integration test


@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"));
}
}

10

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add Spring Data JPA

<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>

11

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add a Speaker entity


@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
}
12

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add a Speaker Repository

public interface SpeakerRepository


extends CrudRepository<Speaker, Long> {
Speaker findByTwitter(String twitter);
Collection<Speaker> findByLastName(String lastName);
}

13

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Test that repository


@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()));
}
}

14

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add Spring Data REST

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>

15

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

RESTful repository

public interface SpeakerRepository


extends CrudRepository<Speaker, Long> {
@RestResource(path = "by-twitter")
Speaker findByTwitter(@Param("id") String twitter);
Collection<Speaker> findByLastName(@Param("name") String lastName);
}

16

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add Spring Security

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

17

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Spring Security config

@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");
}
}

18

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Fix our test


@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"));
}
}
19

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add Spring Boot actuator

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

20

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add a health indicator


@Bean
public HealthIndicator jsugHealthIndicator() {
return () -> {
if (new Random().nextBoolean()) {
return Health.up().build();
}
else {
return Health.down().withDetail("Boooo",42).build();
}
};
}

21

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add remote shell

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-remote-shell</artifactId>
</dependency>

22

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add a speaker controller


@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 {
}
}
23

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Create speaker show view

<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>

24

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Best experience with PaaS

$ mvn package
$ cf push jsug -p target/jsug-0.0.1-SNAPSHOT.jar
$ cf scale jsug -i 4

! Spring Boot features get a lot done for 12factor.net


! PaaS friendly: fast startup, devops oriented

25

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Starter POMs
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
compile("org.springframework.boot:spring-boot-starter-web")

! standard POM / gradle files: define dependencies


! many available: batch, integration, web, ampq
! starter data-jpa = spring-data-jpa + hibernate

26

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

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

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Lets write our own starter!

28

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

New auto-config project

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

! Create a new hello-service-auto-configuration project


! Only one mandatory dependency
! Should contain specific dependencies and auto-configuration classes

29

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add custom service interface

public interface HelloService {


String sayHello();
}

! This is the part that were trying to auto-configure


! In a typical use case, this interface comes from a 3rd party lib

30

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Create a default implementation

public class ConsoleHelloService implements HelloService {


public String sayHello() {
System.out.println("Hello Console");
}
}

! This default implementation will be shipped with the auto-config project but
should not be used if the application provides one.
31

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Auto-configuration example
@Configuration
@ConditionalOnClass(HelloService.class)
public class HelloServiceAutoConfiguration {
@ConditionalOnMissingBean
@Bean
public HelloService helloService() {
return new ConsoleHelloService();
}
}
32

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Declare the auto-configuration

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
demo.hello.HelloServiceAutoConfiguration

// one can order AutoConfigurations


// with those annotations
@AutoConfigureBefore
@AutoConfigureAfter

33

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add a dependency to our auto-configuration

<dependency>
<groupId>org.test.jsug</groupId>
<artifactId>hello-service-auto-configuration</artifactId>
<version>...</version>
</dependency>

! Add our auto-config project as a dependency in our main project

34

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Invoke our service when the application starts


@Component
public class Startup implements CommandLineRunner {
@Autowired private HelloService helloService;
@Override
public void run(String... args) throws Exception {
helloService.sayHello();
}
}

! A Hello Service implementation is used on startup


! Running this will use the default implementation
35

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Override default (auto-configured) implementation

@Bean
public HelloService helloService() {
return () ->
LoggerFactory.getLogger(DemoApplication.class)
.info("Hello from logs");
}
}

! Add a @Bean definition in our DemoApplication class


! We provide our own implementation, so the default one wont be created
36

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Add type-safe properties

@ConfigurationProperties("hello")
public class HelloProperties {
private String prefix = "Hello ";
private String target;
// getters and setters
}

37

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Enable properties support

@EnableConfigurationProperties(HelloProperties.class)
@Configuration
@ConditionalOnClass(HelloService.class)
public class HelloServiceAutoConfiguration {

38

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Use type-safe properties


public class ConsoleHelloService implements HelloService {
@Autowired
private HelloProperties properties;
@Override
public void run(String... strings) throws Exception {
System.out.println(properties.getPrefix() + " " +
properties.getTarget());
}
}
39

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Generate properties meta-data


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

! annotation processor that generates meta-data


! uses Javadoc to build keys descriptions
! default values detected
! manual declaration allowed
40

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

Document properties
@ConfigurationProperties("hello")
public class HelloProperties {
/**
* Prefix of welcome message.
*/
private String prefix = "Hello ";
/**
* Target of welcome message.
*/
private String target;
// getters and setters
}
41

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

https://spring.io powered by

github.com/spring-io/sagan

42

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

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

@springboot

43

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@springcentral
@snicoll

Learn More. Stay Connected.

! Start your project at start.spring.io

Twitter: twitter.com/springcentral

! Getting started guides

YouTube: spring.io/video

! Follow @springboot

LinkedIn: spring.io/linkedin

! StackOverflow - #spring-boot

Google Plus: spring.io/gplus

44

Unless otherwise indicated, these slides are 2013-2015Pivotal Software, Inc. and licensedunder a

Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/

@snicoll

You might also like