Download - Get ready for spring 4
![Page 1: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/1.jpg)
Speaker: Oleg Tsal-‐Tsalko (@tsaltsol)
Get ready for Spring 4
![Page 2: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/2.jpg)
![Page 3: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/3.jpg)
Modern Spring ecosystem
![Page 4: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/4.jpg)
Spring Boot
![Page 5: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/5.jpg)
Spring Boot Groovy app
@Controller class ThisWillActuallyRun { @RequestMapping("/") @ResponseBody String home() { return "Hello World!" } }
![Page 6: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/6.jpg)
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); } }
![Page 7: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/7.jpg)
Spring XD architecture
Taps Compute
HDFS
Workflow
Export
Spring XD RunSme
Ingest
Jobs
Export
Files Sensors Mobile Social
RDBMS
NoSQL
R, SAS
Spring XD Shell
Streams
Redis
Gemfire
PredicSve modeling
![Page 8: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/8.jpg)
Spring XD RunSme
hbp | filter | file
Rabbit, Redis, (Pluggable)
XD Admin
CLUSTERED NODE
Filter Module
CLUSTERED NODE
HTTP Module
CLUSTERED NODE
File Module
In Memory Transport
hbp | filter | file
SINGLE NODE
All Modules
![Page 9: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/9.jpg)
Spring 4.0
Almost there… RC1 now!!!
![Page 10: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/10.jpg)
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…
![Page 11: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/11.jpg)
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)
4.0 M1
![Page 12: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/12.jpg)
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
![Page 13: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/13.jpg)
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
![Page 14: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/14.jpg)
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
![Page 15: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/15.jpg)
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)
4.0 M1
![Page 16: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/16.jpg)
Bean ValidaSon 1.1 support
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.
4.0 M1
![Page 17: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/17.jpg)
JMS 2.0 support 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.
4.0 M1
![Page 18: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/18.jpg)
JEE7 concurrency uSliSes in Spring 4 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
![Page 19: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/19.jpg)
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
4.0 M1
![Page 20: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/20.jpg)
WebSocket JSR-‐356 support (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) { // ... } }
4.0 M1
![Page 21: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/21.jpg)
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
![Page 22: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/22.jpg)
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
![Page 23: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/23.jpg)
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() { // ... } }
WebSocket JSR-‐356 client side support 4.0 M1
![Page 24: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/24.jpg)
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.
![Page 25: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/25.jpg)
Spring WebSocket API I
Programming model for building message-‐oriented applicaSons using STOMP over
WebSocket protocol for example
Inspira/on
• 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
![Page 26: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/26.jpg)
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}
![Page 27: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/27.jpg)
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);
![Page 28: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/28.jpg)
Spring Simple Messaging API (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); } }
4.0 M1
![Page 29: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/29.jpg)
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
![Page 30: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/30.jpg)
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
![Page 31: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/31.jpg)
Spring Simple Messaging API (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); } } }
4.0 M1
![Page 32: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/32.jpg)
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
![Page 33: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/33.jpg)
spring-‐websocket-‐por~olio DEMO app architecture
![Page 34: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/34.jpg)
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 {
//… }
![Page 35: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/35.jpg)
JEE annotaSon support conSnue @ManagedBean public class MyTradeService implements TradeService{
@Inject public MyTradeService(MatchingService service){ //… }
@javax.transac9on.Transac9onal public void matchTrade(Trade trade){ //… }
}
![Page 36: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/36.jpg)
@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
![Page 37: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/37.jpg)
Make #result available for SpEL in @CachePut key abribute
@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; … }
4.0 M2
![Page 38: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/38.jpg)
Introduce AcSveProfilesResolver in the TestContext framework
4.0 M2
@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"}; } }; } //... }
![Page 39: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/39.jpg)
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));
4.0 M3
![Page 40: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/40.jpg)
@PropertySources annotaSon @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!!!
4.0 RC1
![Page 41: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/41.jpg)
Autowiring of generic types 4.0 RC1
![Page 42: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/42.jpg)
Groovy config 4.0 RC1
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="" }
}
![Page 43: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/43.jpg)
@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
![Page 44: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/44.jpg)
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
![Page 45: Get ready for spring 4](https://reader034.vdocuments.us/reader034/viewer/2022042602/55d4c4dfbb61eb4f7c8b45a3/html5/thumbnails/45.jpg)
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