Slide 1

Slide 1 text

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/ Spring Framework 4.1 Sébastien Deleuze, Spring Framework commiter, Pivotal @sdeleuze Built from SpringOne slides for Brian Clozel, Juergen Hoeller, Rossen Stoyanchev and Stéphane Nicoll

Slide 2

Slide 2 text

Spring Framework 4.1 2 § Minimum requirements § Java 6+ § Java EE 6+ (but still Servlet 2.5 compliant) § Recommended § Java 8 § Java EE 7 § Version status § 4.1: current § 4.0: maintenance § 3.2: EOL

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Spring MVC annotations 4 § @MVC very popular and evolving through feedback § Started in 2.5 + REST in 3.0 § Many refinements in 3.1 and 3.2 § WebSocket messaging in 4.0 § Continues to evolve in 4.1

Slide 5

Slide 5 text

@Controller 5 § The central component stereotype in Spring MVC § Contains @RequestMapping methods § Supporting methods:
 @ModelAttribute/@InitBinder/@ExceptionHandler @Controller   class  UserController  {   !   @RequestMapping("/user")     @ResponseBody     public  User  getUser()  {          return  new  User("eric",  "7!#H2");     }   ! }

Slide 6

Slide 6 text

@RestController 6 § Another component stereotype § Meta-annotated with @Controller + @ResponseBody § @ResponseBody “inherited” on method level @RestController   class  UserController  {   !   @RequestMapping("/user")     public  User  getUser()  {          return  new  User("eric",  "7!#H2");     }   ! }

Slide 7

Slide 7 text

@ControllerAdvice 7 § “Global” supporting methods:
 @ExceptionHandler, @ModelAttribute, @InitBinder § Auto-detected, just declare it as a bean § Fine-grained control
 @ControllerAdvice(basePackageClasses=MyController.class) @ControllerAdvice   class  GlobalControllerExceptionHandler  {   !        @ResponseStatus(HttpStatus.CONFLICT)          @ExceptionHandler(DataIntegrityViolationException.class)          public  void  handleConflict()  {  }
 ! }

Slide 8

Slide 8 text

Jackson @JsonView Support 8 interface  PublicView  {};   ! class  User  {   
   @JsonView(PublicView.class)     private  String  username
   private  String  password;   !   ...   
 } @RestController   class  UserController  {   !   @RequestMapping("/user")     @JsonView(PublicView.class)     public  User  getUser()  {          return  new  User("eric",  "7!#H2");     }   ! }   ! ! {"username":  "eric"}

Slide 9

Slide 9 text

@ControllerAdvice   public  class  JsonpAdvice   extends  AbstractJsonpResponseBodyAdvice  {     public  JsonpAdvice()  {       super("callback");     }     } JSONP support 9 Simply declare as Spring-managed bean: parseResponse({"username":  "eric",  "password":  "7!#H2"})  

Slide 10

Slide 10 text

