Spring Framework 4.1

Spring Framework 4.1

Spring Framework 4.1 news and noteworthy

5778521f67d80de0ee3b213e4f159a59?s=128

Sébastien Deleuze

September 23, 2014
Tweet

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/ 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
  2. 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
  3. 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
  4. 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
  5. @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");     }   ! }
  6. @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");     }   ! }
  7. @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()  {  }
 ! }
  8. 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"}
  9. @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"}) <script  type="application/javascript"                  src="http://foo.com/users/1234?callback=parseResponse">   </script>
  10. java.util.Optional method argument (JDK 1.8) 10 @RestController   public  class

     TestController  {   !    @RequestMapping("/test")      public  void  handle(@RequestParam  Optional<LocalDate>  date)  {              StringBuilder  sb  =  new  StringBuilder("Date:  ");              date.ifPresent(s  -­‐>  sb.append(s.toString()));              //  ...      }   
 }
  11. 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  -­‐>  ...);
  12. 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
  13. ResponseEntity builder 13 public  ResponseEntity<String>  handle()  {      

     String  body  =  "Hello  World";        HttpHeaders  headers  =  new  HttpHeaders()        headers.setLocation(location);        return  new  ResponseEntity<String>(body,  headers,  HttpStatus.CREATED);   }   
 public  ResponseEntity<String>  handle()  {        URI  location  =  ...;        return  ResponseEntity.created(location).body("Hello  World");   }   Before After
  14. 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
  15. 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)
  16. 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
  17. 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
  18. “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
  19. Groovy Markup Templating 19 § MarkupTemplateEngine in Groovy 2.3 (XML,

    XHTML, HTML5) § DRY markup, Groovy DSL yieldUnescaped  '<!DOCTYPE  html>'                                                                               html(lang:'en')  {                                                                                                                    head  {                                                                                                                                          title('My  page')                                                                                                      }                                                                                                                                            body  {                                                                                                                                          p('This  is  an  example  of  HTML  contents')                                                      }                                                                                                                                     }
  20. 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();      }   }   !
  21. New in MVC Namespace: view resolvers 21 ! <mvc:view-­‐resolvers>  

       <mvc:content-­‐negotiation>              <mvc:default-­‐views>                      <bean  class="org.springframework.web..MappingJackson2JsonView"/>              </mvc:default-­‐views>      </mvc:content-­‐negotiation>      <mvc:jsp  />   </mvc:view-­‐resolvers>   ! !
  22. 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);        }   }
  23. MVC Namespace: enhanced view controllers 23 ! <mvc:redirect-view-controller path="/old" redirect-url="/new"

    context-relative="false" status-code="308" keep-query-params="true" /> ! <mvc:status-controller path="/bad" status-code="404" /> !
  24. 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
  25. 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
  26. WebSocket Support 26 SockJS websocket / xhr-streaming / eventsource /

    xhr / ... WebSocket API STOMP @Controller spring-messaging spring-websocket
  27. Example STOMP Message 27 
 SEND destination:/topic/greetings content-type:text/plain ! Hello

    world! ! ! 
 COMMAND header1:value1 header2:value2 ! Body ! !
  28. 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);      }   ! }
  29. @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)  {              //  ...      }   ! }
  30. 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
  31. Spring 4.0 Messaging infrastructure 1/2 31 public  class  OrderMessageHandler  {

            public  OrderStatus  handleMessage(Order  order)             {                    //  Order  processing       return  new  OrderStatus(...);                         }             }
  32. Spring 4.0 Messaging infrastructure 2/2 32 <?xml  version="1.0"  encoding="UTF-­‐8"?>  

    <beans  xmlns="http://www.springframework.org/schema/beans"          xmlns:xsi="http://www.w3.org/2001/XMLSchema-­‐instance"                      xmlns:jms="http://www.springframework.org/schema/jms"                      xsi:schemaLocation="http://www.springframework.org/schema/beans                      http://www.springframework.org/schema/beans/spring-­‐beans.xsd                      http://www.springframework.org/schema/jms                      http://www.springframework.org/schema/jms/spring-­‐jms.xsd">                     <jms:listener-­‐container  message-­‐converter="jmsMessageConverter">                   <jms:listener  destination="test.order"  ref="orderMessageHandler"  method="handleMessage"/>                             </jms:listener-­‐container>                     <bean  id="orderMessageHandler"  class="foo.bar.OrderMessageHandler"/>                     <bean  id="jmsMessageConverter"                      class="org.springframework.jms.support.converter.MappingJackson2MessageConverter">                               <property  name="targetType"  value="TEXT"/>                               <property  name="typeIdPropertyName"  value="__type"/>                             </bean>               </beans>
  33. 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(...);                         }             }
  34. 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;                                 }                 ! }
  35. 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)  {}   !
  36. 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<OrderStatus>  processOrder(Message<Order>  order)  {}
  37. JmsMessagingTemplate 37 § Similar to JmsTemplate, using o.s.messaging.Message § Exception

    translation § No JMS API involved at all Message<Order>  orderMessage  =  MessageBuilder.       withPayload(order).setHeader("orderType",  "sell").build();                       messagingTemplate.send("order",  orderMessage);
  38. 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
  39. 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)  {  …  }                 }  
  40. 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;                         }             }  
  41. 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)  {  …  }             ! }  
  42. 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)  {  …  }                 }  
  43. 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)  {  …  }                 }
  44. 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
  45. 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
  46. 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!