Download - Spring4 whats up doc?
Subtitle TextAuthorContact info
David Gómez@dgomezg
Spring 4 core improvements
Spring 4 core improvements
Generics in Qualifiers
Exposing attributes in Meta-annotations
Autowiring Lists and Arrays
@Description on @Configuration classes
@Conditional (user-defined @Profiles)
Time Zone support on Locale Context
Generics in Qualifierspublic interface MessageService {! public String getMessage();!}
public class GeneralWaver implements MessageService{ @Override public String getMessage() { return "Hello world!"; }!}
public class PersonWaver implements MessageService {! @Autowired public PersonRepository personRepository;! @Override public String getMessage() { ... }}
En Spring 3.2….
public class MultiMessagePrinter {! //All Message Services are injected @Autowired private List<MessageService> messageServices;! public void printMessage() { for (MessageService messageService: messageServices) { System.out.println(messageService.getMessage()); } }!}
Generics in Qualifiers
<?xml version="1.0" encoding="UTF-8"?><beans ...>! <context:annotation-config/>! <!-- Database config --> <jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:sql/schema.ddl"/> <jdbc:script location="classpath:sql/data.sql"/> </jdbc:embedded-database> <bean id=“personRepository" class="com.autentia.playground.spring4.helloWorld.db.JdbcPersonRepository"/>! <!-- Wavers (MessageService implementations) --> <bean id="personWaver" class="com.autentia.playground.spring4.helloWorld.messages.PersonWaver"/> <bean id="generalWaver" class="com.autentia.playground.spring4.helloWorld.messages.GeneralWaver"/>! <!-- Printer : waves to everybody using available MessageServices --> <bean id="messagePrinter" class="com.autentia.playground.spring4.helloWorld.messages.MultiMessagePrinter"/>!</beans>
En Spring 3.2….
Generics in Qualifierspublic interface MessageService<T> {! public T getMessage();!}
public class GeneralWaver implements MessageService<String>{ @Override public String getMessage() { return "Hello world!"; }!}
public class PersonWaver implements MessageService<Person> {! @Autowired public PersonRepository personRepository;! @Override public Person getMessage() { ... }}
En Spring 4 also….
public class MultiMessagePrinter {! @Autowired private MessageService<Person> messageServices;! public void printMessage() { System.out.println(messageService.getMessage().toString()); }!}
public interface MessageService {! public String getMessage();!}
Autowiring ordered Lists and ArraysIn Spring 3.2….
public class GeneralWaver implements MessageService{ @Override public String getMessage() { return "Hello world!"; }!}
public class PersonWaver implements MessageService {! @Autowired public PersonRepository personRepository;! @Override public String getMessage() { ... }}
public class MultiMessagePrinter {! //All Message Services are injected @Autowired private List<MessageService> messageServices;! public void printMessage() { for (MessageService messageService: messageServices) { System.out.println(messageService.getMessage()); } }!}
Hello Sr. David Gomez G.Hello world!
public interface MessageService {! public String getMessage();!}
Autowiring ordered Lists and ArraysIn Spring 4….
public class GeneralWaver implements MessageService, Ordered {! @Override public String getMessage() { return "Hello world!"; }! @Override public int getOrder() { return Integer.MIN_VALUE; }!}
public class PersonWaver implements MessageService {! @Autowired public PersonRepository personRepository;! @Override public int getOrder() { return 0; }}
public class MultiMessagePrinter {! //All Message Services are injected @Autowired private List<MessageService> messageServices;! public void printMessage() { for (MessageService messageService: messageServices) { System.out.println(messageService.getMessage()); } }!}
Hello world!Hello Sr. David Gomez G.
Exposing attributes in Meta-annotationsIn Spring 3.2….
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic @interface Service { String[] value();}
@MyTransactionalServicepublic class PersonWaver implements MessageService {! @Autowired public PersonRepository personRepository;! @Override public String getMessage() { ... }}
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Service@Transactional(timeout=60)public @interface MyTransactionalService { String[] value();}
Exposing attributes in Meta-annotationsIn Spring 4….
@MyTransactionalService(propagation=Propagation.REQUIRES_NEW)public class PersonWaver implements MessageService {! @Autowired public PersonRepository personRepository;! @Override public String getMessage() { ... }}
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Service@Transactionalpublic @interface MyTransactionalService { String[] value(); Propagation propagation() default Propagation.REQUIRED; int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;!}
@Description on @Configuration classesIn Spring 4….
@Configuration@ComponentScanpublic class Application {! @Bean @Description("This is a mock implementation of MockService") MessageService mockMessageService() { return new MessageService() { @Override public String getMessage() { return "Hello world!"; } }; }}
Useful when beans are exposed, !for example, as JMX beans
@Configuration@ComponentScan@Profile(“test”)public class Application {! @Bean @Description("This is a mock implementation of MockService") MessageService mockMessageService() { return new MessageService() { @Override public String getMessage() { return "Hello world!"; } }; }}
@Profiles and @ConditionalIn Spring 3.2….
<beans profile="dev"> <jdbc:embedded-database id="dataSource"> <jdbc:script location="classpath:sql/schema.ddl"/> <jdbc:script location="classpath:sql/data.sql"/> </jdbc:embedded-database> </beans>! <beans profile="prod"> <jee:jndi-lookup id="dataSource" jndi-name="jdbc/LiveDataSource"/> </beans>
-Dspring.profiles.active=“dev"
@Configuration@ComponentScanpublic class Application {! @Bean @Description("This is a mock implementation of MockService”) @Conditional(NoMessageServiceDefined.class) MessageService mockMessageService() { return new MessageService() { @Override public String getMessage() { return "Hello world!"; } }; }}
@Profiles and @ConditionalIn Spring 4….
!public class NoMessageServiceDefined implements Condition {! @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return context.getBeanFactory().getBeansOfType(MessageService.class) .isEmpty(); }}
Web Container improvements
Spring 4 web improvementsSupport for Servlet 3.0
(Servlet 2.5 still supported for GAE compatibility)
(servlet 3.0 jar needed for SPRING MVC Tests)
@RestController (@RequestMapping + @ResponseBody)
@AsyncRestTemplate (Non-blocking REST clients)
!
@Controllerpublic class WaverController {! @RequestMapping("/person") public @ResponseBody Person showPersonalMessage() { return personWaver.getMessage(); }! @RequestMapping("/message") public @ResponseBody String showMessage() { return genericWaver.getMessage(); }!}
@RestControllerIn Spring 3.2….
@RestControllerpublic class WaverController {! @RequestMapping("/person") public Person showPersonalMessage() { return personWaver.getMessage(); }! @RequestMapping("/message") public String showMessage() { return genericWaver.getMessage(); }!}
@RestControllerIn Spring 4…
@RestController = @Controller + @ResponseBody
public class RestTemplate { public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) {} public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... urlVariables) {} public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables) {} public void put(String url, Object request, Object... urlVariables) {}}
@AsyncRestTemplate (Non-blocking REST clients)
RestTemplate
public class RestTemplate { public <T> T getForObject(String url, Class<T> responseType, Object... urlVariables) {} public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... urlVariables) {} public <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables) {} public void put(String url, Object request, Object... urlVariables) {}}
@AsyncRestTemplate (Non-blocking REST clients)
AsyncRestTemplatepublic class AsyncRestTemplate {! public <T> ListenableFuture<ResponseEntity<T>> getForEntity(String url, Class<T> responseType, Object... uriVariables) {}! public ListenableFuture<URI> postForLocation(String url, HttpEntity<?> request, Object... uriVariables) {}! public ListenableFuture<?> put(String url, HttpEntity<?> request, Object... uriVariables) {}}
public interface ListenableFuture<T> extends Future<T> {! void addCallback(ListenableFutureCallback<? super T> callback);!}
@AsyncRestTemplate (Non-blocking REST clients)
AsyncRestTemplate
ListenableFuture<ResponseEntity<Person>> futureEntity = template.getForEntity( "http://localhost:8080/spring4/person/{personId}", Integer.class, 1);!// register a callbackfutureEntity.addCallback(new ListenableFutureCallback<ResponseEntity<Person>>() { @Override public void onSuccess(ResponseEntity<Person> entity) { //... }! @Override public void onFailure(Throwable t) { //... }});
Spring 4 meets Java 8
Support for lambdas on callbacksIn Spring 3.2
public Person findById(int id) { return jdbcTemplate.query("select * from persons where id = ?", new RowMapper<Person>() { @Override public Person mapRow(ResultSet rs, int rowNum) throws SQLException { return new Person(rs.getInt("id"), rs.getString("treatment"), rs.getString("name"), rs.getString("surname"), new Date(rs.getDate("birthDate").getTime())); } }, id) .get(0); }
Support for lambdas on callbacksIn Spring 4
public Person findById(int id) { return jdbcTemplate.queryForObject( "select * from persons where id = ?", (rs, rowNum) -> new Person(rs.getInt("id"), rs.getString("treatment"), rs.getString("name"), rs.getString("surname"), new Date(rs.getDate("birthDate").getTime())), id);}
Support for lambdas on callbacksIn Spring 4
@Override@Transactionalpublic Person getMessage() { final Person person;! txTemplate.execute((txStatus) -> { person = messageRepository.findById(1); txStatus.setRollbackOnly(); return null; });! return person;}
JSR-310package java.time
Distinction between Computer-times and Human-Times
Human-Times
TimeZone (ISO-8601)
LocalDateTime
LocalDate
LocalTime
JSR-310package java.time
Amounts of Time
Duration (nanosecond resolution)
Amounts of Days
Period (years, months, and days)
TimeZones
ZonedDateTime
OffsetDateTime
JSR-310 in Spring 4
In web handler Methodsimport java.time.Clock;import java.time.ZoneId;!@RestControllerpublic class WaverController {! @RequestMapping("/person") public Person showPersonalMessage(ZoneId zoneId) { Clock clock = Clock.of(zoneId) LocalTime time = LocalTime.now(clock); return personWaver.getMessageFor(time); }!}
External Libraries
External Libraries SupportHibernate 3.6+
Hibernate 4.3 (JPA 2.1)
EhCache 2.1
Quartz 1.8
JodaTime 2.0
Hibernate Validator 4.3 (Bean Validation 1.1)
Jackson 2.0 (1.8/1.9 deprecated)
Other changes
Support for JEE7 (& JEE6)Serlvet 3.0
JMS 2.0
JTA 1.2
JPA 2.1
Bean Validation 1.1
JSR-236 Concurrency (ThreadExecutors)
WebSockets with
Spring 4
WebSocket SupportWebSocket server support via JSR-356 runtimes
(Tomcat 7.0.7 -Jetty 9)
Fallback option using SockJS
(SockJsHttpRequestHandler)
Dedicated talk on
“WebSockets with Spring 4”
coming soon
Subtitle TextAuthorContact info
David Gómez@dgomezg
(de momento)