SlideShare a Scribd company logo
Spring 4
Ken Coenen, Dieter Hubau, Tim De Grande, Steve De Zitter,
Serguei Storojenko, Andreas Evers
Agenda
Steve De Zitter
Java SDK & EE support
Tim De Grande
Spring Core
Serguei Storojenko
Spring WebMVC
Ken Coenen
WebSockets and Messaging
Dieter Hubau
Testing improvements
Andreas Evers
Spring Core
Java 8 support
Java 8 features in Spring 4/4.1
▪ Lambda expressions
▪ Method references
▪ JSR-310 Date/Time Support
▪ Repeatable annotations
▪ Parameter name discovery
▪ Java.util.Optional
▪ Related new injection features
▪ Ordering, @Priority, Generic types
Java 8 lamda conventions
▪ Functional interfaces
▪ Typically callback interfaces such as Runnable/Callable
▪ Common functional interfaces in java.util.function
▪ Function, Predicate, Supplier
▪ Used extensively in Java8 Streams Api
Lambda conventions in Spring api’s
▪ TransactionTemplate with TransactionCallback
▪ JdbcTemplate/JdbcOperations with PreparedStatementSetter
▪ JdbcTemplate/JdbcOperations with RowMapper
▪ TaskExecutor
▪ ListenableFuture
Lambdas JdbcOperations example
▪ PreparedStatementSetter and RowMapper pre Java 8
List<Beer> beers = jdbcOperations.query(SELECT_BEER_BY_NAME_AND_ALCOHOL_PERCENTAGE,
new PreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps) throws SQLException{
ps.setString(1, "%" + name + "%");
ps.setBigDecimal(2, alcoholPercentage);
}
},
new RowMapper<Beer>() {
@Override
public Beer mapRow(ResultSet rs, int rowNum) throws SQLException{
return new Beer(rs.getLong("id"), rs.getString("name"),
rs.getString("description"),
rs.getBigDecimal("alcoholPercentage"),
rs.getTimestamp("modifiedTimestamp”));
}
}
);
Lambdas JdbcOperations example
▪ PreparedStatementSetter and RowMapper with lambdas
List<Beer> beers = jdbcOperations.query(
SELECT_BEER_BY_NAME_AND_ALCOHOL_PERCENTAGE,
ps -> {
ps.setString(1, "%" + name + "%");
ps.setBigDecimal( 2, alcoholPercentage);
},
(rs, rowNum) -> new Beer(rs.getLong( "id"),
rs.getString("name"),
rs.getString("description"),
rs.getBigDecimal( "alcoholPercentage”))
);
Lambdas TaskExecutor example
▪ TaskExecutor (ThreadPoolTaskExecutor) pre Java 8
return threadPoolTaskExecutor.submitListenable( new Callable<List<Beer>>() {
@Override
public List<Beer> call() throws Exception {
return beerRepository.getAllBeers();
}
});
▪ TaskExecutor with lambdas
return threadPoolTaskExecutor.submitListenable(
() -> beerRepository.getAllBeers()
);
ListenableFuture example
▪ ListenableFuture pre Java 8 with ListenableFutureCallback
ListenableFuture<List<Beer>> future =
taskExecutorService.getBeersAsyncUsingTaskExecutor();
future.addCallback( new ListenableFutureCallback<List<Beer>>() {
@Override
public void onFailure(Throwable throwable) {
//Handle Failure
}
@Override
public void onSuccess(List<Beer> beers) {
//Handle success
}
});
ListenableFuture example
▪ ListenableFuture pre Java 8 with success and failure callback
ListenableFuture<List<Beer>> future =
taskExecutorService.getBeersAsyncUsingTaskExecutor();
future.addCallback( new SuccessCallback<List<Beer>>() {
@Override
public void onSuccess(List<Beer> beers) {
//Handle success
}
}, new FailureCallback() {
@Override
public void onFailure(Throwable throwable) {
//Handle Failure
}
});
Lambdas ListenableFuture examples
▪ ListenableFuture with Lambdas
ListenableFuture<List<Beer>> listenableFuture = taskExecutorService.
getBeersAsyncUsingAnnotationsAndListenableFuture();
listenableFuture.addCallback((beers) -> {
beers.stream().forEach(System. out::println);
},
(throwable) -> {
//Handle failure
}
);
Method references
▪ PreparedStatementSetter and RowMapper method reference example
List<Beer> beers = jdbcOperations.query(
SELECT_BEER_BY_NAME_AND_ALCOHOL_PERCENTAGE,
ps -> {
ps.setString(1, "%" + name + "%");
ps.setBigDecimal( 2, alcoholPercentage);
},
this::mapRow
);
JSR-310 Date/Time Api
▪ Support for Java8 LocalDate, LocalDateTime, …
▪ @DateTimeFormat annotation is also applicable to Java8 Date/Time
types.
▪ Bind String to JSR-310 Date/Time objects
▪ Render JSR-310 objects to Strings
JSR-310 Date/Time Api support example
▪ Mapping incoming @PathVariable to LocalDateTime
@RequestMapping (value = "/modified/{modifiedDate}",method = RequestMethod.
GET)
public List<Beer> getBeersModifiedAfterDate(
@PathVariable @DateTimeFormat(pattern="ddMMyyyyHHmm”)
LocalDateTime modifiedDate){
return beerRepository.getBeersLastModifiedTimestampGreaterThan(
Timestamp.valueOf(modifiedDate));
}
▪ /modified/110320151930
JSR-310 Date/Time Api support example
▪ Domain object
public class Beer {
private Long id;
private String name;
private String description;
private BigDecimal alcoholPercentage;
// @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
private LocalDate since;
@DateTimeFormat (pattern = "ddMMyyyyHHmm")
private LocalDateTime modifiedTimestamp;
Rendering out the LocalDateTime property
▪ Jsp Snippet
Beer modified timestamp: <form:input path="modifiedTimestamp" />
▪ Renders:
Repeatable annotations
▪ @Scheduled
▪ @PropertySource
▪ …
@PropertySource
▪ Java 8 Repeatable annotations
@Configuration
@PropertySource ("classpath:/someProperties.properties")
@PropertySource ("classpath:/someProperties2.properties")
public class SpringConfiguration {
▪ Pre-java8
@Configuration
@PropertySources (value = {
@PropertySource ("classpath:/someProperties.properties"),
@PropertySource ("classpath:/someProperties2.properties")
})
public class SpringConfiguration {
@Scheduled
▪ Java 8 Repeatable annotations
@Scheduled(cron = "0 0 12 * * ?"),
@Scheduled(cron = "0 0 18 * * ?")
public void scheduledTask() {
System.out.println(message + LocalDateTime. now());
}
▪ Pre Java-8
@Schedules({
@Scheduled(cron = "0 0 12 * * ?"),
@Scheduled(cron = "0 0 18 * * ?")
})
public void scheduledTask() {
System.out.println(message + LocalDateTime. now());
}
Spring 4 Parameter discovery
▪ As of Spring 4.0 aware of Java8’s parameter reflection
▪ Parameter names now available in Spring through common Java8
reflection methods.
▪ Java8
▪ ‘-parameters’ compiler flag
▪ Java 6 and 7: via asm
▪ ‘-debug’ compiler flag
Spring 4 parameter discovery
▪ Without parameter discovery (no –debug or –parameters compilation flag)
@RequestMapping (value = "/{id}", method = RequestMethod. GET)
public Beer getBeerById( @PathVariable("id") Long id) {
return beerRepository.getBeerById(id);
}
▪ With Parameter discovery
@RequestMapping (value = "/{id}", method = RequestMethod. GET)
public Beer getBeerById( @PathVariable Long id) {
return beerRepository.getBeerById(id);
}
Spring data custom query parameter discovery
▪ Custom query in Spring data JPA without parameter name discovery
▪ Custom query in Spring data JPA with parameter name discovery
Java 8 Optional
▪ Java.util.Optional as method parameter type with annotations that have
required attribute
▪ @RequestParam
▪ @RequestHeader
▪ @MatrixVariable
▪ …
▪ Optional on Autowired dependencies
Optional MVC Handler method parameters
▪ Using required=false
@RequestMapping (value = "/{id}", method = RequestMethod. GET)
public Beer getBeerById(
@PathVariable Long id,
@RequestHeader(required=false) String country) {
if(country!=null)
System.out.println(country);
return beerRepository.getBeerById(id);
}
Optional on MVC handler method parameter
▪ Usage of Optional on @RequestHeader parameter
@RequestMapping (value = "/{id}", method = RequestMethod. GET)
public Beer getBeerById(
@PathVariable Long id,
@RequestHeader Optional<String> country) {
country.ifPresent(System.out::println);
return beerRepository.getBeerById(id);
}
Optional on Injected dependencies
▪ Required=false on dependency
@RestController
@RequestMapping ("/beers")
public class BeerController {
@Autowired(required = false)
private NotificationService notificationService;
▪ Using the dependency
@RequestMapping (value = "/{id}", method = RequestMethod. GET)
public Beer getBeerById(
@PathVariable Long id,
@RequestHeader Optional<String> country) {
if(notificationService != null)
notificationService.sendNotification("getBeerForId: " + id);
Optional on Injected dependencies
▪ Optional dependency
@RestController
@RequestMapping ("/beers")
public class BeerController {
@Autowired
private Optional<NotificationService> notificationService;
▪ Using the dependency
@RequestMapping (value = "/{id}", method = RequestMethod. GET)
public Beer getBeerById( @PathVariable Long id,
@RequestHeader Optional<String> country) {
notificationService.ifPresent(
service -> service.sendNotification( "getBeerForId: " + id)
);
return beerRepository.getBeerById(id);
}
Injection of Ordered Lists (Spring 4.0)
▪ Injection point or Ordered List
@RestController @RequestMapping ("/beers")
public class BeerController {
@Autowired
private List<MyService> services;
▪ MyService dependency with @Order(1)
@Service @Order (1)
public class MyServiceImpl implements MyService {
▪ MyService dependency with @Order(2)
@Service @Order (2)
public class MyOtherServiceImpl implements MyService {
▪ Injection point for Ordered List
@RestController @RequestMapping ("/beers")
public class BeerController {
@Autowired
private List<MyService> services;
▪ MyService dependency with @Order(1)
@Bean @Order(1)
public MyService service1() {
return new MyServiceImpl();
}
▪ MyService dependency with @Order(3)
@Bean @Order(3)
public MyService service2() {
return new MyOtherServiceImpl();
}
@Order on @Bean methods (Spring 4.1)
@javax.annotation.Priotity
▪ Injection point for Ordered List
@RestController
@RequestMapping ("/beers")
public class BeerController {
@Autowired
private List<MyService> services;
▪ MyService dependency with @Priority(1)
@Service @Priority (1)
public class MyServiceImpl implements MyService {
▪ MyService dependency with @Priority(2)
@Service @Priority (2)
public class MyOtherServiceImpl implements MyService {
@Priority for primary candidate selection
▪ Inject 1 Bean with multiple @Priority beans
@RestController @RequestMapping ("/beers")
public class BeerController {
@Autowired
private MyService service; //Injects MyServiceImpl
▪ Inject 1 Bean with multiple @Order beans
▪ Fails! Causes: org.springframework.beans.factory.
NoUniqueBeanDefinitionException
▪ This can be solved however!
▪ By Electing 1 of the @Order beans with @Primary (Spring 3 annotation)
@Service
@Order(1) @Primary
public class MyServiceImpl implements MyService {
@Qualifier for candidate selection
@Service @Qualifier ("myServiceImpl")
public class MyServiceImpl implements MyService {
@Service @Qualifier("myOtherServiceImpl")
public class MyOtherServiceImpl implements MyService {
@RestController @RequestMapping ("/beers")
public class BeerController {
@Autowired @Qualifier ("myServiceImpl")
private MyService service; //Injects MyServiceImpl
Generic type for candidate selection (Spring 4.0)
@Service
public class BeerServiceImpl implements MyService<Beer> {
@Service
public class MyOtherServiceImpl implements MyService<OtherEntity> {
@RestController @RequestMapping ("/beers")
public class BeerController {
@Autowired
private MyService<Beer> service; //Injects BeerServiceImpl
Sources and code
▪ Sources
▪ http://spring.io/blog/2015/01/14/springone2gx-2014-replay-spring-framework-on-java-8
▪ http://www.infoq.com/articles/spring-4-java-8
▪ http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#new-in-4.0
▪ http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#new-in-4.1
▪ Code
▪ GitHub: https://github.com/Turbots/spring4_workshop
▪ Maven module: spring4-java8-features
Core Spring
In the beginning there was… XML
In the beginning there was… XML
▪ Spring 3 made it possible to get rid of XML configuration for Spring (mostly)
@Configuration
But what about descriptions?
Spring 4 adds the @Description annotation
But what about descriptions? (2)
Spring 4 allows you to use all information to decide which beans to inject
through @Conditional
Different strokes for different folks
Different strokes for different folks (2)
Conditions have access to:
Different strokes for different folks (3)
Annotated object Condition Context
Annotations
Meta annotations
Class hierarchy
...
Bean definition registry
Scopes
Beans that are created
Classloader
Environment
Resources
...
One step further
In Spring 3
▪ Only at the class level
▪ @Lazy components get created
when they need to be injected.
Laziness
Spring 4
▪ Also at injection point
Laziness (2)
Web Improvements
48
General Web Improvements Spring 4.0
▪ Focused primarily on Servlet 3.0+ environments.
▪ WebSocket support
▪ New @RestController annotation
▪ New AsyncRestTemplate class
▪ Comprehensive time zone support
49
Focus on Servlet 3.0 + environments
▪ Deployment to Servlet 2.5 servers
remains an option
▪ Keep in mind: If you are using the
Spring MVC Test Framework you
will need to ensure that a Servlet
3.0 compatible JAR is in your test
classpath.
▪ Main practical implication: web.xml
is no longer needed (still
supported, though)
50
Interface WebApplicationInitializer
▪ WebApplicationInitializer must be used, if web.xml is not used
▪ DEMO
51
@RestController annotation
▪ Before spring 4.0
▪ Spring 4.0
52
AsyncRestTemplate
▪ Web applications often need to
query external REST services these
days. The very nature of HTTP and
synchronous calls can lead up to
challenges when scaling
applications for those needs:
multiple threads may be blocked,
waiting for remote HTTP responses.
53
AsyncRestTemplate (2)
▪ AsyncRestTemplate returns ListenableFuture wrapper instead of
concrete results as RestTemplate does.
▪ ListenableFuture accepts completion callbacks
54
ListenableFuture
▪ DEMO
55
Comprehensive time zone support
▪ Before Spring 4.0
56
Comprehensive time zone support (2)
▪ Spring 4.0: the new extension of LocaleContext provides TimeZone support
57
Comprehensive time zone support (3)
▪ Spring 4.0: new LocalContextResolver
58
Comprehensive time zone support (4)
▪ Out of box, there is a bunch of classes implementing
LocalContextResolver interface.
▪ Some of them support setting default TimeZone
▪ Some of them also support fall back to the server TimeZone
59
Comprehensive time zone support (5)
▪ When available, the user’s TimeZone can be obtained using the
RequestContext.getTimeZone() method.
▪ Time zone information will automatically be used by Date/Time Converter and
Formatter objects registered with Spring’s ConversionService.
60
Comprehensive time zone support (6)
Question
How to pass time zone info from the client to LocaleContext?
61
Comprehensive time zone support (7)
▪ Old good Locale scenario:
- Locale info passed as a request parameter (ex: user chooses language)
- Out-of-box LocaleChangeInterceptor would intercept the request and
set the required Locale in LocaleResolver
62
Comprehensive time zone support (8)
▪ Possible TimeZone scenario:
- TimeZone info passed as a request parameter (ex: JavaScript function
returning TimeZone)
- Extending LocaleChangeInterceptor (writing own interceptor) to
handle TimeZone info and setting the correct LocaleContext in
LocaleContextResolver
63
Spring 4.1 web improvement
▪ There is a number of small and bigger improvements. Further, in this
presentation some of them will be highlighted.
▪ For the complete and comprehensive list of the improvements, please, consult
the Spring documentation
64
JDK 1.8’s java.util.Optional support
▪ Optional is now supported for @RequestParam, @RequestHeader, and
@MatrixVariable controller method arguments.
▪ DEMO
65
@JsonView
▪ Jackson’s @JsonView is supported directly on @ResponseBody and
ResponseEntity controller methods for serializing different amounts of detail
for the same POJO (e.g. summary vs. detail page).
▪ Also supported with View-based rendering by adding the serialization view type
as a model attribute under a special key.
▪ DEMO
66
New type: RequestEntity
▪ Provides a builder-style API to guide client-side REST code towards the
preparation of HTTP requests.
▪ For example:
67
ResponseEntity provides builder-style API
▪ Example:
68
Full list of improvements
▪ Full list of improvements to be found here:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/new-in-
4.1.html
WebSockets
In the beginning there was… polling
Do you have
new data?
In the beginning there was… polling (2)
Do you have
new data?
No
In the beginning there was… polling (3)
In the beginning there was… polling (4)
Do you have
new data?
In the beginning there was… polling (5)
Do you have
new data?
No
In the beginning there was… polling (6)
In the beginning there was… polling (7)
Long polling
Do you have
new data?
Long polling (2)
Do you have
new data?
Long polling (3)
Do you have
new data?
Here is your
data
Polling disadvantages
● Client initiates a request (even with long polling mechanism)
● Traffic and overhead (even if there is no data!)
● Big delay between event and notification
● Consider server loads
And with HTML5 came… WebSockets!
What do you think about a
protocol upgrade?
And with HTML5 came… WebSockets! (2)
What do you think about a
protocol upgrade?
Sure, why not!
HTTP 101 Switching Protocols
And with HTML5 came… WebSockets! (3)
Open TCP socket
What about AJAX? Can I still use it?
AJAX
High latency (HTTP req/res for each
roundtrip)
Small to medium messages
WebSockets
Low latency (TCP socket remains
open)
Large and frequent messages
Realtime applications (stocks,
games, …)
● Not every project needs WebSockets!
WebSockets in Spring
● New Spring WebSocket module
● Fallback option with SockJS
● as underlying sub-protocol (https://stomp.github.io/)
○ Simple interoperable protocol for asynchronous messaging
○ Client actions: SEND, SUBSCRIBE / UNSUBSCRIBE, ACK / NACK
○ Server actions: MESSAGE, RECEIPT, ERROR
WebSockets in Spring (2)
● Generic Spring Messaging Module
○ Some Spring integration types promoted to Core (eg. Message,
@MessageMapping, …)
○ Also usable when using JMS
WebSockets in Spring (3)
@EnableWebSocket @EnableWebSocketMessageBroker
Raw WebSocket handler support
Extend TextWebSocketHandler or
BinaryWebSocketHandler and
implement handleTextMessage
WebSocket using a higher-level
messaging sub-protocol (eg. STOMP)
Raw example
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;
public class MyHandler extends TextWebSocketHandler {
@Override
public void handleTextMessage(WebSocketSession session, TextMessage msg) {
// ...
}
}
Raw example (2)
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
Demo application
● AngularJS application
● Spring WebMVC backend
● SockJS with higher-level STOMP protocol and Jackson serialization
Testing improvements
Cleaning up after Spring 3.x
Cleaning up after Spring 3.x (2)
● Many packages/classes/methods were marked as deprecated in the Spring 3.x version
● In Spring 4.x:
○ All deprecated packages have been removed
○ Many deprecated methods and fields have been removed
● Before upgrading from 3.x to 4.x → Look at the deprecation warnings!
Pruning in Spring 4.0
● Several things have been pruned to improve the testing experience
< 4.0 4.0+
No more JUnit 3.8 support Use JUnit 4 or TestNG
@ExpectedException Use @Test(expected = MyEx.class) or @Rule
@NotTransactional Use @Transactional(propagation = NOT_SUPPORTED)
SimpleJdbcTestUtils Use JdbcTestUtils or ScriptUtils or @Sql
Changes in dependencies in Spring 4.0
● Servlet API mocks → upgraded to Servlet 3.0 API
○ Servlet 3.0 API is easier, more powerful and more versatile
○ Servlet 2.5 API is still supported
● JUnit
○ minimum version 4.8
○ recommended version 4.11
● TestNG → Use version 6.8.5
Changes in dependencies in Spring 4.1
● Servlet API mocks → upgraded to Servlet 3.0 API
○ Servlet 3.0 API is easier, more powerful and more versatile
○ Servlet 2.5 API is still supported
● JUnit
○ minimum version 4.9 is supported
○ version 4.11 is recommended
● TestNG
○ version 6.8.8 is recommended
New in Spring 4.0
● SocketUtils
○ Used to scan for available UDP and TCP ports
○ Handy for setting up different containers / servers during integration tests
● ActiveProfilesResolver API
○ Programmatic alternative to static profile strings (like in Spring 3.x)
○ Use the resolver attribute in @ActiveProfiles annotation
● Meta-annotation support for tests
○ Easy to create annotations for your annotations
New in Spring 4.1
● Groovy scripts can be used to configure your Spring context
● Programmatically start/stop/commit your test transaction with
TestTransaction
● Default & Custom TestExecutionListeners can now be automatically
discovered
● Custom TestExecutionListeners can be merged with the default ones
● @Sql and @SqlConfig allow you to configure execution of SQL scripts
declaratively:
○ before/after a test class
○ before/after a test method
Demo
Questions

More Related Content

Spring 4 - A&BP CC

  • 1. Spring 4 Ken Coenen, Dieter Hubau, Tim De Grande, Steve De Zitter, Serguei Storojenko, Andreas Evers
  • 2. Agenda Steve De Zitter Java SDK & EE support Tim De Grande Spring Core Serguei Storojenko Spring WebMVC Ken Coenen WebSockets and Messaging Dieter Hubau Testing improvements Andreas Evers Spring Core
  • 4. Java 8 features in Spring 4/4.1 ▪ Lambda expressions ▪ Method references ▪ JSR-310 Date/Time Support ▪ Repeatable annotations ▪ Parameter name discovery ▪ Java.util.Optional ▪ Related new injection features ▪ Ordering, @Priority, Generic types
  • 5. Java 8 lamda conventions ▪ Functional interfaces ▪ Typically callback interfaces such as Runnable/Callable ▪ Common functional interfaces in java.util.function ▪ Function, Predicate, Supplier ▪ Used extensively in Java8 Streams Api
  • 6. Lambda conventions in Spring api’s ▪ TransactionTemplate with TransactionCallback ▪ JdbcTemplate/JdbcOperations with PreparedStatementSetter ▪ JdbcTemplate/JdbcOperations with RowMapper ▪ TaskExecutor ▪ ListenableFuture
  • 7. Lambdas JdbcOperations example ▪ PreparedStatementSetter and RowMapper pre Java 8 List<Beer> beers = jdbcOperations.query(SELECT_BEER_BY_NAME_AND_ALCOHOL_PERCENTAGE, new PreparedStatementSetter() { @Override public void setValues(PreparedStatement ps) throws SQLException{ ps.setString(1, "%" + name + "%"); ps.setBigDecimal(2, alcoholPercentage); } }, new RowMapper<Beer>() { @Override public Beer mapRow(ResultSet rs, int rowNum) throws SQLException{ return new Beer(rs.getLong("id"), rs.getString("name"), rs.getString("description"), rs.getBigDecimal("alcoholPercentage"), rs.getTimestamp("modifiedTimestamp”)); } } );
  • 8. Lambdas JdbcOperations example ▪ PreparedStatementSetter and RowMapper with lambdas List<Beer> beers = jdbcOperations.query( SELECT_BEER_BY_NAME_AND_ALCOHOL_PERCENTAGE, ps -> { ps.setString(1, "%" + name + "%"); ps.setBigDecimal( 2, alcoholPercentage); }, (rs, rowNum) -> new Beer(rs.getLong( "id"), rs.getString("name"), rs.getString("description"), rs.getBigDecimal( "alcoholPercentage”)) );
  • 9. Lambdas TaskExecutor example ▪ TaskExecutor (ThreadPoolTaskExecutor) pre Java 8 return threadPoolTaskExecutor.submitListenable( new Callable<List<Beer>>() { @Override public List<Beer> call() throws Exception { return beerRepository.getAllBeers(); } }); ▪ TaskExecutor with lambdas return threadPoolTaskExecutor.submitListenable( () -> beerRepository.getAllBeers() );
  • 10. ListenableFuture example ▪ ListenableFuture pre Java 8 with ListenableFutureCallback ListenableFuture<List<Beer>> future = taskExecutorService.getBeersAsyncUsingTaskExecutor(); future.addCallback( new ListenableFutureCallback<List<Beer>>() { @Override public void onFailure(Throwable throwable) { //Handle Failure } @Override public void onSuccess(List<Beer> beers) { //Handle success } });
  • 11. ListenableFuture example ▪ ListenableFuture pre Java 8 with success and failure callback ListenableFuture<List<Beer>> future = taskExecutorService.getBeersAsyncUsingTaskExecutor(); future.addCallback( new SuccessCallback<List<Beer>>() { @Override public void onSuccess(List<Beer> beers) { //Handle success } }, new FailureCallback() { @Override public void onFailure(Throwable throwable) { //Handle Failure } });
  • 12. Lambdas ListenableFuture examples ▪ ListenableFuture with Lambdas ListenableFuture<List<Beer>> listenableFuture = taskExecutorService. getBeersAsyncUsingAnnotationsAndListenableFuture(); listenableFuture.addCallback((beers) -> { beers.stream().forEach(System. out::println); }, (throwable) -> { //Handle failure } );
  • 13. Method references ▪ PreparedStatementSetter and RowMapper method reference example List<Beer> beers = jdbcOperations.query( SELECT_BEER_BY_NAME_AND_ALCOHOL_PERCENTAGE, ps -> { ps.setString(1, "%" + name + "%"); ps.setBigDecimal( 2, alcoholPercentage); }, this::mapRow );
  • 14. JSR-310 Date/Time Api ▪ Support for Java8 LocalDate, LocalDateTime, … ▪ @DateTimeFormat annotation is also applicable to Java8 Date/Time types. ▪ Bind String to JSR-310 Date/Time objects ▪ Render JSR-310 objects to Strings
  • 15. JSR-310 Date/Time Api support example ▪ Mapping incoming @PathVariable to LocalDateTime @RequestMapping (value = "/modified/{modifiedDate}",method = RequestMethod. GET) public List<Beer> getBeersModifiedAfterDate( @PathVariable @DateTimeFormat(pattern="ddMMyyyyHHmm”) LocalDateTime modifiedDate){ return beerRepository.getBeersLastModifiedTimestampGreaterThan( Timestamp.valueOf(modifiedDate)); } ▪ /modified/110320151930
  • 16. JSR-310 Date/Time Api support example ▪ Domain object public class Beer { private Long id; private String name; private String description; private BigDecimal alcoholPercentage; // @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) private LocalDate since; @DateTimeFormat (pattern = "ddMMyyyyHHmm") private LocalDateTime modifiedTimestamp;
  • 17. Rendering out the LocalDateTime property ▪ Jsp Snippet Beer modified timestamp: <form:input path="modifiedTimestamp" /> ▪ Renders:
  • 18. Repeatable annotations ▪ @Scheduled ▪ @PropertySource ▪ …
  • 19. @PropertySource ▪ Java 8 Repeatable annotations @Configuration @PropertySource ("classpath:/someProperties.properties") @PropertySource ("classpath:/someProperties2.properties") public class SpringConfiguration { ▪ Pre-java8 @Configuration @PropertySources (value = { @PropertySource ("classpath:/someProperties.properties"), @PropertySource ("classpath:/someProperties2.properties") }) public class SpringConfiguration {
  • 20. @Scheduled ▪ Java 8 Repeatable annotations @Scheduled(cron = "0 0 12 * * ?"), @Scheduled(cron = "0 0 18 * * ?") public void scheduledTask() { System.out.println(message + LocalDateTime. now()); } ▪ Pre Java-8 @Schedules({ @Scheduled(cron = "0 0 12 * * ?"), @Scheduled(cron = "0 0 18 * * ?") }) public void scheduledTask() { System.out.println(message + LocalDateTime. now()); }
  • 21. Spring 4 Parameter discovery ▪ As of Spring 4.0 aware of Java8’s parameter reflection ▪ Parameter names now available in Spring through common Java8 reflection methods. ▪ Java8 ▪ ‘-parameters’ compiler flag ▪ Java 6 and 7: via asm ▪ ‘-debug’ compiler flag
  • 22. Spring 4 parameter discovery ▪ Without parameter discovery (no –debug or –parameters compilation flag) @RequestMapping (value = "/{id}", method = RequestMethod. GET) public Beer getBeerById( @PathVariable("id") Long id) { return beerRepository.getBeerById(id); } ▪ With Parameter discovery @RequestMapping (value = "/{id}", method = RequestMethod. GET) public Beer getBeerById( @PathVariable Long id) { return beerRepository.getBeerById(id); }
  • 23. Spring data custom query parameter discovery ▪ Custom query in Spring data JPA without parameter name discovery ▪ Custom query in Spring data JPA with parameter name discovery
  • 24. Java 8 Optional ▪ Java.util.Optional as method parameter type with annotations that have required attribute ▪ @RequestParam ▪ @RequestHeader ▪ @MatrixVariable ▪ … ▪ Optional on Autowired dependencies
  • 25. Optional MVC Handler method parameters ▪ Using required=false @RequestMapping (value = "/{id}", method = RequestMethod. GET) public Beer getBeerById( @PathVariable Long id, @RequestHeader(required=false) String country) { if(country!=null) System.out.println(country); return beerRepository.getBeerById(id); }
  • 26. Optional on MVC handler method parameter ▪ Usage of Optional on @RequestHeader parameter @RequestMapping (value = "/{id}", method = RequestMethod. GET) public Beer getBeerById( @PathVariable Long id, @RequestHeader Optional<String> country) { country.ifPresent(System.out::println); return beerRepository.getBeerById(id); }
  • 27. Optional on Injected dependencies ▪ Required=false on dependency @RestController @RequestMapping ("/beers") public class BeerController { @Autowired(required = false) private NotificationService notificationService; ▪ Using the dependency @RequestMapping (value = "/{id}", method = RequestMethod. GET) public Beer getBeerById( @PathVariable Long id, @RequestHeader Optional<String> country) { if(notificationService != null) notificationService.sendNotification("getBeerForId: " + id);
  • 28. Optional on Injected dependencies ▪ Optional dependency @RestController @RequestMapping ("/beers") public class BeerController { @Autowired private Optional<NotificationService> notificationService; ▪ Using the dependency @RequestMapping (value = "/{id}", method = RequestMethod. GET) public Beer getBeerById( @PathVariable Long id, @RequestHeader Optional<String> country) { notificationService.ifPresent( service -> service.sendNotification( "getBeerForId: " + id) ); return beerRepository.getBeerById(id); }
  • 29. Injection of Ordered Lists (Spring 4.0) ▪ Injection point or Ordered List @RestController @RequestMapping ("/beers") public class BeerController { @Autowired private List<MyService> services; ▪ MyService dependency with @Order(1) @Service @Order (1) public class MyServiceImpl implements MyService { ▪ MyService dependency with @Order(2) @Service @Order (2) public class MyOtherServiceImpl implements MyService {
  • 30. ▪ Injection point for Ordered List @RestController @RequestMapping ("/beers") public class BeerController { @Autowired private List<MyService> services; ▪ MyService dependency with @Order(1) @Bean @Order(1) public MyService service1() { return new MyServiceImpl(); } ▪ MyService dependency with @Order(3) @Bean @Order(3) public MyService service2() { return new MyOtherServiceImpl(); } @Order on @Bean methods (Spring 4.1)
  • 31. @javax.annotation.Priotity ▪ Injection point for Ordered List @RestController @RequestMapping ("/beers") public class BeerController { @Autowired private List<MyService> services; ▪ MyService dependency with @Priority(1) @Service @Priority (1) public class MyServiceImpl implements MyService { ▪ MyService dependency with @Priority(2) @Service @Priority (2) public class MyOtherServiceImpl implements MyService {
  • 32. @Priority for primary candidate selection ▪ Inject 1 Bean with multiple @Priority beans @RestController @RequestMapping ("/beers") public class BeerController { @Autowired private MyService service; //Injects MyServiceImpl ▪ Inject 1 Bean with multiple @Order beans ▪ Fails! Causes: org.springframework.beans.factory. NoUniqueBeanDefinitionException ▪ This can be solved however! ▪ By Electing 1 of the @Order beans with @Primary (Spring 3 annotation) @Service @Order(1) @Primary public class MyServiceImpl implements MyService {
  • 33. @Qualifier for candidate selection @Service @Qualifier ("myServiceImpl") public class MyServiceImpl implements MyService { @Service @Qualifier("myOtherServiceImpl") public class MyOtherServiceImpl implements MyService { @RestController @RequestMapping ("/beers") public class BeerController { @Autowired @Qualifier ("myServiceImpl") private MyService service; //Injects MyServiceImpl
  • 34. Generic type for candidate selection (Spring 4.0) @Service public class BeerServiceImpl implements MyService<Beer> { @Service public class MyOtherServiceImpl implements MyService<OtherEntity> { @RestController @RequestMapping ("/beers") public class BeerController { @Autowired private MyService<Beer> service; //Injects BeerServiceImpl
  • 35. Sources and code ▪ Sources ▪ http://spring.io/blog/2015/01/14/springone2gx-2014-replay-spring-framework-on-java-8 ▪ http://www.infoq.com/articles/spring-4-java-8 ▪ http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#new-in-4.0 ▪ http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#new-in-4.1 ▪ Code ▪ GitHub: https://github.com/Turbots/spring4_workshop ▪ Maven module: spring4-java8-features
  • 37. In the beginning there was… XML
  • 38. In the beginning there was… XML ▪ Spring 3 made it possible to get rid of XML configuration for Spring (mostly) @Configuration
  • 39. But what about descriptions?
  • 40. Spring 4 adds the @Description annotation But what about descriptions? (2)
  • 41. Spring 4 allows you to use all information to decide which beans to inject through @Conditional Different strokes for different folks
  • 42. Different strokes for different folks (2)
  • 43. Conditions have access to: Different strokes for different folks (3) Annotated object Condition Context Annotations Meta annotations Class hierarchy ... Bean definition registry Scopes Beans that are created Classloader Environment Resources ...
  • 45. In Spring 3 ▪ Only at the class level ▪ @Lazy components get created when they need to be injected. Laziness
  • 46. Spring 4 ▪ Also at injection point Laziness (2)
  • 48. 48 General Web Improvements Spring 4.0 ▪ Focused primarily on Servlet 3.0+ environments. ▪ WebSocket support ▪ New @RestController annotation ▪ New AsyncRestTemplate class ▪ Comprehensive time zone support
  • 49. 49 Focus on Servlet 3.0 + environments ▪ Deployment to Servlet 2.5 servers remains an option ▪ Keep in mind: If you are using the Spring MVC Test Framework you will need to ensure that a Servlet 3.0 compatible JAR is in your test classpath. ▪ Main practical implication: web.xml is no longer needed (still supported, though)
  • 50. 50 Interface WebApplicationInitializer ▪ WebApplicationInitializer must be used, if web.xml is not used ▪ DEMO
  • 51. 51 @RestController annotation ▪ Before spring 4.0 ▪ Spring 4.0
  • 52. 52 AsyncRestTemplate ▪ Web applications often need to query external REST services these days. The very nature of HTTP and synchronous calls can lead up to challenges when scaling applications for those needs: multiple threads may be blocked, waiting for remote HTTP responses.
  • 53. 53 AsyncRestTemplate (2) ▪ AsyncRestTemplate returns ListenableFuture wrapper instead of concrete results as RestTemplate does. ▪ ListenableFuture accepts completion callbacks
  • 55. 55 Comprehensive time zone support ▪ Before Spring 4.0
  • 56. 56 Comprehensive time zone support (2) ▪ Spring 4.0: the new extension of LocaleContext provides TimeZone support
  • 57. 57 Comprehensive time zone support (3) ▪ Spring 4.0: new LocalContextResolver
  • 58. 58 Comprehensive time zone support (4) ▪ Out of box, there is a bunch of classes implementing LocalContextResolver interface. ▪ Some of them support setting default TimeZone ▪ Some of them also support fall back to the server TimeZone
  • 59. 59 Comprehensive time zone support (5) ▪ When available, the user’s TimeZone can be obtained using the RequestContext.getTimeZone() method. ▪ Time zone information will automatically be used by Date/Time Converter and Formatter objects registered with Spring’s ConversionService.
  • 60. 60 Comprehensive time zone support (6) Question How to pass time zone info from the client to LocaleContext?
  • 61. 61 Comprehensive time zone support (7) ▪ Old good Locale scenario: - Locale info passed as a request parameter (ex: user chooses language) - Out-of-box LocaleChangeInterceptor would intercept the request and set the required Locale in LocaleResolver
  • 62. 62 Comprehensive time zone support (8) ▪ Possible TimeZone scenario: - TimeZone info passed as a request parameter (ex: JavaScript function returning TimeZone) - Extending LocaleChangeInterceptor (writing own interceptor) to handle TimeZone info and setting the correct LocaleContext in LocaleContextResolver
  • 63. 63 Spring 4.1 web improvement ▪ There is a number of small and bigger improvements. Further, in this presentation some of them will be highlighted. ▪ For the complete and comprehensive list of the improvements, please, consult the Spring documentation
  • 64. 64 JDK 1.8’s java.util.Optional support ▪ Optional is now supported for @RequestParam, @RequestHeader, and @MatrixVariable controller method arguments. ▪ DEMO
  • 65. 65 @JsonView ▪ Jackson’s @JsonView is supported directly on @ResponseBody and ResponseEntity controller methods for serializing different amounts of detail for the same POJO (e.g. summary vs. detail page). ▪ Also supported with View-based rendering by adding the serialization view type as a model attribute under a special key. ▪ DEMO
  • 66. 66 New type: RequestEntity ▪ Provides a builder-style API to guide client-side REST code towards the preparation of HTTP requests. ▪ For example:
  • 68. 68 Full list of improvements ▪ Full list of improvements to be found here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/new-in- 4.1.html
  • 70. In the beginning there was… polling Do you have new data?
  • 71. In the beginning there was… polling (2) Do you have new data? No
  • 72. In the beginning there was… polling (3)
  • 73. In the beginning there was… polling (4) Do you have new data?
  • 74. In the beginning there was… polling (5) Do you have new data? No
  • 75. In the beginning there was… polling (6)
  • 76. In the beginning there was… polling (7)
  • 77. Long polling Do you have new data?
  • 78. Long polling (2) Do you have new data?
  • 79. Long polling (3) Do you have new data? Here is your data
  • 80. Polling disadvantages ● Client initiates a request (even with long polling mechanism) ● Traffic and overhead (even if there is no data!) ● Big delay between event and notification ● Consider server loads
  • 81. And with HTML5 came… WebSockets! What do you think about a protocol upgrade?
  • 82. And with HTML5 came… WebSockets! (2) What do you think about a protocol upgrade? Sure, why not! HTTP 101 Switching Protocols
  • 83. And with HTML5 came… WebSockets! (3) Open TCP socket
  • 84. What about AJAX? Can I still use it? AJAX High latency (HTTP req/res for each roundtrip) Small to medium messages WebSockets Low latency (TCP socket remains open) Large and frequent messages Realtime applications (stocks, games, …) ● Not every project needs WebSockets!
  • 85. WebSockets in Spring ● New Spring WebSocket module ● Fallback option with SockJS ● as underlying sub-protocol (https://stomp.github.io/) ○ Simple interoperable protocol for asynchronous messaging ○ Client actions: SEND, SUBSCRIBE / UNSUBSCRIBE, ACK / NACK ○ Server actions: MESSAGE, RECEIPT, ERROR
  • 86. WebSockets in Spring (2) ● Generic Spring Messaging Module ○ Some Spring integration types promoted to Core (eg. Message, @MessageMapping, …) ○ Also usable when using JMS
  • 87. WebSockets in Spring (3) @EnableWebSocket @EnableWebSocketMessageBroker Raw WebSocket handler support Extend TextWebSocketHandler or BinaryWebSocketHandler and implement handleTextMessage WebSocket using a higher-level messaging sub-protocol (eg. STOMP)
  • 88. Raw example import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.TextMessage; public class MyHandler extends TextWebSocketHandler { @Override public void handleTextMessage(WebSocketSession session, TextMessage msg) { // ... } }
  • 89. Raw example (2) @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/myHandler"); } @Bean public WebSocketHandler myHandler() { return new MyHandler(); } }
  • 90. Demo application ● AngularJS application ● Spring WebMVC backend ● SockJS with higher-level STOMP protocol and Jackson serialization
  • 92. Cleaning up after Spring 3.x
  • 93. Cleaning up after Spring 3.x (2) ● Many packages/classes/methods were marked as deprecated in the Spring 3.x version ● In Spring 4.x: ○ All deprecated packages have been removed ○ Many deprecated methods and fields have been removed ● Before upgrading from 3.x to 4.x → Look at the deprecation warnings!
  • 94. Pruning in Spring 4.0 ● Several things have been pruned to improve the testing experience < 4.0 4.0+ No more JUnit 3.8 support Use JUnit 4 or TestNG @ExpectedException Use @Test(expected = MyEx.class) or @Rule @NotTransactional Use @Transactional(propagation = NOT_SUPPORTED) SimpleJdbcTestUtils Use JdbcTestUtils or ScriptUtils or @Sql
  • 95. Changes in dependencies in Spring 4.0 ● Servlet API mocks → upgraded to Servlet 3.0 API ○ Servlet 3.0 API is easier, more powerful and more versatile ○ Servlet 2.5 API is still supported ● JUnit ○ minimum version 4.8 ○ recommended version 4.11 ● TestNG → Use version 6.8.5
  • 96. Changes in dependencies in Spring 4.1 ● Servlet API mocks → upgraded to Servlet 3.0 API ○ Servlet 3.0 API is easier, more powerful and more versatile ○ Servlet 2.5 API is still supported ● JUnit ○ minimum version 4.9 is supported ○ version 4.11 is recommended ● TestNG ○ version 6.8.8 is recommended
  • 97. New in Spring 4.0 ● SocketUtils ○ Used to scan for available UDP and TCP ports ○ Handy for setting up different containers / servers during integration tests ● ActiveProfilesResolver API ○ Programmatic alternative to static profile strings (like in Spring 3.x) ○ Use the resolver attribute in @ActiveProfiles annotation ● Meta-annotation support for tests ○ Easy to create annotations for your annotations
  • 98. New in Spring 4.1 ● Groovy scripts can be used to configure your Spring context ● Programmatically start/stop/commit your test transaction with TestTransaction ● Default & Custom TestExecutionListeners can now be automatically discovered ● Custom TestExecutionListeners can be merged with the default ones ● @Sql and @SqlConfig allow you to configure execution of SQL scripts declaratively: ○ before/after a test class ○ before/after a test method
  • 99. Demo