3. 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
4. Generics in Qualifiers
En Spring 3.2….
public 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() {
...
}
}
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());
}
}
5. Generics in Qualifiers
En Spring 3.2….
<?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>
6. Generics in Qualifiers
En Spring 4 also….
public 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() {
...
}
}
public class MultiMessagePrinter {
!
!
!
}
@Autowired
private MessageService<Person> messageServices;
public void printMessage() {
System.out.println(messageService.getMessage().toString());
}
7. Autowiring ordered Lists and Arrays
In Spring 3.2….
public 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() {
...
}
}
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!
8. Autowiring ordered Lists and Arrays
In Spring 4….
public interface MessageService {
!
!
public String getMessage();
public class GeneralWaver }
implements MessageService, Ordered {
!
!
!
}
@Override
public String getMessage() {
return "Hello world!";
}
@Override
public int getOrder() {
return Integer.MIN_VALUE;
}
public class MultiMessagePrinter {
!
!
!
}
public class PersonWaver
implements MessageService {
!
!
@Autowired
public PersonRepository personRepository;
@Override
public int getOrder() {
return 0;
}
}
//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.
9. Exposing attributes in Meta-annotations
In Spring 3.2….
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
String[] value();
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Service
@Transactional(timeout=60)
public @interface MyTransactionalService {
String[] value();
}
@MyTransactionalService
public class PersonWaver
implements MessageService {
!
!
}
@Autowired
public PersonRepository personRepository;
@Override
public String getMessage() {
...
}
10. Exposing attributes in Meta-annotations
In Spring 4….
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Service
@Transactional
public @interface MyTransactionalService {
String[] value();
Propagation propagation() default Propagation.REQUIRED;
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
!
}
@MyTransactionalService(propagation=Propagation.REQUIRES_NEW)
public class PersonWaver
implements MessageService {
!
!
}
@Autowired
public PersonRepository personRepository;
@Override
public String getMessage() {
...
}
11. @Description on @Configuration classes
In Spring 4….
@Configuration
@ComponentScan
public 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
12. @Profiles and @Conditional
In 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
@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!";
}
};
}
13. @Profiles and @Conditional
In Spring 4….
@Configuration
@ComponentScan
public 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!";
}
};
}
}
!
public class NoMessageServiceDefined implements Condition {
!
}
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getBeanFactory().getBeansOfType(MessageService.class)
.isEmpty();
}
15. Spring 4 web improvements
Support 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)
!
16. @RestController
In Spring 3.2….
@Controller
public class WaverController {
!
!
!
}
@RequestMapping("/person")
public @ResponseBody Person showPersonalMessage() {
return personWaver.getMessage();
}
@RequestMapping("/message")
public @ResponseBody String showMessage() {
return genericWaver.getMessage();
}
17. @RestController
In Spring 4…
@RestController = @Controller + @ResponseBody
@RestController
public class WaverController {
!
!
!
}
@RequestMapping("/person")
public Person showPersonalMessage() {
return personWaver.getMessage();
}
@RequestMapping("/message")
public String showMessage() {
return genericWaver.getMessage();
}
18. @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) {}
}
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) {}
}
19. @AsyncRestTemplate (Non-blocking REST clients)
AsyncRestTemplate
public 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);
22. Support for lambdas on callbacks
In 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);
}
23. Support for lambdas on callbacks
In 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);
}
24. Support for lambdas on callbacks
In Spring 4
@Override
@Transactional
public Person getMessage() {
final Person person;
!
!
}
txTemplate.execute((txStatus) -> {
person = messageRepository.findById(1);
txStatus.setRollbackOnly();
return null;
});
return person;
26. JSR-310
package java.time
Amounts of Time
Duration (nanosecond resolution)
Amounts of Days
Period (years, months, and days)
TimeZones
ZonedDateTime
OffsetDateTime
27. JSR-310 in Spring 4
In web handler Methods
import java.time.Clock;
import java.time.ZoneId;
!
@RestController
public class WaverController {
!
!
}
@RequestMapping("/person")
public Person showPersonalMessage(ZoneId zoneId) {
Clock clock = Clock.of(zoneId)
LocalTime time = LocalTime.now(clock);
return personWaver.getMessageFor(time);
}
33. WebSocket Support
WebSocket server support via JSR-356 runtimes
(Tomcat 7.0.7 -Jetty 9)
Fallback option using SockJS
(SockJsHttpRequestHandler)
k on
tal
g 4”
ed
prin
icat
ed
ith S
D
ts w
ocke
ebS
“W
soon
ming
co