Get	
  ready	
  for	
  Spring	
  4	
  

Speaker:	
  Oleg	
  Tsal-­‐Tsalko	
  (@tsaltsol)	
  
Modern	
  Spring	
  ecosystem	
  
Spring	
  Boot	
  
Spring	
  Boot	
  Groovy	
  app	
  
@Controller	
  
class	
  ThisWillActuallyRun	
  {	
  
	
  
	
  	
  	
  	
  @RequestMapping("/")	
  
	
  	
  	
  	
  @ResponseBody	
  
	
  	
  	
  	
  String	
  home()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  "Hello	
  World!"	
  
	
  	
  	
  	
  }	
  
	
  
}	
  
	
  
Spring	
  Boot	
  Java	
  app	
  
import	
  org.springframework.boot.*;	
  
import	
  org.springframework.boot.autoconfigure.*;	
  
import	
  org.springframework.stereotype.*;	
  
import	
  org.springframework.web.bind.annotaSon.*;	
  
	
  
@Controller	
  
@EnableAutoConfigura9on	
  
public	
  class	
  SampleController	
  {	
  
	
  
	
  	
  	
  	
  @RequestMapping("/")	
  
	
  	
  	
  	
  @ResponseBody	
  
	
  	
  	
  	
  String	
  home()	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  "Hello	
  World!";	
  
	
  	
  	
  	
  }	
  
	
  
	
  	
  	
  	
  public	
  staSc	
  void	
  main(String[]	
  args)	
  throws	
  ExcepSon	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  SpringApplica9on.run(SampleController.class,	
  args);	
  
	
  	
  	
  	
  }	
  
}	
  
	
  
Spring	
  XD	
  architecture	
  
Files	
  

Sensors	
  

Mobile	
  

Social	
  

Spring	
  XD	
  Shell	
  
Spring	
  XD	
  RunSme	
  

Gemfire	
  

Taps	
  

Jobs	
  

Compute	
  
HDFS	
  

PredicSve	
  modeling	
  

Workflow	
  

Redis	
  

Ingest	
  

Streams	
  

Export	
  

Export	
  

RDBMS	
  
NoSQL	
  
R,	
  SAS	
  
Spring	
  XD	
  RunSme	
  

XD	
  Admin	
  

hbp	
  |	
  filter	
  |	
  file	
  

CLUSTERED	
  NODE	
  

CLUSTERED	
  NODE	
  

CLUSTERED	
  NODE	
  

SINGLE	
  
NODE	
  

HTTP	
  
Module	
  

Filter	
  
Module	
  

File	
  
Module	
  

All	
  
Modules	
  

Rabbit,	
  Redis,	
  (Pluggable)	
  

In	
  Memory	
  
Transport	
  

hbp	
  |	
  filter	
  |	
  file	
  
Spring	
  4.0	
  

Almost	
  there…	
  RC1	
  now!!!	
  
Spring	
  4.0	
  
[RC1]	
  
Biggest	
  changes:	
  
•  Comprehensive	
  Java	
  8	
  support	
  
•  Support	
  for	
  Java	
  EE	
  7	
  APIs	
  
•  WebSocket	
  support	
  
•  Programming	
  model	
  for	
  message-­‐oriented	
  architectures	
  
Smaller	
  features:	
  
•  Support	
  for	
  @javax.transacSon.TransacSonal	
  
•  New	
  @CondiSonal	
  annotaSon	
  
•  New	
  @RestController	
  annotaSon	
  
•  AsyncRestTemplate	
  
•  Autowiring	
  of	
  generic	
  types	
  
•  Groovy	
  based	
  config	
  
And	
  more…	
  
4.0	
  M1	
  

Java	
  8	
  &	
  Java	
  EE	
  7	
  support	
  
Comprehensive	
  Java	
  8	
  
support	
  
• Lambdas	
  
• Date	
  and	
  Time	
  API	
  (JSR-­‐310)	
  
• Parameter	
  name	
  discovery	
  
• Repeatable	
  annotaSons	
  
• Concurrency	
  enhancement	
  

Support	
  for	
  Java	
  EE	
  7	
  APIs	
  
• Asynchronous	
  API	
  for	
  RestTemplate	
  
• Bean	
  ValidaSon	
  1.1	
  (JSR-­‐349)	
  
• Expression	
  Language	
  3.0	
  (JSR-­‐341)	
  
• JMS	
  2.0	
  (JSR-­‐343)	
  
• Concurrency	
  USliSes	
  for	
  Java	
  EE	
  
(JSR-­‐236)	
  
• JPA	
  2.1	
  (JSR-­‐338)	
  
• Servlet	
  3.1	
  (JSR-­‐340)	
  
• JSF	
  2.2	
  (JSR-­‐344)	
  
Get	
  advantage	
  of	
  Java	
  8	
  lambdas	
  
in	
  well	
  known	
  Spring	
  APIs!!!	
  
JdbcTemplate	
  jdbcTemplate;	
  	
  
	
  
//	
  method	
  references	
  	
  
private	
  Customer	
  map(ResultSet	
  rs,	
  int	
  rowNum)	
  throws	
  SQLExcepSon	
  {	
  	
  
	
  return	
  new	
  Customer(	
  rs.getString("name"),	
  rs.getInt("age")	
  );	
  }	
  	
  
	
  
//	
  let	
  it	
  saSsfy	
  the	
  `RowMapper`	
  funcSonal	
  interface	
  	
  
