Spring 3.1
-
Upload
chti-jug -
Category
Technology
-
view
4.535 -
download
5
Transcript of Spring 3.1
© Zenika 2011 Spring 3.1 1
Spring 3.1
© Zenika 2011 Spring 3.1 2
Speaker's qualificationsSpeaker's qualifications
• Arnaud Cogoluègnes• Consultant with Zenika• Has been using Spring since 2005• SpringSource certified trainer• Co-author:
• Spring par la pratique, 2nd edition• Spring Dynamic Modules in Action• Spring Batch in Action
© Zenika 2011 Spring 3.1 3
AgendaAgenda
• History• Environment• Java configuration• Spring JPA• Cache abstraction• Spring MVC improvements
© Zenika 2011 Spring 3.1 4
HistoryHistory
• v. 0.9 : june 2003 (foundations)• v. 1.0 : march 2004• v. 1.1 : september 2004• v. 1.2 : may 2005• v. 2.0 : october 2006 (XML namespaces)• v. 2.5 : november 2007 (annotations)• v. 3.0 : décember 2009 (Java config, SpEL, REST)
© Zenika 2011 Spring 3.1 5
Environment
EnvironmentEnvironment
• Inside the application context
Property SourceProperty Source
ProfileProfile
© Zenika 2011 Spring 3.1 6
db.driver=org.h2.driverdb.url=jdbc:h2:mem:db1db.user=sadb.password=
Environment / Property SourceEnvironment / Property Source
• Do you know this?
<context:property-placeholder location="database.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${db.driver}" /> <property name="url" value="jdbc:${db.url}" /> <property name="username" value="${db.user}" /> <property name="password" value="${db.password}" /></bean>
database.properties
© Zenika 2011 Spring 3.1 7
db.driver=org.h2.driverdb.url=jdbc:h2:mem:db1db.user=sadb.password=
Environment / Property SourceEnvironment / Property Source
• Spring 3.1 introduces an abstraction for property sources• But what is a PropertySource anyway?
Property Source =
© Zenika 2011 Spring 3.1 8
Environment / PropertySourceEnvironment / PropertySource
• Where do PropertySources come from?
ResourcePropertySource
Properties files
System and environmentvariablesProperties
PropertySource
JndiPropertySource
JNDI ServletContext/ConfigPropertySource
Servlet context and config
© Zenika 2011 Spring 3.1 9
Environment / Property SourceEnvironment / Property Source
• How to refer to PropertySource?
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClass" value="${db.driver}"/> <property name="jdbcUrl" value="${db.url}"/> <property name="username" value="${db.user}"/> <property name="password" value="${db.password}"/></bean>
© Zenika 2011 Spring 3.1 10
Environment / Property SourceEnvironment / Property Source
• How to refer to PropertySource?
@Configurationpublic class DatabaseConfiguration {
@Value("${db.driver}") private String driver; @Value("${db.url}") private String url; @Value("${db.user}") private String user; @Value("${db.password}") private String password;
@Bean public DataSource dataSource() { // creates DataSource return dataSource; }
}
© Zenika 2011 Spring 3.1 11
Environment / PropertySourceEnvironment / PropertySource
• How to define a PropertySource ?
<context:property-placeholder location="classpath:application.properties" />
© Zenika 2011 Spring 3.1 12
Environment / PropertySourceEnvironment / PropertySource
• How to define a PropertySource ?
<context:property-placeholder properties-ref="applicationProperties" />
<util:properties id="applicationProperties"> <prop key="db.driver">org.h2.Driver</prop> <prop key="db.url">jdbc:h2:mem:db1</prop> <prop key="db.user">sa</prop> <prop key="db.password"></prop></util:properties>
© Zenika 2011 Spring 3.1 13
Environment / PropertySourceEnvironment / PropertySource
• How to define a PropertySource ?
<context-param> <param-name>contextInitializerClasses</param-name> <param-value>com.zenika.SomeInitializer</param-value></context-param>
public class SomeInitializer implements ApplicationContextInitializer <ConfigurableApplicationContext> {
public void initialize( ConfigurableApplicationContext ctx) { PropertySource ps = ... ctx.getEnvironment().getPropertySources().addFirst(ps); }
}
© Zenika 2011 Spring 3.1 14
Environment / PropertySourceEnvironment / PropertySource
• Unified way to deal with properties• More flexible than simple property placeholder
• Configurable programmatically, useful for test configs
• Part of the new Environment abstraction
© Zenika 2011 Spring 3.1 15
Environment / ProfileEnvironment / Profile
Environment
Property SourceProperty Source
ProfileProfile
© Zenika 2011 Spring 3.1 16
Environment / ProfileEnvironment / Profile
"dev" profile
Service
Datasource
Repository
"prod" profile
Datasource
Application Context
© Zenika 2011 Spring 3.1 17
Environment / ProfileEnvironment / Profile
• Different beans for different environments
<bean class="com.zenika.ContactDao"> <constructor-arg ref="dataSource" /></bean>
<beans profile="test"> <jdbc:embedded-database id="dataSource" type="H2" /></beans>
<beans profile="prod"> <jee:jndi-lookup id="ds" jndi-name="java:comp/env/jdbc/ds" /></beans>
© Zenika 2011 Spring 3.1 18
Environment / ProfileEnvironment / Profile
• Let's reach the clouds!
<bean class="com.zenika.ContactDao"> <constructor-arg ref="dataSource" /></bean>
<beans profile="dev"> <jdbc:embedded-database id="dataSource" type="H2" /></beans>
<beans profile="cloud"> <cloud:data-source id="dataSource" service-name="contactDs"/></beans>
© Zenika 2011 Spring 3.1 19
Environment / ProfileEnvironment / Profile
• Creating the application context for the test profile
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();ctx.getEnvironment().setActiveProfiles("test");ctx.load("classpath:/application-context.xml");ctx.refresh();
© Zenika 2011 Spring 3.1 20
Environment / ProfileEnvironment / Profile
• Activating a profile declaratively
-Dspring.profiles.active="prod"
© Zenika 2011 Spring 3.1 21
Environment / ProfileEnvironment / Profile
• Bootstrapping with the TestContext framework
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:/application-context.xml")@ActiveProfiles("test")public class ProfileTest {
@Autowired private ContactDao contactDao;
@Test public void getContact() throws Exception { ... }
}
© Zenika 2011 Spring 3.1 22
Environment / ProfileEnvironment / Profile
• Just « prod » profile
<bean class="com.zenika.spring31.ContactDao"> <constructor-arg ref="dataSource" /></bean>
<beans profile="prod"> <jee:jndi-lookup id="ds" jndi-name="java:comp/env/jdbc/ds" /></beans>
© Zenika 2011 Spring 3.1 23
Environment / ProfileEnvironment / Profile
• Override what you need in the test
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration( loader=AnnotationConfigContextLoader.class)public class SpecialProfileTest {
@Autowired private ContactDao contactDao;
@Test public void getContact() throws Exception { ... }
@Configuration @ImportResource("classpath:/application-context.xml") static class ContextConfiguration { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder().build(); } }}
© Zenika 2011 Spring 3.1 24
Java configurationJava configuration
• Nothing equivalent to XML namespaces so far...
@Transactional@Repositorypublic class HibernateContactRepo { ... }
<context:component-scan base-package="com.zenika" />
<tx:annotation-driven />
© Zenika 2011 Spring 3.1 25
Java configurationJava configuration
• Annotations equivalent to common XML shortcuts
@Transactional@Repositorypublic class HibernateContactRepo { ... }
@Configuration@EnableTransactionManagement@ComponentScan(basePackageClasses=HibernateContactRepo.class)public class ContextConfiguration { ... }
© Zenika 2011 Spring 3.1 26
Java configurationJava configuration
• Annotations equivalent to common XML shortcuts@Configuration@EnableTransactionManagement@ComponentScan(basePackageClasses=HibernateContactRepo.class)public class ContextConfiguration {
@Bean public SessionFactory sf() throws Exception { return new AnnotationSessionFactoryBuilder() .setDataSource(dataSource()) .setPackagesToScan(Contact.class.getPackage().getName()) .buildSessionFactory(); }
@Bean public PlatformTransactionManager tm() throws Exception { return new HibernateTransactionManager(sf()); }
@Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2).build(); }
}
© Zenika 2011 Spring 3.1 27
Spring JPASpring JPA
• More support for persistence in Spring JPA
public interface ContactRepository extends JpaRepository<Contact, Long> { }
<jpa:repositories base-package="com.zenika.jpa" />
long initialCount = contactRepo.count();Contact contact = new Contact();contact.setFirstname("Arnaud");contact.setLastname("Cogoluègnes");contactRepo.save(contact);Assert.assertEquals(initialCount+1, contactRepo.count());
© Zenika 2011 Spring 3.1 28
Spring JPASpring JPA
• Define your own method, following conventions
public interface ContactRepository extends JpaRepository<Contact, Long> {
List<Contact> findByFirstname(String firstname);
}
List<Contact> contacts = contactRepo.findByFirstname("Arnaud");
© Zenika 2011 Spring 3.1 29
Spring JPASpring JPA
• Define JPQL queries for methods
public interface ContactRepository extends JpaRepository<Contact, Long> {
@Query("from Contact c where lower(c.firstname) = lower(?1)") List<Contact> find(String search);
}
List<Contact> contacts = contactRepo.find("arnaud");
© Zenika 2011 Spring 3.1 30
Spring JPASpring JPA
• Built-in support for pagination
Pageable request = new PageRequest(1,2,new Sort("lastname")); Page<Contact> page = contactRepo.findAll(request);
List<Contact> contacts = page.getContent();long total = page.getTotalElements();long number = page.getNumberOfElements();
© Zenika 2011 Spring 3.1 31
Quick note on Spring DataQuick note on Spring Data
• Spring JPA is part of the Spring Data project• Spring Data is an umbrella project• Spring Data provides Spring support for « new » data
access technologies• MongoDB, Neo4j, Riak, Redis, Hadoop
• Support planned for additional NoSQL technologies• HBase, Cassandra, CouchDB
• Don't hesitate to check out Spring Data!• http://www.springsource.org/spring-data
© Zenika 2011 Spring 3.1 32
Cache support in Spring 3.1Cache support in Spring 3.1
• What about some transparent cache on method calls?
Contact contact = contactRepo.findOne(contact.getId());contact = contactRepo.findOne(contact.getId());
Hibernate: select contact0_.id as id0_0_, ... Hibernate: select contact0_.id as id0_0_, ...
public interface ContactRepository extends JpaRepository<Contact, Long> { Contact findOne(Long id);
}
© Zenika 2011 Spring 3.1 33
Cache support in Spring 3.1Cache support in Spring 3.1
• Let's combine Spring JPA and Spring 3.1's cache support !• NB: the cache support works on any kinds of beans
public interface ContactRepository extends JpaRepository<Contact, Long> {
@Cacheable("contacts") Contact findOne(Long id);
}
Contact contact = contactRepo.findOne(contact.getId());contact = contactRepo.findOne(contact.getId());
Hibernate: select contact0_.id as id0_0_, ...
© Zenika 2011 Spring 3.1 34
Cache support in Spring 3.1Cache support in Spring 3.1
• This is how to configure the cache
<cache:annotation-driven />
<bean id="cacheManager" class="o.s.cache.support.SimpleCacheManager"> <property name="caches"> <set> <bean class="o.s.cache.concurrent.ConcurrentMapCache" c:name="contacts" /> </set> </property></bean>
© Zenika 2011 Spring 3.1 35
Cache support in Spring 3.1Cache support in Spring 3.1
• The cache support is an abstraction• The Spring Framework provides implementations
• SimpleCacheManager• Uses collections of caches• Useful for testing or small, non-distributed environments
• EhCacheCacheManager• Backed up by Ehcache
• The Spring Gemfire project ships with an implementation
© Zenika 2011 Spring 3.1 36
Cache support in Spring 3.1Cache support in Spring 3.1
• Can use expression for keys
public interface ContactRepository extends JpaRepository<Contact, Long> {
@Cacheable(value="contacts",key="#p0+'.'+#p1") Contact findByLastnameAndFirstname(String lastname, String firstname);
}
Contact contact = contactRepo.findByLastnameAndFirstname( "Cogoluègnes", "Arnaud");contact = contactRepo.findByLastnameAndFirstname( "Cogoluègnes", "Arnaud");
Hibernate: select contact0_.id as id0_, ...
© Zenika 2011 Spring 3.1 37
Cache support in Spring 3.1Cache support in Spring 3.1
• Method can do some housekeeping with @CacheEvict
@Transactionalpublic interface ContactRepository extends JpaRepository<Contact, Long> {
@Cacheable("contacts") Contact findOne(Long id);
@CacheEvict(value="contacts",key="#p0.id") Contact save(Contact contact);
}
© Zenika 2011 Spring 3.1 38
Cache support in Spring 3.1Cache support in Spring 3.1
• Spring's cache support can be used • on the data access layer
• replaces 2nd level cache or provides cache for a JDBC-based layer
• at the web tier level• caches business services calls or web services calls
© Zenika 2011 Spring 3.1 39
Spring MVC enhancementsSpring MVC enhancements
• Easier registration of HttpMessageConverters
• But what is a HttpMessageConverter anyway?
• HttpMessageConverters are used in Spring's REST support• Java object to HTTP response conversion
• From Java to XML, JSON, etc.
• HTTP request to Java object conversion• From XML, JSON to Java
• On the server but on the client side as well...
© Zenika 2011 Spring 3.1 40
Spring MVC enhancementsSpring MVC enhancements
• Easier registration with a dedicated XML tag• Used to be directly at the HandlerAdapter level
<mvc:annotation-driven> <mvc:message-converters register-defaults="false"> <bean class="com.zenika.web.ContactHttpMessageConverter" /> </mvc:message-converters></mvc:annotation-driven>
© Zenika 2011 Spring 3.1 41
Spring MVC enhancementsSpring MVC enhancements
• Java-based configuration• Same as <mvc:annotation-driven />
@Configuration@EnableWebMvcpublic class WebConfig extends WebMvcConfigurerAdapter {
@Override public void configureMessageConverters( List<HttpMessageConverter<?>> converters) { converters.add(new ContactHttpMessageConverter()); }
}
© Zenika 2011 Spring 3.1 42
Spring MVC enhancementsSpring MVC enhancements
• Big refactoring on the way to process annotations
@Controllerpublic class ContactController {
@Autowired private ContactRepository repo;
@RequestMapping(value="/contacts/{id}", method=RequestMethod.GET ) @ResponseBody public Contact get(@PathVariable Long id) { return repo.findOne(id); }
}
© Zenika 2011 Spring 3.1 43
Spring MVC enhancementsSpring MVC enhancements
• Who used to process annotations like @RequestMapping, @RequestParam, etc?
• Answer: the AnnotationMethodHandlerAdapter.• Processing was hard-coded in the class• Spring 3.1 introduced the HandlerMethod abstraction
• RequestMappingHandlerMapping• RequestMappingHandlerAdapter
© Zenika 2011 Spring 3.1 44
Spring MVC enhancementsSpring MVC enhancements
• Consequences of the HandlerMethod abstraction• Backward compatible (@RequestMapping, @RequestParam
& co).• More fine-grained control over controller method execution• Possible interception around the invocation of the controller• Pluggable mechanism on method argument
• You can create your own @RequestParam-like annotations!• Check the HandlerMethodArgumentResolver and HandlerMethodReturnValueHandler interfaces
© Zenika 2011 Spring 3.1 45
Support for Servlet 3.0Support for Servlet 3.0
• Servlet 3.0 allows for programmatic registration• ServletContext.addServlet(String, Servlet)• ServletContext.addFilter(String, Filter)
• Hook for frameworks• ServletContainerInitializer• Implementations listed in META-INF/services
• In Spring: SpringServletContainerInitializer
© Zenika 2011 Spring 3.1 46
Support for Servlet 3.0Support for Servlet 3.0
• SpringServletContainerInitializer triggers WebApplicationInitializers
• WebApplicationInitializer• The API to use• Detected and called by Spring (through the web container)• Used for initialization
• Registering a DispatcherServlet• Bootstrapping the Spring ApplicationContext
© Zenika 2011 Spring 3.1 47
Support for Servlet 3.0Support for Servlet 3.0
• No need of web.xml anymorepublic class ZenContactInitializer implements WebApplicationInitializer {
@Override public void onStartup(ServletContext sc) throws ServletException { AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(WebConfig.class); sc.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); dispatcherContext.register(DispatcherConfig.class);
ServletRegistration.Dynamic dispatcher = sc.addServlet( "dispatcher", new DispatcherServlet(dispatcherContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/main"); }}
© Zenika 2011 Spring 3.1 48
ResourcesResources
• Summary• http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/
• http://blog.springsource.com/2011/06/09/spring-framework-3-1-m2-released/
• Environment• http://blog.springsource.com/2011/02/14/spring-3-1-m1-introducing-profile/
• http://blog.springsource.com/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles/
• http://blog.springsource.com/2011/02/15/spring-3-1-m1-unified-property-management/
• Cache abstraction• http://blog.springsource.com/2011/02/23/spring-3-1-m1-caching/
• Spring JPA• http://blog.springsource.com/2011/02/10/getting-started-with-spring-data-jpa/
• http://blog.springsource.com/2011/07/27/fine-tuning-spring-data-repositories/
• Spring MVC• http://blog.springsource.com/2011/02/21/spring-3-1-m1-mvc-namespace-
enhancements-and-configuration/
• http://blog.springsource.com/2011/06/13/spring-3-1-m2-spring-mvc-enhancements-2/
© Zenika 2011 Spring 3.1 49
Questions ?