Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Spring Framework 4.1

Spring Framework 4.1

Spring Framework 4.1 news and noteworthy

Sébastien Deleuze

September 23, 2014
Tweet

More Decks by Sébastien Deleuze

Other Decks in Programming

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!