Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 1 Getting Started With Spring Stéphane Nicoll, Spring Framework Committer, Pivotal @snicoll
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 2 https://github.com/snicoll @snicoll Stéphane Nicoll [email protected] #springtn
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ A brief history of Spring ! ! Started in 2002 ! AOP, IoC and DI ! Templates for JDBC/REST/JMS/… ! Abstractions (e.g. for Cache implementations) ! A nice upgrade path for using new JDK features 3
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Aspect Oriented Programming 4 public BookLoan loan(User user, Book book) {! if(user.isLibrarian()) {! // do it! } // else... forbidden! } @Secured("ROLE_LIBRARIAN")! // Spring Security uses AOP to back this! public BookLoan loan(Book book) {! // do it! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ DI with Spring 1/2 6 package org.example.app;! ! @Configuration // used by the container to bootstrap your app! @ComponentScan("org.example.app") // scans packages for Beans! public class AppConfig {! @Bean! public DataSource datasource() {! //...! return ds;! }! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ DI with Spring 2/2 7 @Component // declare components with annotations! public class LoanService {! @Autowired! public LoanService(UserService userService, ! BookRepository bookRepo) {! //...! }! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Framework offers more! 8 ! ! Many other features ! A programming model ! Running in production, everywhere ! Huge active community ! Helps you write modern JVM apps
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Application cache ! ! ! ! Required steps: • Configure a cache store • Check if a Book with that id exists in the cache every time the method is invoked • If so return it • If it does not, execute the method and cache the result before returning the value to the user 9 public Book findById(String id) { ... }!
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Manual application cache 10 package spring;! ! import net.sf.ehcache.CacheManager;! import net.sf.ehcache.Ehcache;! import net.sf.ehcache.Element;! import spring.Book;! import spring.BookRepository;! ! import org.springframework.util.Assert;! ! public class BookRepositoryImpl implements BookRepository {! ! private Ehcache booksCache;! ! @Override! public Book findById(String id) {! // Check if item is not in the cache! Element cacheHit = booksCache.get(id);! if (cacheHit != null) {! return (Book) cacheHit.getObjectValue();! }! ! // Fetch the item if it's not in the cache! Book result = doFindById(id);! if (result != null) {! Element element = new Element(id, result);! booksCache.put(element);! }! return result;! }! ! ! protected Book doFindById(String id) {! // Actual retrieval! }! ! public void setCacheManager(CacheManager cacheManager) {! Assert.notNull(cacheManager, "CacheManager must not be null");! this.booksCache = cacheManager.getEhcache("books");! if (this.booksCache == null) {! throw new IllegalStateException("No cache named 'books' was found");! }! }! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Manual application cache (cont’d) 11 private Ehcache booksCache;! ! @Override! public Book findById(String id) {! // Check if item is not in the cache! Element cacheHit = booksCache.get(id);! if (cacheHit != null) {! return (Book) cacheHit.getObjectValue();! }! ! // Fetch the item if it's not in the cache! Book result = doFindById(id);! if (result != null) {! Element element = new Element(id, result);! booksCache.put(element);! }! return result;! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Manual application cache (cont’d) 12 public void setCacheManager(CacheManager cacheManager) {! Assert.notNull(cacheManager, "CacheManager must not be null");! this.booksCache = cacheManager.getEhcache("books");! if (this.booksCache == null) {! throw new IllegalStateException("No cache named 'books' was found");! }! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Application cache (the spring way) 14 package spring;! ! import org.springframework.cache.annotation.Cacheable;! ! public class BookRepositoryImpl implements BookRepository {! ! @Override! @Cacheable("books")! public Book findById(String id) { ... }! ! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Configuring application cache (the spring way) 15 @Configuration! @EnableCaching! public class ApplicationConfig {! ! @Value("classpath:my-ehcache.xml")! private Resource ehCacheConfig;! ! @Bean! public CacheManager ehCacheManager() {! return new EhCacheCacheManager(! EhCacheManagerUtils.buildCacheManager(ehCacheConfig));! }! ! @Bean! public BookRepository bookRepository() {! return new BookRepositoryImpl();! }! ! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Application cache (summary) ! No cache store specific access in your code • Separation of concern • Library specific APIs do not leak in your code ! Supported cache stores are updated for you • Ehcache, Hazelcast, JCache, Guava, Redis, JDK HashMap, etc. ! Benefit from new features (JCache support in 4.1) • Super easy once the infrastructure is in place 16
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting started guide - Try it out yourself! 17
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ The Web - Spring MVC 22 ! ! Controller/Actions based ! Flexible ! Many points of extension ! Community-driven over the years
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Web Controllers / Views 23 @Controller! @RequestMapping("/loan")! public class BookLoanController {! ! @RequestMapping("/show")! public String showLoan(@RequestParam Long loanId, Model model) {! BookLoan loan = this.repository.findLoan(loanId);! model.add("loan", loan);! return "loans/show";! }! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Web Controllers / REST 24 @RestController("/books")! public class BooksController {! ! @Autowired public BooksController(...) { }! ! @RequestMapping("/{id}")! public Book findBook(@PathVariable String id) {! ! }! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Web Controllers / Exception Handling 25 @ControllerAdvice(annotations = RestController.class)! public class RestControllersAdvice {! ! @ExceptionHandler(BookNotFoundException.class)! public ResponseEntity<String> handleNotFoundException(! BookNotFoundException ex) {! return ResponseEntity.notFound().build();! }! ! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Messaging abstraction 26 ! Initially defined by the Spring Integration project ! Integrated in the core this year and integrated across the board • JMS AMQP, Websocket, …. public class BookSender {! ! @Autowired! public BookSender(MessageSendingOperations<?> sendingOperations) {}! ! public void sendOrder(Book book) {! Message<Book> message = MessageBuilder.withPayload(book)! .setHeader("foo", "bar").build();! sendingOperations.send(message);! }! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Websockets 27 ! ! Introduced in Spring 4.0 ! Foundational Websocket API ! Transparent SockJS layer ! higher-level STOMP messaging
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ STOMP 28 SEND destination:/topic/greetings content-type:text/plain ! Hello World^@ Learn more about this new feature: http://spring.io/guides/gs/messaging-stomp-websocket/
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ STOMP example - HTTP with push notifications X @Controller! public class AccountController {! ! @Autowired private SimpMessagingTemplate template;! ! @RequestMapping(value="/accounts", method=POST)! public void save(@Valid Account account) { ! // notify connected users! this.template.convertAndSend("/topic/accounts", account);! } ! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Architecture of an example app X SUBSCRIBE /topic/accounts SUBSCRIBE /topic/accounts
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Architecture of an example app X SEND /topic/accounts POST /accounts
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Architecture of an example app X MESSAGE MESSAGE MESSAGE MESSAGE
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 29 “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/ Spring portfolio & Spring platform 30 spring.io/platform
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Boot ! ! Single point of focus ! Get you 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 32
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 33
Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting started, ! really quick Spring Boot
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Simple Groovy App ! Let’s create a very simple hero.groovy app ! ! ! ! ! ! ! Boot CLI post process such script to add things such as import statements X class HomeController { ! ! @RequestMapping("/")! String home() {! 'Hello Tunis'! }! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring 4 - @Conditional 37 @Conditional(CustomCondition.class)! @Configuration! public class AppConfiguration {! ! }
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 38 @Configuration! @EnableAutoConfiguration! class HomeController {! ! public static void main(String[] args) {! SpringApplication.run(MyApplication.class, args);! }! }
Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Packaging ! production and cloud-ready Spring Boot
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Packaging for production ! ! ! Externalizing Configuration to Properties • Just put application.properties in your classpath or next to you jar, e.g. ! ! ! • Can be overridden: java -jar hero.jar —server.port=6080 • Can be injected: java -jar hero.jar —conference=Spring 40 server.port = 9000 @Value("${conference}")! private String conference; $ spring jar hero.jar hero.groovy! $ java -jar hero.jar
Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Getting started, ! with Java Spring Boot
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Simple Java app ! Create a skeleton project on http://start.spring.io ! Choose the web option and download the project ! Add a simple controller alongside the app X @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/ Testing ! Testing with a random port using @IntegrationTest X @RunWith(SpringJUnit4ClassRunner.class)! @SpringApplicationConfiguration(classes = Application.class)! @WebAppConfiguration! @IntegrationTest("server.port=0")! public class HomeControllerIntegrationTest {! ! @Value("${local.server.port}")! private int port;! ! @Test! public void runAndTestHttpEndpoint() {! String url = "http://localhost:" + this.port + "/";! String body = new RestTemplate().getForObject(url, String.class);! assertEquals("Hello World!", body);! } ! }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Boot Starters ! ! ! ! ! Standard Maven POMs ! Define dependencies that we recommend 42 <dependency>! <groupId>org.springframework.boot</groupId>! <artifactId>spring-boot-starter-web</artifactId>! </dependency>
Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring Data Spring Boot
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Using Spring Data MongoDB ! Add spring-boot-starter-data-mongodb ! Add a simple UserAccount entity with some obvious attributes ! A simple repository interface can be defined as follows: ! ! ! ! ! We can easily add a test for that, too. X @Repository! public interface UserAccountRepository extends MongoRepository<UserAccount, Long> {! ! UserAccount findByUsername(String username);! ! Collection<UserAccount> findByFamilyName(String familyName);! }
Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Exposing the repository Spring Boot
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Using Spring Data Rest ! Add spring-boot-starter-data-rest ! Update the repository as follows ! ! ! ! ! ! We can change the baseURI by overriding RepositoryRestMvcConfiguration X @RepositoryRestResource(path = "users")! public interface UserAccountRepository extends MongoRepository<UserAccount, Long> {! ! @RestResource(path = "username")! UserAccount findByUsername(@Param("name") String username);! ! List<UserAccount> findByFamilyName(@Param("name") String familyName);! }
Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Security integration Spring Boot
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Using Spring Security ! Add spring-boot-starter-security ! Create an authentication manager to secure the endpoints with custom users ! ! ! ! ! ! ! Method security can be added as well X @Configuration! static class AuthenticationSecurity 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/ Spring Actuator ! Adds common non-functional features to your application • MVC endpoints • JMX support ! Examples • Health check • Environment information • Autoconfig • Metrics • … 46
Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Adding common non-functional features Spring Boot
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ If we had more time… 48 Building a war Spring Batch Spring Integration Spring AMQP Spring JMS SpringApplicationBuilder CommandLineRunner Profile YAML support @ConfigurationProperties Logging Static resources Thymeleaf Websocket Redis Disabling auto-config CLI customization Servlet container customization
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Your next app? JDK8 + Spring Framework 4 + Spring Boot 49
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 50 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