java.util.Optional method argument (JDK 1.8) 10 @RestController   public  class  TestController  {   !    @RequestMapping("/test")      public  void  handle(@RequestParam  Optional  date)  {              StringBuilder  sb  =  new  StringBuilder("Date:  ");              date.ifPresent(s  -­‐>  sb.append(s.toString()));              //  ...      }   
 }

Slide 11

Slide 11 text

ListenableFuture return type 11 § ListenableFuture
 together with AsyncRestTemplate § Supported on @RequestMapping methods in 4.1
 return instead of DeferredResult § Java 8 lambda compatible in 4.1
 listenableFuture.addCallback(result  -­‐>  ...  ,  ex  -­‐>  ...);

Slide 12

Slide 12 text

HttpMessageConverter Additions 12 § Gson
 lighter footprint (vs Jackson) ; used in Spring Android § Google Protocol Buffers
 effective inter-service communication data protocol § Jackson / XML
 just add jackson-dataformat-xml to classpath
 support @JsonView
 use Jackson and JAXB annotations
 @XmlRootElement not needed anymore

Slide 13

Slide 13 text

ResponseEntity builder 13 public  ResponseEntity  handle()  {        String  body  =  "Hello  World";        HttpHeaders  headers  =  new  HttpHeaders()        headers.setLocation(location);        return  new  ResponseEntity(body,  headers,  HttpStatus.CREATED);   }   
 public  ResponseEntity  handle()  {        URI  location  =  ...;        return  ResponseEntity.created(location).body("Hello  World");   }   Before After

Slide 14

Slide 14 text

RequestEntity builder 14 ! HttpHeaders  headers  =  new  HttpHeaders();   headers.setAccept(MediaType.APPLICATION_JSON);   HttpEntity  httpEntity  =  new  HttpEntity("Hello  World",  headers);   restTemplate.exchange(uri,  HttpMethod.POST,  httpEntity,  String.class);   ! ! ! ! ! restTemplate.exchange(   RequestEntity.post(uri)   .accept(MediaType.APPLICATION_JSON)   .body("Hello  World"),  String.class);   ! ! Before After

Slide 15

Slide 15 text

Static Resource Handling 15 § Major Spring Framework 4.1 feature § Design to be used with Grunt/Gulp/etc. § Two new auxiliary strategies forming two chains • ResourceResolver • ResourceTransformer § ResourceUrlProvider 
 determine “public” resource URL (e.g. insert version)

Slide 16

Slide 16 text

Built-in Resolvers 16 § PathResourceResolver
 simple path lookup under configured locations § VersionResourceResolver 
 resolution with version in URL path § GzipResourceResolver 
 lookup with .gz extension when “Accept-Encoding: gzip” § CachingResourceResolver 
 caching of resolved resource

Slide 17

Slide 17 text

Built-in Transformers 17 § CssLinkResourceTransformer 
 update links in CSS file (e.g. insert version) § AppCacheManifestTransformer 
 update links in HTML5 AppCache manifest
 insert comment with content-based hash § CachingResourceTransformer 
 caching of transformed resource

Slide 18

Slide 18 text

“Fingerprinting” URLs (content-based version) 18 ! boolean  useResourceCache  =  !this.environment.acceptsProfiles("dev");   VersionResourceResolver  resolver  =  new  VersionResourceResolver();   resolver.addContentVersionStrategy("/**");   registry.addResourceHandler("/**").addResourceLocations(locations)              .resourceChain(useResourceCache).addResolver(resolver);   ! ! ! ! Example URL: /css/font-­‐awesome.min-­‐7fbe76cdac.css

Slide 19

Slide 19 text

Groovy Markup Templating 19 § MarkupTemplateEngine in Groovy 2.3 (XML, XHTML, HTML5) § DRY markup, Groovy DSL yieldUnescaped  ''                                                                               html(lang:'en')  {                                                                                                                    head  {                                                                                                                                          title('My  page')                                                                                                      }                                                                                                                                            body  {                                                                                                                                          p('This  is  an  example  of  HTML  contents')                                                      }                                                                                                                                     }

Slide 20

Slide 20 text

New in MVC Java Config: view resolvers 20 @Configuration   @EnableWebMvc   public  class  WebConfig  extends  WebMvcConfigurerAdapter  {      @Override      public  void  configureViewResolvers(ViewResolverRegistry  registry)  {              registry.enableContentNegotiation(new  MappingJackson2JsonView());              registry.jsp();      }   }   !

Slide 21

Slide 21 text

New in MVC Namespace: view resolvers 21 !                                                                         ! !

Slide 22

Slide 22 text

MVC Java Config: enhanced view controllers 22 ! @Configuration   @EnableWebMvc   public  class  WebConfig  extends  WebMvcConfigurerAdapter  {        @Override        public  void  addViewControllers(ViewControllerRegistry  registry)  {                registry.addRedirectViewController("/old/path",  "/new/path");                registry.addStatusController("/path",  HttpStatus.NOT_FOUND);        }   }

Slide 23

Slide 23 text

MVC Namespace: enhanced view controllers 23 ! ! !

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

WebSocket Support 25 § Introduced in 4.0 § Support JSR 356 compliant runtimes (and more …) § Transparent SockJS layer § fall back on HTTP streaming or long polling § wide range of browser versions § Higher-level STOMP messaging
 enables @Controller-style programming model

Slide 26

Slide 26 text

WebSocket Support 26 SockJS websocket / xhr-streaming / eventsource / xhr / ... WebSocket API STOMP @Controller spring-messaging spring-websocket

Slide 27

Slide 27 text

Example STOMP Message 27 
 SEND destination:/topic/greetings content-type:text/plain ! Hello world! ! ! 
 COMMAND header1:value1 header2:value2 ! Body ! !

Slide 28

Slide 28 text

HTTP Requests with Push Notifications 28 @Controller   public  class  AccountController  {   !    @Autowired      private  SimpMessagingTemplate  template;   !    @RequestMapping(value="/accounts",  method=RequestMethod.POST)      public  void  save(@Valid  Account  account)  {              //  ...              //  notify  connected  users              this.template.convertAndSend("/topic/accounts",  account);      }   ! }

Slide 29

Slide 29 text

@Controller HTTP and WebSocket Processing 29 @Controller   public  class  PortfolioController  {   !    @MessageMapping("/trade")      public  void  executeTrade(Trade  trade)  {              //  ...      }   !    @RequestMapping(value="/trades/{id}",  method=RequestMethod.GET)      public  Trade  getTrade(Integer  id)  {              //  ...      }   ! }

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Spring 4.0 Messaging infrastructure 1/2 31 public  class  OrderMessageHandler  {         public  OrderStatus  handleMessage(Order  order)             {                    //  Order  processing       return  new  OrderStatus(...);                         }             }

Slide 32

Slide 32 text

Spring 4.0 Messaging infrastructure 2/2 32                                                                                                                                                                                                                  

Slide 33

Slide 33 text

Spring 4.1 Messaging infrastructure 1/2 33 @Component   public  class  OrderMessageHandler  {         @JmsListener(destination  =  "test.order")               public  OrderStatus  process(Order  order)  {                 //  Order  processing                           return  new  OrderStatus(...);                         }             }

Slide 34

Slide 34 text

Spring 4.1 Messaging infrastructure 2/2 34 @EnableJms   @Configuration   public  class  ApplicationConfig  {   !   @Bean                   public  JmsListenerContainerFactory>  jmsListenerContainerFactory(ConnectionFactory                 connectionFactory)  {       DefaultJmsListenerContainerFactory  factory  =  new  DefaultJmsListenerContainerFactory();                                   factory.setConnectionFactory(connectionFactory);                                   factory.setMessageConverter(jmsMessageConverter());                                   return  factory;                                 }                 !   @Bean                   public  MessageConverter  jmsMessageConverter()  {                     MappingJackson2MessageConverter  converter  =  new  MappingJackson2MessageConverter();                                   converter.setTargetType(MessageType.TEXT);                                   converter.setTypeIdPropertyName("__type");                                   return  converter;                                 }                 ! }

Slide 35

Slide 35 text

Flexible method signatures 35 @JmsListener(destination  =  "order")   public  void  processOrder(Order  order)  {}       @JmsListener(destination  =  "order")   public  void  processOrder(Session  session,  TextMessage  textMessage)  {}       @JmsListener(destination  =  "order")   public  void  processOrder(@Valid  Order  order)  {}       @JmsListener(destination  =  "order")   public  void  processOrder(Order  order,  @Header  String  orderType)  {}       @JmsListener(destination  =  "order")   @SendTo("orderStatus")   public  OrderStatus  processOrder(Order  order)  {}   !

Slide 36

Slide 36 text

Messaging abstraction 36 § Introduced in Spring Framework 4.0 § org.springframework.messaging.Message is a generic message representation with headers and a body
 ! ! § Full access to body and headers for both inbound and outbound messages @JmsListener(destination  =  "order")   @SendTo("orderStatus")   public  Message  processOrder(Message  order)  {}

Slide 37

Slide 37 text

JmsMessagingTemplate 37 § Similar to JmsTemplate, using o.s.messaging.Message § Exception translation § No JMS API involved at all Message  orderMessage  =  MessageBuilder.       withPayload(order).setHeader("orderType",  "sell").build();                       messagingTemplate.send("order",  orderMessage);

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

Caching abstraction 39 public  class  BookRepository  {         @Cacheable("books")               public  Book  findById(String  id)  {  …  }                   @Cacheable(value  =  "books",  key  =             "T(foo.caching.BookIdResolver).resolveBookId(#isbn)")     public  Book  findById(ISBN  isbn)  {  …  }                   @CachePut(value  =  "books",  key  =  "#book.id")               public  Book  update(Book  book)  {  …  }                   @CacheEvict(value  =  "books")               public  void  delete(String  id)  {  …  }                 }  

Slide 40

Slide 40 text

Caching abstraction 2/2 40 @Configuration   @EnableCaching   public  class  ApplicationConfig  {         @Bean               public  CacheManager  cacheManager()  {                 ConcurrentMapCacheManager  cacheManager  =  new  ConcurrentMapCacheManager();                           cacheManager.setCacheNames(Arrays.asList("books,  cars"));                           return  cacheManager;                         }             }  

Slide 41

Slide 41 text

Class level customizations 41 @CacheConfig("books")   public  class  BookRepository  {         @Cacheable               public  Book  findById(String  id)  {  …  }                   @Cacheable(key  =  "T(foo.caching.BookIdResolver).resolveBookId(#isbn)")               public  Book  findById(ISBN  isbn)  {  …  }                   @CachePut(key  =  "#book.id")               public  Book  update(Book  book)  {  …  }                   @CacheEvict               public  void  delete(String  id)  {  …  }             ! }  

Slide 42

Slide 42 text

Method level customizations 42 @CacheConfig("books")   public  class  BookRepository  {         @Cacheable               public  Book  findById(String  id)  {  …  }                   @Cacheable(keyGenerator  =  "isbnKeyGenerator")               public  Book  findById(ISBN  isbn)  {  …  }                   @CachePut(key  =  "#book.id")               public  Book  update(Book  book)  {  …  }                   @CacheEvict               public  void  delete(String  id)  {  …  }                 }  

Slide 43

Slide 43 text

JCache (JSR-107) support 43 @CacheDefaults(cacheName  =  "books")   public  class  BookRepository  {         @CacheResult               public  Book  findById(String  id)  {  …  }                   @CacheResult(cacheKeyGenerator  =  IsbnCacheKeyGenerator.class)               public  Book  findById(ISBN  isbn)  {  …  }                   @CachePut               public  void  update(String  id,  @CacheValue  Book  book)  {  …  }                   @CacheRemove               public  void  delete(String  id)  {  …  }                 }

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

Huge gains for enterprise grade application 45 § ResolvableType optimizations § Benchmark in order to be in the same context than big applications § Results • Before: 8000 us • After: 120 us

Slide 46

Slide 46 text

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/ Thanks!