Customer	
  customer	
  =	
  jdbcTemplate.queryForObject(	
  	
  
	
  "select	
  name,	
  age	
  from	
  customers	
  ",this::map);	
  	
  
	
  
Customer	
  customer	
  =	
  jdbcTemplate.queryForObject(sql,	
  
	
  (rs,	
  rowNum)	
  -­‐>	
  new	
  Customer(rs.getLong("id")));	
  	
  
	
  

4.0	
  M1	
  
4.0	
  M1	
  

Lambdas	
  fit	
  naturally	
  wherever	
  you	
  
have	
  funcSonal	
  interfaces	
  
JmsTemplate+MessageCreator:	
  	
  
=>	
  Message	
  createMessage(Session	
  session)	
  throws	
  
JMSExcepSon	
  	
  
	
  
TransacSonTemplate+Transac9onCallback:	
  	
  
=>	
  Object	
  doInTransacSon(TransacSonStatus	
  status)	
  	
  
	
  
And	
  other:	
  
•  JdbcTemplate:	
  
–  ResultSetExtractor,	
  RowCallbackHandler	
  

•  JmsTemplate:	
  

–  MessagePostProcessor,	
  BrowserCallback	
  

• 

TaskExecutor:	
  

–  Runnable,	
  Callable	
  
4.0	
  M1	
  

JSR-­‐310	
  Date	
  and	
  Time	
  support	
  
import	
  java.Sme.*;	
  
import	
  org.springframework.format.annotaSon.*;	
  
	
  
public	
  class	
  Trade{	
  
	
  
	
  //…	
  
	
  
	
  @DateTimeFormat(iso=ISO.DATE)	
  
	
  private	
  LocalDate	
  tradeDate;	
  	
  
	
  	
  
	
  
	
  @DateTimeFormat(iso=ISO.DATE)	
  
	
  private	
  LocalDateTime	
  createTimestamp;	
  
}	
  
4.0	
  M1	
  

JDK8	
  support	
  in	
  depth	
  
•  Implicit	
  use	
  of	
  LinkedHashMap/Set	
  instead	
  of	
  simple	
  
HashMap/Set	
  to	
  preserve	
  ordering	
  diffs	
  in	
  JDK7	
  and	
  JDK8	
  
•  Embed	
  ASM4.1	
  into	
  Spring	
  codebase	
  to	
  support	
  JDK8	
  
bytecode	
  changes	
  and	
  to	
  keep	
  compaSbility	
  with	
  CGLib3.0	
  
•  Support	
  for	
  JDK	
  8	
  Data	
  &	
  Time	
  (JSR-­‐310)	
  encorporated	
  with	
  
Spring’s	
  Joda	
  Time	
  lib	
  
•  Add	
  awaitTerminaSonSeconds/commonPool	
  properSes	
  to	
  
ForkJoinPoolFactoryBean	
  to	
  support	
  JDK8	
  changes	
  in	
  it.	
  
•  Encorporate	
  JDK8	
  changes	
  in	
  reflecSon	
  API	
  (such	
  as	
  
java.lang.reflect.Parameter)	
  
Bean	
  ValidaSon	
  1.1	
  support	
  

4.0	
  M1	
  

MethodValida+onInterceptor	
  autodetects	
  Bean	
  Valida/on	
  1.1's	
  ExecutableValidator	
  API	
  now	
  	
  
and	
  uses	
  it	
  in	
  favor	
  of	
  Hibernate	
  Validator	
  4.2's	
  na/ve	
  variant.	
  
JMS	
  2.0	
  support	
  

4.0	
  M1	
  

What	
  was	
  done	
  already:	
  
•  Added	
  "deliveryDelay"	
  property	
  on	
  JmsTemplate	
  
•  Added	
  support	
  for	
  "deliveryDelay"	
  and	
  CompleSonListener	
  to	
  
CachedMessageProducer	
  
•  Added	
  support	
  for	
  the	
  new	
  "create(Shared)DurableConsumer"	
  variants	
  in	
  
Spring’s	
  CachingConnecSonFactory	
  
•  Added	
  support	
  for	
  the	
  new	
  "createSession"	
  variants	
  with	
  fewer	
  
parameters	
  in	
  Spring’s	
  SingleConnecSonFactory	
  
Known	
  constraints:	
  
•  There	
  is	
  no	
  special	
  support	
  for	
  the	
  simplified	
  JMSContext	
  API,	
  and	
  likely	
  
never	
  will	
  be,	
  because	
  of	
  different	
  Spring	
  mechanism	
  of	
  managing	
  
connecSon	
  pools	
  and	
  sessions	
  
•  JmsTemplate	
  has	
  no	
  out-­‐of-­‐the-­‐box	
  support	
  for	
  send	
  calls	
  with	
  an	
  async	
  
compleSon	
  listener.	
  
JEE7	
  concurrency	
  uSliSes	
  in	
  Spring	
  4	
  

4.0	
  M1	
  

This	
  is	
  built	
  into	
  ConcurrentTaskExecutor	
  and	
  ConcurrentTaskScheduler	
  now,	
  
automaScally	
  detecSng	
  the	
  JSR-­‐236	
  ExecutorService	
  variants	
  and	
  adapSng	
  
to	
  them.	
  
Example	
  of	
  ManagedExecutorService	
  usage	
  introduced	
  in	
  JEE7:	
  	
  
	
  
4.0	
  M1	
  

JPA	
  2.1	
  support	
  
EnStyManagerFactory.createEnStyManager(	
  
	
  Synchroniza9onType.SYNCHRONIZED/UNSYNCHRONIZED,	
  Map)	
  	
  
	
  
@PersistenceContext(	
  
	
  synchronizaSonType=SYNCHRONIZED/UNSYNCHRONIZED)	
  	
  
	
  
	
  
	
  
	
  Support	
  for	
  both	
  transacSonal	
  and	
  extended	
  EnStyManagers	
  	
  
	
  and	
  for	
  both	
  Spring-­‐managed	
  resource	
  transacSons	
  and	
  JTA	
  
transacSons	
  
WebSocket	
  JSR-­‐356	
  support	
  

4.0	
  M1	
  

(Annota/on	
  driven	
  using	
  Servlet	
  container	
  scan)	
  
import	
  javax.websocket.server.ServerEndpoint;	
  
import	
  org.springframework.web.socket.server.endpoint.SpringConfigurator;	
  
	
  
@ServerEndpoint(value	
  =	
  "/echo",	
  configurator	
  =	
  SpringConfigurator.class)	
  
public	
  class	
  EchoEndpoint	
  {	
  
	
  
	
  	
  private	
  final	
  EchoService	
  echoService;	
  
	
  
	
  	
  @Autowired	
  
	
  	
  public	
  EchoEndpoint(EchoService	
  echoService)	
  {	
  
	
  	
  	
  	
  this.echoService	
  =	
  echoService;	
  
	
  	
  }	
  
	
  
	
  	
  @OnMessage	
  
	
  	
  public	
  void	
  handleMessage(Session	
  session,	
  String	
  message)	
  {	
  
	
  	
  	
  	
  //	
  ...	
  
	
  	
  }	
  
}	
  
WebSocket	
  JSR-­‐356	
  support	
  

(Spring	
  container-­‐centric	
  registra/on)	
  
import	
  org.springframework.web.socket.server.endpoint.ServerEndpointExporter;	
  
	
  
@ConfiguraSon	
  
public	
  class	
  EndpointConfig	
  {	
  
	
  
	
  	
  @Bean	
  
	
  	
  public	
  EchoEndpoint	
  echoEndpoint()	
  {	
  
	
  	
  	
  	
  return	
  new	
  EchoEndpoint(echoService());	
  
	
  	
  }	
  
	
  
	
  	
  @Bean	
  
	
  	
  public	
  EchoService	
  echoService()	
  {	
  
	
  	
  	
  	
  //	
  ...	
  
	
  	
  }	
  
	
  
	
  	
  @Bean	
  
	
  	
  public	
  ServerEndpointExporter	
  endpointExporter()	
  {	
  
	
  	
  	
  	
  return	
  new	
  ServerEndpointExporter();	
  
	
  	
  }	
  
}	
  

4.0	
  M1	
  
WebSocket	
  JSR-­‐356	
  support	
  

(Separate	
  endpoint	
  instance	
  per	
  socket)	
  
import	
  org.springframework.web.socket.server.endpoint.ServerEndpointExporter;	
  
import	
  org.springframework.web.socket.server.endpoint.ServerEndpointRegistra9on;	
  
	
  
@ConfiguraSon	
  
public	
  class	
  EndpointConfig	
  {	
  
	
  
	
  	
  @Bean	
  
	
  	
  public	
  EndpointRegistra9on	
  echoEndpoint()	
  {	
  
	
  	
  	
  	
  return	
  new	
  EndpointRegistra9on("/echo",	
  EchoEndpoint.class);	
  
	
  	
  }	
  
	
  
	
  	
  @Bean	
  
	
  	
  public	
  ServerEndpointExporter	
  endpointExporter()	
  {	
  
	
  	
  	
  	
  return	
  new	
  ServerEndpointExporter();	
  
	
  	
  }	
  
	
  
	
  	
  //	
  ..	
  
}	
  

4.0	
  M1	
  
4.0	
  M1	
  

WebSocket	
  JSR-­‐356	
  client	
  side	
  support	
  

Purely	
  programmaSc	
  way:	
  
	
  

WebSocketContainer	
  container	
  =	
  ContainerProvider.getWebSocketContainer();	
  
container.connectToServer(EchoEndpoint.class,	
  new	
  URI("ws:localhost:8080/webapp/echo"));	
  
	
  

Using	
  Spring	
  ApplicaSonContext:	
  
	
  

import	
  org.springframework.web.socket.client.endpoint.AnnotatedEndpointConnec9onManager;	
  
	
  
@ConfiguraSon	
  
public	
  class	
  EndpointConfig	
  {	
  
	
  
	
  	
  //	
  For	
  Endpoint	
  sub-­‐classes	
  use	
  EndpointConnecSonManager	
  instead	
  
	
  
	
  	
  @Bean	
  
	
  	
  public	
  AnnotatedEndpointConnec9onManager	
  connecSonManager()	
  {	
  
	
  	
  	
  	
  return	
  new	
  AnnotatedEndpointConnec9onManager(echoEndpoint(),	
  "ws://localhost:8080/webapp/echo");	
  
	
  	
  }	
  
	
  
	
  	
  @Bean	
  
	
  	
  public	
  EchoEndpoint	
  echoEndpoint()	
  {	
  
	
  	
  	
  	
  //	
  ...	
  
	
  	
  }	
  
}	
  
	
  
Spring	
  WebSocket	
  API	
  
Why	
  own	
  API?	
  
•  To	
  support	
  available	
  fallback	
  opSons	
  for	
  
WebSockets	
  such	
  as	
  SockJS.	
  
•  WebSocket	
  API	
  is	
  too	
  low	
  level	
  (messages	
  could	
  
be	
  anything,	
  no	
  broadcast,	
  no	
  failure	
  handling	
  
mechanism,	
  etc.)	
  	
  
•  No	
  	
  way	
  to	
  handle	
  both	
  HTTP	
  and	
  WebSocket	
  
requests	
  in	
  one	
  place	
  as	
  per	
  Front	
  Controller	
  
pabern.	
  
•  No	
  sub-­‐protocol	
  and	
  higher	
  level	
  protocols	
  
support.	
  
Spring	
  WebSocket	
  API	
  	
  
I	
  
Inspira/on	
  
	
  	
  
Programming	
  model	
  for	
  building	
  message-­‐
oriented	
  applicaSons	
  using	
  STOMP	
  over	
  
WebSocket	
  protocol	
  for	
  example	
  
•  Transparent	
  WebSocket	
  emulaSon	
  using	
  SockJS	
  
•  Separate	
  messaging	
  module	
  with	
  main	
  messaging	
  
abstracSons	
  taken	
  from	
  Spring	
  IntegraSon	
  
•  STOMP	
  sub-­‐protocol	
  support	
  (built-­‐in	
  simple	
  STOMP	
  
broker)	
  
•  Higher	
  level	
  programming	
  model	
  
STOMP	
  
SUBSCRIBE 	
  	
  
id:sub-­‐1 	
  	
  
desSnaSon:/topic/price.stock.* 	
  	
  
	
  
MESSAGE 	
  	
  
subscripSon:sub-­‐1
	
  	
  
message-­‐id:wm2si1tj-­‐4	
  	
  
content-­‐type:	
  applicaSon/json
	
  	
  
desSnaSon:/topic/stocks.PRICE.STOCK.NASDAQ.EM
	
  	
  
{"Scker":"EMC","price":24.19}
	
  	
  
	
  
WebSocket	
  Client	
  API	
  
var	
  socket	
  =	
  new	
  SockJS('/spring-­‐websocket-­‐porholio/
porholio'); 	
  	
  
var	
  client	
  =	
  Stomp.over(socket);
	
  	
  
	
  
	
  	
  
var	
  onConnect	
  =	
  funcSon()	
  { 	
  	
  
	
  	
  client.subscribe("/topic/price.stock.*",	
  func9on(message)	
  {	
  
	
  	
  	
  	
  	
  	
  //	
  process	
  quote 	
  	
  
	
  	
  }); 	
  	
  
};
	
  	
  
client.connect('guest',	
  'guest',	
  onConnect); 	
  	
  
	
  
Spring	
  Simple	
  Messaging	
  API	
  

4.0	
  M1	
  

(Handling	
  STOMP	
  message	
  sent	
  via	
  WebSocket	
  
protocol)	
  
@Controller 	
  	
  
public	
  class	
  Por~olioController	
  { 	
  	
  
	
  
	
  	
  
	
  	
  //	
  ... 	
  	
  
	
  
	
  	
  
	
  	
  @MessageMapping(value="/app/trade")
	
  	
  
	
  	
  public	
  void	
  executeTrade(Trade	
  trade,	
  Principal	
  principal)	
  {
	
  	
  
	
  	
  	
  	
  trade.setUsername(principal.getName());
	
  	
  
	
  	
  	
  	
  this.tradeService.executeTrade(trade); 	
  	
  
	
  	
  }
	
  	
  
}
	
  	
  
	
  
Spring	
  Simple	
  Messaging	
  API	
  
(Failures	
  handling)	
  

@Controller 	
  	
  
public	
  class	
  Por~olioController	
  { 	
  	
  
	
  
	
  	
  
	
  	
  //	
  ... 	
  	
  
	
  
	
  	
  
	
  	
  @MessageExcep9onHandler	
  
	
  	
  @SendToUser("/queue/errors") 	
  	
  
	
  	
  public	
  String	
  handleExcepSon(Throwable	
  excepSon)	
  { 	
  	
  
	
  	
  	
  	
  return	
  excepSon.getMessage(); 	
  	
  
	
  	
  }
	
  	
  
}
	
  	
  
	
  

4.0	
  M1	
  
Spring	
  Simple	
  Messaging	
  API	
  

(Handle	
  SUBSCRIBE	
  events	
  from	
  client)	
  
@Controller 	
  	
  
public	
  class	
  Por~olioController	
  {	
  	
  
	
  
	
  	
  
	
  	
  //	
  ... 	
  	
  
	
  
	
  	
  
	
  	
  @SubscribeMapping("/app/posi9ons")
	
  	
  
	
  	
  public	
  List<Por~olioPosiSon>	
  getPor~olios(Principal	
  principal)	
  {	
  	
  
	
  	
  	
  	
  String	
  user	
  =	
  principal.getName();
	
  	
  
	
  	
  	
  	
  Por~olio	
  por~olio	
  =	
  this.por~olioService.findPor~olio(user); 	
  	
  
	
  	
  	
  	
  return	
  por~olio.getPosiSons();
	
  	
  
	
  	
  }
	
  	
  
}
	
  	
  
	
  

4.0	
  M1	
  
Spring	
  Simple	
  Messaging	
  API	
  

4.0	
  M1	
  

(Sending	
  updates	
  to	
  client	
  periodically)	
  
@Service
	
  	
  
public	
  class	
  QuoteService	
  {
	
  	
  
	
  
	
  	
  
	
  	
  private	
  final	
  MessageSendingOpera9ons<String>	
  messagingTemplate;	
  
	
  	
  
	
  	
  @Scheduled(fixedDelay=1000) 	
  	
  
	
  	
  public	
  void	
  sendQuotes()	
  {
	
  	
  
	
  	
  	
  	
  for	
  (Quote	
  quote	
  :	
  this.quoteGenerator.generateQuotes())	
  {
	
  	
  
	
  	
  	
  	
  	
  	
  String	
  desSnaSon	
  =	
  "/topic/price.stock."	
  +	
  quote.getTicker(); 	
  	
  
	
  	
  	
  	
  	
  	
  this.messagingTemplate.convertAndSend(des9na9on,	
  quote);	
  	
  
	
  	
  	
  	
  }
	
  	
  
	
  	
  }
	
  	
  
}
	
  	
  
Spring	
  Simple	
  Messaging	
  API	
  
(Configura/on)	
  

@ConfiguraSon	
  
@EnableWebSocketMessageBroker	
  
@EnableScheduling	
  
@ComponentScan(basePackages="org.springframework.samples")	
  
public	
  class	
  WebSocketConfig	
  implements	
  WebSocketMessageBrokerConfigurer	
  {	
  
	
  
	
  @Override	
  
	
  public	
  void	
  registerStompEndpoints(StompEndpointRegistry	
  registry)	
  {	
  
	
  
	
  registry.addEndpoint("/porholio").withSockJS();	
  
	
  }	
  
	
  
	
  @Override	
  
	
  public	
  void	
  configureMessageBroker(MessageBrokerConfigurer	
  configurer)	
  {	
  
	
  
	
  configurer.enableSimpleBroker("/queue/",	
  "/topic/");	
  
	
  
	
  //configurer.enableStompBrokerRelay("/queue/",	
  "/topic/");	
  
	
  
	
  configurer.setApplica9onDes9na9onPrefixes("/app");	
  
	
  }	
  
}	
  

4.0	
  M1	
  
spring-­‐websocket-­‐por~olio	
  	
  
DEMO	
  app	
  architecture	
  
Composable	
  stereotype	
  model	
  
@Service	
  
@Scope(“session”)	
  
@Primary	
  
@Transac9onal(rollbackFor=Run9meExcep9on.class)	
  
@RetenSon(RetenSonPolicy.RUNTIME)	
  
public	
  @interface	
  MyService	
  {	
  
	
  boolean	
  readOnly();	
  
}	
  
	
  
@MyService(readOnly=true)	
  
public	
  class	
  MyTradeService	
  {	
  
	
  //…	
  
}	
  
JEE	
  annotaSon	
  support	
  conSnue	
  
@ManagedBean	
  
public	
  class	
  MyTradeService	
  implements	
  TradeService{	
  
	
  	
  
	
  @Inject	
  
	
  public	
  MyTradeService(MatchingService	
  service){	
  
	
  
	
  //…	
  
	
  }	
  
	
  
	
  @javax.transac9on.Transac9onal	
  
	
  	
  public	
  void	
  matchTrade(Trade	
  trade){	
  
	
  
	
  //…	
  
	
  }
	
  	
  
}	
  
	
  
@CondiSonal	
  annotaSon	
  
@Condi9onal(MyCondi9on.class)	
  
@Configura9on	
  	
  
public	
  class	
  ExampleConfiguraSon	
  {	
  
	
  
	
  //	
  @Bean	
  methods	
  
}	
  
	
  
	
  
public	
  class	
  MyCondi9on	
  implements	
  Condi9on	
  {	
  
	
  
	
  public	
  boolean	
  matches(...)	
  {	
  
	
  
	
  //	
  return	
  true	
  if	
  the	
  condiSon	
  holds	
  true	
  
	
  }	
  
}	
  

4.0	
  M2	
  
Make	
  #result	
  available	
  for	
  SpEL	
  in	
  
@CachePut	
  key	
  abribute	
  

4.0	
  M2	
  

@CachePut(value	
  =	
  "personEn9ty",	
  key	
  =	
  "#result.id")	
  
public	
  Person	
  persistPerson(Person	
  p)	
  {	
  
	
  	
  Person	
  result	
  =	
  personRepository.save(p);	
  
	
  	
  return	
  result;	
  
}	
  
	
  
@EnSty	
  
public	
  class	
  Person	
  {	
  
	
  	
  @Id	
  @GeneratedValue	
  
	
  	
  private	
  Long	
  id;	
  
	
  	
  …	
  
}	
  
Introduce	
  AcSveProfilesResolver	
  in	
  the	
  
TestContext	
  framework	
  
@RunWith(SpringJUnitRunner.class)	
  
@ContextConfiguraSon(TestContext.class)	
  
@Ac9veProfiles	
  
public	
  class	
  IntegraSonTest	
  {	
  
	
  	
  	
  	
  //…	
  
	
  	
  	
  	
  @Test	
  
	
  	
  	
  	
  public	
  void	
  integraSonTest(){	
  
	
  	
  	
  	
  	
  	
  	
  	
  //...	
  
	
  	
  	
  	
  }	
  
}	
  
	
  
@ConfiguraSon	
  
public	
  class	
  TestContext{	
  
	
  	
  	
  	
  @Bean	
  
	
  	
  	
  	
  public	
  Ac9veProfilesResolver	
  acSveProfilesResolver(){	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  new	
  Ac9veProfilesResolver(){	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  String[]	
  resolve(Class<?>	
  testClass){	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  //…	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  new	
  String[]{"test"};	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  };	
  
	
  	
  	
  	
  }	
  
	
  	
  	
  	
  //...	
  
}	
  

4.0	
  M2	
  
4.0	
  M3	
  

Autowiring	
  ordered	
  collecSons	
  based	
  
on	
  @Order	
  annotaSon	
  
@Component	
  
@Order(value=1)	
  
public	
  class	
  BusinessServiceA	
  implements	
  BusinessService{}	
  
	
  
@Component	
  
@Order(value=2)	
  
public	
  class	
  BusinessServiceB	
  implements	
  BusinessService{}	
  
	
  
@Component	
  
public	
  class	
  ServiceRegistry	
  {	
  
	
  @Autowired	
  
	
  public	
  List<BusinessService>	
  services;	
  
}	
  
	
  
assertThat(services.get(0).getClass(),	
  is(BusinessServiceA.class));	
  
assertThat(services.get(1).getClass(),	
  is(BusinessServiceB.class));	
  
@PropertySources	
  annotaSon	
  

4.0	
  RC1	
  

@ConfiguraSon	
  
@PropertySources({	
  
	
  	
  @PropertySource(value	
  =	
  "file:/etc/applicaSon/config.properSes",	
  
	
  ignoreResourceNotFound	
  =	
  true),	
  
	
  	
  @PropertySource(value	
  =	
  "file:/usr/local/etc/applicaSon/config.properSes",	
  
	
  ignoreResourceNotFound	
  =	
  true),	
  
	
  	
  @PropertySource(value	
  =	
  "file:conf/config.properSes",	
  
	
  ignoreResourceNotFound	
  =	
  true),	
  
	
  	
  @PropertySource(value	
  =	
  "classpath:applicaSon.properSes")	
  
})	
  
public	
  class	
  AppConfiguraSon{	
  
	
  //…	
  
}	
  
	
  
Or	
  even	
  without	
  @PropertySources	
  using	
  Java8	
  repeatable	
  annota/ons!!!	
  
Autowiring	
  of	
  generic	
  types	
  

4.0	
  RC1	
  
Groovy	
  config	
  
def	
  bb	
  =	
  new	
  BeanBuilder()	
  	
  
bb.loadBeans("classpath:*SpringBeans.groovy")	
  
def	
  applica9onContext	
  =	
  bb.createApplicaSonContext()	
  	
  
	
  
//	
  MySpringBeans.groovy	
  	
  
import	
  o.sf.jdbc.core.JdbcTemplate	
  
import	
  o.sf.jdbc.datasource.DataSourceTransac9onManager	
  	
  
beans	
  {	
  	
  
	
  jdbcTemplate(JdbcTemplate)	
  {	
  	
  
	
  
	
  dataSource	
  =	
  dataSource	
  	
  
	
  }	
  	
  
	
  transac9onManager(DataSourceTransac9onManager){	
  	
  
	
  
	
  dataSource	
  =	
  dataSource	
  	
  
	
  }	
  	
  
	
  dataSource(BasicDataSource)	
  
	
  
	
  driverClassName	
  ="org.h2.Driver"	
  
	
  
	
  url="jdbc:h2:mem:grailsDB"	
  
	
  
	
  username="sa"	
  
	
  
	
  password=""	
  
	
  }	
  
}	
  	
  

4.0	
  RC1	
  
@ControllerAdvice	
  annotaSon	
  
@ControllerAdvice({"com.example.web.api"})	
  
public	
  class	
  GlobalErrorHandler	
  {	
  	
  
	
  	
  	
  //	
  common	
  @ExcepSonHandler	
  methods	
  are	
  defined	
  here	
  
}	
  
	
  
Will	
  be	
  applied	
  to	
  both	
  Controllers	
  below:	
  
com.example.web.api.feature1.Feature1Controller	
  	
  
com.example.web.api.feature2.Featuer2Controller	
  

4.0	
  RC1	
  
Other	
  changes…	
  
4.0	
  M1	
  
•  Replace	
  EasyMock	
  with	
  Mockito	
  
•  [SPR-­‐8258]	
  EhCache	
  2.5	
  support	
  
4.0	
  M2	
  
•  [SPR-­‐10664]	
  Make	
  #result	
  available	
  for	
  SpEL	
  in	
  @CachePut	
  key	
  abribute	
  
•  [SPR-­‐10338]	
  Introduce	
  AcSveProfilesResolver	
  in	
  the	
  TestContext	
  
framework	
  
4.0	
  M3	
  
•  [SPR-­‐5574]	
  Autowiring	
  should	
  support	
  ordered	
  collecSon	
  driven	
  by	
  Order	
  
annotaSon	
  or	
  Ordered	
  interface	
  
4.0	
  RC1	
  
•  [SPR-­‐8371]	
  Add	
  @PropertySources	
  annotaSon	
  and	
  support	
  
ignoreResourceNotFound	
  and	
  preserve	
  mulSple	
  @PropertySources	
  order	
  
•  [SPR-­‐10222]	
  Allow	
  @ControllerAdvice	
  to	
  be	
  cofigured	
  with	
  a	
  join	
  point	
  to	
  
target	
  a	
  subset	
  of	
  controller	
  
How	
  to	
  track	
  progress?	
  
•  Track	
  JIRA	
  -­‐	
  
hbps://jira.springsource.org/browse/SPR/
fixforversion/14229	
  
•  Check	
  commits	
  to	
  codebase	
  -­‐	
  
hbps://github.com/SpringSource/spring-­‐
framework/commits/master	
  
Thank	
  you!	
  
Oleg	
  Tsal-­‐Tsalko	
  
Email:	
  oleg.tsalko@gmail.com	
  
Twiber:	
  @tsaltsol	
  
	
  
	
  
	
  

Get ready for spring 4

  • 1.
    Get  ready  for  Spring  4   Speaker:  Oleg  Tsal-­‐Tsalko  (@tsaltsol)  
  • 3.
  • 4.
  • 5.
    Spring  Boot  Groovy  app   @Controller   class  ThisWillActuallyRun  {            @RequestMapping("/")          @ResponseBody          String  home()  {                  return  "Hello  World!"          }     }    
  • 6.
    Spring  Boot  Java  app   import  org.springframework.boot.*;   import  org.springframework.boot.autoconfigure.*;   import  org.springframework.stereotype.*;   import  org.springframework.web.bind.annotaSon.*;     @Controller   @EnableAutoConfigura9on   public  class  SampleController  {            @RequestMapping("/")          @ResponseBody          String  home()  {                  return  "Hello  World!";          }            public  staSc  void  main(String[]  args)  throws  ExcepSon  {                  SpringApplica9on.run(SampleController.class,  args);          }   }    
  • 7.
    Spring  XD  architecture   Files   Sensors   Mobile   Social   Spring  XD  Shell   Spring  XD  RunSme   Gemfire   Taps   Jobs   Compute   HDFS   PredicSve  modeling   Workflow   Redis   Ingest   Streams   Export   Export   RDBMS   NoSQL   R,  SAS  
  • 8.
    Spring  XD  RunSme   XD  Admin   hbp  |  filter  |  file   CLUSTERED  NODE   CLUSTERED  NODE   CLUSTERED  NODE   SINGLE   NODE   HTTP   Module   Filter   Module   File   Module   All   Modules   Rabbit,  Redis,  (Pluggable)   In  Memory   Transport   hbp  |  filter  |  file  
  • 9.
    Spring  4.0   Almost  there…  RC1  now!!!  
  • 10.
    Spring  4.0   [RC1]   Biggest  changes:   •  Comprehensive  Java  8  support   •  Support  for  Java  EE  7  APIs   •  WebSocket  support   •  Programming  model  for  message-­‐oriented  architectures   Smaller  features:   •  Support  for  @javax.transacSon.TransacSonal   •  New  @CondiSonal  annotaSon   •  New  @RestController  annotaSon   •  AsyncRestTemplate   •  Autowiring  of  generic  types   •  Groovy  based  config   And  more…  
  • 11.
    4.0  M1   Java  8  &  Java  EE  7  support   Comprehensive  Java  8   support   • Lambdas   • Date  and  Time  API  (JSR-­‐310)   • Parameter  name  discovery   • Repeatable  annotaSons   • Concurrency  enhancement   Support  for  Java  EE  7  APIs   • Asynchronous  API  for  RestTemplate   • Bean  ValidaSon  1.1  (JSR-­‐349)   • Expression  Language  3.0  (JSR-­‐341)   • JMS  2.0  (JSR-­‐343)   • Concurrency  USliSes  for  Java  EE   (JSR-­‐236)   • JPA  2.1  (JSR-­‐338)   • Servlet  3.1  (JSR-­‐340)   • JSF  2.2  (JSR-­‐344)  
  • 12.
    Get  advantage  of  Java  8  lambdas   in  well  known  Spring  APIs!!!   JdbcTemplate  jdbcTemplate;       //  method  references     private  Customer  map(ResultSet  rs,  int  rowNum)  throws  SQLExcepSon  {      return  new  Customer(  rs.getString("name"),  rs.getInt("age")  );  }       //  let  it  saSsfy  the  `RowMapper`  funcSonal  interface     Customer  customer  =  jdbcTemplate.queryForObject(      "select  name,  age  from  customers  ",this::map);       Customer  customer  =  jdbcTemplate.queryForObject(sql,    (rs,  rowNum)  -­‐>  new  Customer(rs.getLong("id")));       4.0  M1  
  • 13.
    4.0  M1   Lambdas  fit  naturally  wherever  you   have  funcSonal  interfaces   JmsTemplate+MessageCreator:     =>  Message  createMessage(Session  session)  throws   JMSExcepSon       TransacSonTemplate+Transac9onCallback:     =>  Object  doInTransacSon(TransacSonStatus  status)       And  other:   •  JdbcTemplate:   –  ResultSetExtractor,  RowCallbackHandler   •  JmsTemplate:   –  MessagePostProcessor,  BrowserCallback   •  TaskExecutor:   –  Runnable,  Callable  
  • 14.
    4.0  M1   JSR-­‐310  Date  and  Time  support   import  java.Sme.*;   import  org.springframework.format.annotaSon.*;     public  class  Trade{      //…      @DateTimeFormat(iso=ISO.DATE)    private  LocalDate  tradeDate;            @DateTimeFormat(iso=ISO.DATE)    private  LocalDateTime  createTimestamp;   }  
  • 15.
    4.0  M1   JDK8  support  in  depth   •  Implicit  use  of  LinkedHashMap/Set  instead  of  simple   HashMap/Set  to  preserve  ordering  diffs  in  JDK7  and  JDK8   •  Embed  ASM4.1  into  Spring  codebase  to  support  JDK8   bytecode  changes  and  to  keep  compaSbility  with  CGLib3.0   •  Support  for  JDK  8  Data  &  Time  (JSR-­‐310)  encorporated  with   Spring’s  Joda  Time  lib   •  Add  awaitTerminaSonSeconds/commonPool  properSes  to   ForkJoinPoolFactoryBean  to  support  JDK8  changes  in  it.   •  Encorporate  JDK8  changes  in  reflecSon  API  (such  as   java.lang.reflect.Parameter)  
  • 16.
    Bean  ValidaSon  1.1  support   4.0  M1   MethodValida+onInterceptor  autodetects  Bean  Valida/on  1.1's  ExecutableValidator  API  now     and  uses  it  in  favor  of  Hibernate  Validator  4.2's  na/ve  variant.  
  • 17.
    JMS  2.0  support   4.0  M1   What  was  done  already:   •  Added  "deliveryDelay"  property  on  JmsTemplate   •  Added  support  for  "deliveryDelay"  and  CompleSonListener  to   CachedMessageProducer   •  Added  support  for  the  new  "create(Shared)DurableConsumer"  variants  in   Spring’s  CachingConnecSonFactory   •  Added  support  for  the  new  "createSession"  variants  with  fewer   parameters  in  Spring’s  SingleConnecSonFactory   Known  constraints:   •  There  is  no  special  support  for  the  simplified  JMSContext  API,  and  likely   never  will  be,  because  of  different  Spring  mechanism  of  managing   connecSon  pools  and  sessions   •  JmsTemplate  has  no  out-­‐of-­‐the-­‐box  support  for  send  calls  with  an  async   compleSon  listener.  
  • 18.
    JEE7  concurrency  uSliSes  in  Spring  4   4.0  M1   This  is  built  into  ConcurrentTaskExecutor  and  ConcurrentTaskScheduler  now,   automaScally  detecSng  the  JSR-­‐236  ExecutorService  variants  and  adapSng   to  them.   Example  of  ManagedExecutorService  usage  introduced  in  JEE7:      
  • 19.
    4.0  M1   JPA  2.1  support   EnStyManagerFactory.createEnStyManager(    Synchroniza9onType.SYNCHRONIZED/UNSYNCHRONIZED,  Map)       @PersistenceContext(    synchronizaSonType=SYNCHRONIZED/UNSYNCHRONIZED)            Support  for  both  transacSonal  and  extended  EnStyManagers      and  for  both  Spring-­‐managed  resource  transacSons  and  JTA   transacSons  
  • 20.
    WebSocket  JSR-­‐356  support   4.0  M1   (Annota/on  driven  using  Servlet  container  scan)   import  javax.websocket.server.ServerEndpoint;   import  org.springframework.web.socket.server.endpoint.SpringConfigurator;     @ServerEndpoint(value  =  "/echo",  configurator  =  SpringConfigurator.class)   public  class  EchoEndpoint  {        private  final  EchoService  echoService;        @Autowired      public  EchoEndpoint(EchoService  echoService)  {          this.echoService  =  echoService;      }        @OnMessage      public  void  handleMessage(Session  session,  String  message)  {          //  ...      }   }  
  • 21.
    WebSocket  JSR-­‐356  support   (Spring  container-­‐centric  registra/on)   import  org.springframework.web.socket.server.endpoint.ServerEndpointExporter;     @ConfiguraSon   public  class  EndpointConfig  {        @Bean      public  EchoEndpoint  echoEndpoint()  {          return  new  EchoEndpoint(echoService());      }        @Bean      public  EchoService  echoService()  {          //  ...      }        @Bean      public  ServerEndpointExporter  endpointExporter()  {          return  new  ServerEndpointExporter();      }   }   4.0  M1  
  • 22.
    WebSocket  JSR-­‐356  support   (Separate  endpoint  instance  per  socket)   import  org.springframework.web.socket.server.endpoint.ServerEndpointExporter;   import  org.springframework.web.socket.server.endpoint.ServerEndpointRegistra9on;     @ConfiguraSon   public  class  EndpointConfig  {        @Bean      public  EndpointRegistra9on  echoEndpoint()  {          return  new  EndpointRegistra9on("/echo",  EchoEndpoint.class);      }        @Bean      public  ServerEndpointExporter  endpointExporter()  {          return  new  ServerEndpointExporter();      }        //  ..   }   4.0  M1  
  • 23.
    4.0  M1   WebSocket  JSR-­‐356  client  side  support   Purely  programmaSc  way:     WebSocketContainer  container  =  ContainerProvider.getWebSocketContainer();   container.connectToServer(EchoEndpoint.class,  new  URI("ws:localhost:8080/webapp/echo"));     Using  Spring  ApplicaSonContext:     import  org.springframework.web.socket.client.endpoint.AnnotatedEndpointConnec9onManager;     @ConfiguraSon   public  class  EndpointConfig  {        //  For  Endpoint  sub-­‐classes  use  EndpointConnecSonManager  instead        @Bean      public  AnnotatedEndpointConnec9onManager  connecSonManager()  {          return  new  AnnotatedEndpointConnec9onManager(echoEndpoint(),  "ws://localhost:8080/webapp/echo");      }        @Bean      public  EchoEndpoint  echoEndpoint()  {          //  ...      }   }    
  • 24.
    Spring  WebSocket  API   Why  own  API?   •  To  support  available  fallback  opSons  for   WebSockets  such  as  SockJS.   •  WebSocket  API  is  too  low  level  (messages  could   be  anything,  no  broadcast,  no  failure  handling   mechanism,  etc.)     •  No    way  to  handle  both  HTTP  and  WebSocket   requests  in  one  place  as  per  Front  Controller   pabern.   •  No  sub-­‐protocol  and  higher  level  protocols   support.  
  • 25.
    Spring  WebSocket  API     I   Inspira/on       Programming  model  for  building  message-­‐ oriented  applicaSons  using  STOMP  over   WebSocket  protocol  for  example   •  Transparent  WebSocket  emulaSon  using  SockJS   •  Separate  messaging  module  with  main  messaging   abstracSons  taken  from  Spring  IntegraSon   •  STOMP  sub-­‐protocol  support  (built-­‐in  simple  STOMP   broker)   •  Higher  level  programming  model  
  • 26.
    STOMP   SUBSCRIBE     id:sub-­‐1     desSnaSon:/topic/price.stock.*       MESSAGE     subscripSon:sub-­‐1     message-­‐id:wm2si1tj-­‐4     content-­‐type:  applicaSon/json     desSnaSon:/topic/stocks.PRICE.STOCK.NASDAQ.EM     {"Scker":"EMC","price":24.19}      
  • 27.
    WebSocket  Client  API   var  socket  =  new  SockJS('/spring-­‐websocket-­‐porholio/ porholio');     var  client  =  Stomp.over(socket);           var  onConnect  =  funcSon()  {        client.subscribe("/topic/price.stock.*",  func9on(message)  {              //  process  quote        });     };     client.connect('guest',  'guest',  onConnect);      
  • 28.
    Spring  Simple  Messaging  API   4.0  M1   (Handling  STOMP  message  sent  via  WebSocket   protocol)   @Controller     public  class  Por~olioController  {              //  ...              @MessageMapping(value="/app/trade")        public  void  executeTrade(Trade  trade,  Principal  principal)  {            trade.setUsername(principal.getName());            this.tradeService.executeTrade(trade);        }     }      
  • 29.
    Spring  Simple  Messaging  API   (Failures  handling)   @Controller     public  class  Por~olioController  {              //  ...              @MessageExcep9onHandler      @SendToUser("/queue/errors")        public  String  handleExcepSon(Throwable  excepSon)  {            return  excepSon.getMessage();        }     }       4.0  M1  
  • 30.
    Spring  Simple  Messaging  API   (Handle  SUBSCRIBE  events  from  client)   @Controller     public  class  Por~olioController  {              //  ...              @SubscribeMapping("/app/posi9ons")        public  List<Por~olioPosiSon>  getPor~olios(Principal  principal)  {            String  user  =  principal.getName();            Por~olio  por~olio  =  this.por~olioService.findPor~olio(user);            return  por~olio.getPosiSons();        }     }       4.0  M1  
  • 31.
    Spring  Simple  Messaging  API   4.0  M1   (Sending  updates  to  client  periodically)   @Service     public  class  QuoteService  {              private  final  MessageSendingOpera9ons<String>  messagingTemplate;          @Scheduled(fixedDelay=1000)        public  void  sendQuotes()  {            for  (Quote  quote  :  this.quoteGenerator.generateQuotes())  {                String  desSnaSon  =  "/topic/price.stock."  +  quote.getTicker();                this.messagingTemplate.convertAndSend(des9na9on,  quote);            }        }     }    
  • 32.
    Spring  Simple  Messaging  API   (Configura/on)   @ConfiguraSon   @EnableWebSocketMessageBroker   @EnableScheduling   @ComponentScan(basePackages="org.springframework.samples")   public  class  WebSocketConfig  implements  WebSocketMessageBrokerConfigurer  {      @Override    public  void  registerStompEndpoints(StompEndpointRegistry  registry)  {      registry.addEndpoint("/porholio").withSockJS();    }      @Override    public  void  configureMessageBroker(MessageBrokerConfigurer  configurer)  {      configurer.enableSimpleBroker("/queue/",  "/topic/");      //configurer.enableStompBrokerRelay("/queue/",  "/topic/");      configurer.setApplica9onDes9na9onPrefixes("/app");    }   }   4.0  M1  
  • 33.
  • 34.
    Composable  stereotype  model   @Service   @Scope(“session”)   @Primary   @Transac9onal(rollbackFor=Run9meExcep9on.class)   @RetenSon(RetenSonPolicy.RUNTIME)   public  @interface  MyService  {    boolean  readOnly();   }     @MyService(readOnly=true)   public  class  MyTradeService  {    //…   }  
  • 35.
    JEE  annotaSon  support  conSnue   @ManagedBean   public  class  MyTradeService  implements  TradeService{        @Inject    public  MyTradeService(MatchingService  service){      //…    }      @javax.transac9on.Transac9onal      public  void  matchTrade(Trade  trade){      //…    }     }    
  • 36.
    @CondiSonal  annotaSon   @Condi9onal(MyCondi9on.class)   @Configura9on     public  class  ExampleConfiguraSon  {      //  @Bean  methods   }       public  class  MyCondi9on  implements  Condi9on  {      public  boolean  matches(...)  {      //  return  true  if  the  condiSon  holds  true    }   }   4.0  M2  
  • 37.
    Make  #result  available  for  SpEL  in   @CachePut  key  abribute   4.0  M2   @CachePut(value  =  "personEn9ty",  key  =  "#result.id")   public  Person  persistPerson(Person  p)  {      Person  result  =  personRepository.save(p);      return  result;   }     @EnSty   public  class  Person  {      @Id  @GeneratedValue      private  Long  id;      …   }  
  • 38.
    Introduce  AcSveProfilesResolver  in  the   TestContext  framework   @RunWith(SpringJUnitRunner.class)   @ContextConfiguraSon(TestContext.class)   @Ac9veProfiles   public  class  IntegraSonTest  {          //…          @Test          public  void  integraSonTest(){                  //...          }   }     @ConfiguraSon   public  class  TestContext{          @Bean          public  Ac9veProfilesResolver  acSveProfilesResolver(){                  return  new  Ac9veProfilesResolver(){                            String[]  resolve(Class<?>  testClass){                                      //…                                      return  new  String[]{"test"};                            }                  };          }          //...   }   4.0  M2  
  • 39.
    4.0  M3   Autowiring  ordered  collecSons  based   on  @Order  annotaSon   @Component   @Order(value=1)   public  class  BusinessServiceA  implements  BusinessService{}     @Component   @Order(value=2)   public  class  BusinessServiceB  implements  BusinessService{}     @Component   public  class  ServiceRegistry  {    @Autowired    public  List<BusinessService>  services;   }     assertThat(services.get(0).getClass(),  is(BusinessServiceA.class));   assertThat(services.get(1).getClass(),  is(BusinessServiceB.class));  
  • 40.
    @PropertySources  annotaSon   4.0  RC1   @ConfiguraSon   @PropertySources({      @PropertySource(value  =  "file:/etc/applicaSon/config.properSes",    ignoreResourceNotFound  =  true),      @PropertySource(value  =  "file:/usr/local/etc/applicaSon/config.properSes",    ignoreResourceNotFound  =  true),      @PropertySource(value  =  "file:conf/config.properSes",    ignoreResourceNotFound  =  true),      @PropertySource(value  =  "classpath:applicaSon.properSes")   })   public  class  AppConfiguraSon{    //…   }     Or  even  without  @PropertySources  using  Java8  repeatable  annota/ons!!!  
  • 41.
    Autowiring  of  generic  types   4.0  RC1  
  • 42.
    Groovy  config   def  bb  =  new  BeanBuilder()     bb.loadBeans("classpath:*SpringBeans.groovy")   def  applica9onContext  =  bb.createApplicaSonContext()       //  MySpringBeans.groovy     import  o.sf.jdbc.core.JdbcTemplate   import  o.sf.jdbc.datasource.DataSourceTransac9onManager     beans  {      jdbcTemplate(JdbcTemplate)  {        dataSource  =  dataSource      }      transac9onManager(DataSourceTransac9onManager){        dataSource  =  dataSource      }      dataSource(BasicDataSource)      driverClassName  ="org.h2.Driver"      url="jdbc:h2:mem:grailsDB"      username="sa"      password=""    }   }     4.0  RC1  
  • 43.
    @ControllerAdvice  annotaSon   @ControllerAdvice({"com.example.web.api"})   public  class  GlobalErrorHandler  {          //  common  @ExcepSonHandler  methods  are  defined  here   }     Will  be  applied  to  both  Controllers  below:   com.example.web.api.feature1.Feature1Controller     com.example.web.api.feature2.Featuer2Controller   4.0  RC1  
  • 44.
    Other  changes…   4.0  M1   •  Replace  EasyMock  with  Mockito   •  [SPR-­‐8258]  EhCache  2.5  support   4.0  M2   •  [SPR-­‐10664]  Make  #result  available  for  SpEL  in  @CachePut  key  abribute   •  [SPR-­‐10338]  Introduce  AcSveProfilesResolver  in  the  TestContext   framework   4.0  M3   •  [SPR-­‐5574]  Autowiring  should  support  ordered  collecSon  driven  by  Order   annotaSon  or  Ordered  interface   4.0  RC1   •  [SPR-­‐8371]  Add  @PropertySources  annotaSon  and  support   ignoreResourceNotFound  and  preserve  mulSple  @PropertySources  order   •  [SPR-­‐10222]  Allow  @ControllerAdvice  to  be  cofigured  with  a  join  point  to   target  a  subset  of  controller  
  • 45.
    How  to  track  progress?   •  Track  JIRA  -­‐   hbps://jira.springsource.org/browse/SPR/ fixforversion/14229   •  Check  commits  to  codebase  -­‐   hbps://github.com/SpringSource/spring-­‐ framework/commits/master  
  • 46.
    Thank  you!   Oleg  Tsal-­‐Tsalko   Email:  oleg.tsalko@gmail.com   Twiber:  @tsaltsol