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
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
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;! }! }
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) {! //...! }! }
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
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) { ... }!
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");! }! }! }
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;! }
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");! }! }
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
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
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 message = MessageBuilder.withPayload(book)! .setHeader("foo", "bar").build();! sendingOperations.send(message);! }! }
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/
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
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Architecture of an example app X SEND /topic/accounts POST /accounts
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Architecture of an example app X MESSAGE MESSAGE MESSAGE MESSAGE
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
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
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
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'! }! }
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);! }! }
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
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!";! ! }! }
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);! } ! }
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 findByUsername(String username);! ! Collection findByFamilyName(String familyName);! }
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 {! ! @RestResource(path = "username")! UserAccount findByUsername(@Param("name") String username);! ! List findByFamilyName(@Param("name") String familyName);! }
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");! }! }
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
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
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Your next app? JDK8 + Spring Framework 4 + Spring Boot 49