What’s New in Spring 3.1


New in Spring 3.0


Java 5+
Spring Expression Language
New Spring MVC Features
REST
Ajax
Declarative Validation
Backwards compatible with Spring 2.5
Spring Expression Language

Unified EL++
Deferred evaluation of expressions
Support for expressions that can set values and invoke methods
Pluggable API for resolving Expressions
Unified Expression Language: http://is.gd/2xqF
Spring 3.0 allows usage in XML files and @Value annotations
REST Support



REST with @PathParam


http://myserver/myapp/show/123




@RequestMapping(method = RequestMethod.GET)
public User show(@PathParam Long id) {
return userManager.getUser(id);
}


REST with RestController
@Controller
public class ResumesController implements RestController<Resume, Long> {
GET http://myserver/myapp/resumes
public List<Resume> index() {}
POST http://myserver/myapp/resumes
public void create(Resume resume) {}
GET http://myserver/myapp/resumes/1
public Resume show(Long id) {}
DELETE http://myserver/myapp/resumes/1
public void delete(Long id) {}
PUT http://myserver/myapp/resumes/1
public void update(Resume resume) {}
}




Dropping Support For...

Commons Attributes
TopLink (EclipseLink instead)
MVC Controller hierarchy
Unit 3.8 Test classes


What’s New in Spring 3.1

Java 7 Support
Hibernate 4 Support
Servlet 3.0 Support
Cache Abstraction
Java Configuration
Environments and Profiles
Test Context Support for Configuration Classes and Profiles


Java 7 Support

Fork/join support
JDBC 4.1
Try-with-resources
RowSet 1.1
Multicatch and final rethrow
String in switch statement support
What’s New in Hibernate 4?

Move to Gradle for builds
SessionFactory building
Initial osgi-fication
Java 6 / JDBC 4 as baseline
Multi-tentant database support
Migration to i18n logging framework
Hibernate 3
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
</value>
<!-- Turn batching off for better error messages under PostgreSQL -->
<!-- hibernate.jdbc.batch_size=0 -->
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


Hibernate 4
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="hibernateExceptionTranslator"
class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
</value>
<!-- Turn batching off for better error messages under PostgreSQL -->
<!-- hibernate.jdbc.batch_size=0 -->
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


Spring + Hibernate 3
@Autowired
@Required
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
public List<T> getAll() {
return hibernateTemplate.loadAll(this.persistentClass);
}
public T get(PK id) {
T entity = hibernateTemplate.get(this.persistentClass, id);
if (entity == null) {
log.warn("Uh oh, '" + this.persistentClass + "' object with id '" + id + "' not found...");
throw new ObjectRetrievalFailureException(this.persistentClass, id);
}
return entity;
}
public T save(T object) {
return hibernateTemplate.merge(object);
}
public void remove(PK id) {
hibernateTemplate.delete(this.get(id));
}


Hibernate 4
@Autowired
@Required
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public List<T> getAll() {
return sessionFactory.getCurrentSession().createQuery("from " + this.persistentClass).list();
}
public T get(PK id) {
T entity = (T) sessionFactory.getCurrentSession().get(this.persistentClass, id);
if (entity == null) {
log.warn("Uh oh, '" + this.persistentClass + "' object with id '" + id + "' not found...");
throw new ObjectRetrievalFailureException(this.persistentClass, id);
}
return entity;
}
public T save(T object) {
return (T) sessionFactory.getCurrentSession().merge(object);
}
public void remove(PK id) {
sessionFactory.getCurrentSession().delete(this.get(id));
}


JPA with Spring 2.0



JPA with Spring 3.1

Spring Data
Spring Data makes it easier to build Spring-powered applications that use new data access technologies such as non-relational databases, map-reduce frameworks, and cloud based data services as well as provide improved support for relational database technologies.


http://www.springsource.org/spring-data







Plain JPA :: Before
/**
* Service interface for {@link Customer}s.
*
* @author Oliver Gierke
*/
public interface CustomerService {
Customer findById(Long id);
Customer save(Customer customer);
List<Customer> findAll();
List<Customer> findAll(int page, int pageSize);
List<Customer> findByLastname(String lastname, int page, int pageSize);
}


/**
* Plain JPA implementation of {@link CustomerService}.
*
* @author Oliver Gierke
*/
@Repository
@Transactional(readOnly = true)
public class CustomerServiceImpl implements CustomerService {
@PersistenceContext
private EntityManager em;
@Override
public Customer findById(Long id) {
return em.find(Customer.class, id);
}
@Override
public List<Customer> findAll() {
return em.createQuery("select c from Customer c", Customer.class).getResultList();
}
@Override
@Transactional
public Customer save(Customer customer) {
if (customer.getId() == null) {
em.persist(customer);
return customer;
} else {
return em.merge(customer);
}
}

JPA with Spring Data :: After
/**
* Repository to manage {@link Customer} instances.
*
* @author Oliver Gierke
*/
public interface CustomerRepository extends
CrudRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
Page<Customer> findByLastname(String lastname, Pageable pageable);
}


What’s New in Servlet 3.0

Programmatic definition of filters, servlets, listeners and URL patterns
@WebServlet, @WebFilter, @WebListener
@WebInitParam
@MultipartConfig
Web Fragments
Asynchronous Servlet and Comet Support


Hardest thing about Servlet 3?
Is getting the Maven dependency right ...




<!-- Servlet 3.0 -->
<!-- http://stackoverflow.com/questions/1979957/maven-dependency-for-servlet-3-0-api -->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.servlet</artifactId>
<version>3.0</version>
<scope>provided</scope>
</dependency>


Spring + Servlet 3.0

WebApplicationInitializer for programmatic configuration
Instead of:


<servlet>
<servlet-name>kickstart</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>kickstart</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>


Servlet 3.0

WebApplicationInitializer for programmatic configuration
You use:


import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
public class KickstartWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet());
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("*.htm");
}
}



WebApplicationInitializer with XmlApplicationContext


import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
public class KickstartWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/applicationContext.xml");
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet());
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("*.htm");
}
}



WebApplicationInitializer with JavaConfig


public class KickstartWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext =
new AnnotationConfigWebApplicationContext();
dispatcherContext.register(DispatcherConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher",
new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}


@MVC Resources
<!-- View Resolver for JSPs -->
<beans:bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<beans:property name="prefix" value="/WEB-INF/pages/"/>
<beans:property name="suffix" value=".jsp"/>
</beans:bean>
<beans:bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<beans:property name="basename" value="messages"/>
<beans:property name="useCodeAsDefaultMessage" value="true"/>
</beans:bean>
<context:component-scan base-package="spring.kickstart"/>
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven/>
<resources mapping="/resources/**" location="/resources/"/>
<!-- Maps '/' requests to the 'index' view -->
<view-controller path="/" view-name="index"/>






<link rel="stylesheet" type="text/css"
href="${ctx}/resources/styles/deliciouslyblue/theme.css" title="default" />
<link rel="alternate stylesheet" type="text/css"
href="${ctx}/resources/styles/deliciouslygreen/theme.css" title="green" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="${ctx}/resources/scripts/application.js"></script>




Web Performance Best Practices

Optimizing caching
Minimizing round-trip times
Minimizing request overhead
Minimizing payload size
Optimizing browser rendering
Optimizing for mobile


Wro4j

Open Source Java project for optimization of web resources
Provides concatenation and minimization of JS and CSS
Gzip, YUI Compressor, JsHint, JsHint, CssLint, LESS, SASS, CoffeeScript, Dojo Shrinksafe
Profiles





XML Profiles

Profiles allow for environment-specific bean definitions
Activated with:
-Dspring.profiles.active=test
ctx.getEnvironment().setActiveProfiles(“dev”)
<init-param> spring.profiles.active in web.xml
@Profile(“prod”) with @Configuration
Wro4j and Profiles










@Profile
import org.springframework.context.annotation.Profile;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Profile("dev")
public @interface Dev {
}
@Repository
@Dev
@Transactional(readOnly = true)
public class CustomerRepositoryImpl implements CustomerRepository {
@PersistenceContext
private EntityManager em;


Cache Abstraction

Not an implementation, but an abstraction
Frees you from writing logic, but does not provide stores
JDK ConcurrentMap
EhCache
@Cacheable and @CacheEvict
Can use Spring EL for “key” and “condition” attributes
Annotations triggered by <cache:annotation-driven/>
Test Support for JavaConfig and Profiles

Spring 3.0 added @Configuration (JavaConfig)
TestContext Framework provides annotationdriven testing support
Spring 3.1 adds “loader” attribute to @ContextConfiguration for @Configuration


Spring 2.0 Testing


public class CustomerRepositoryTest extends AbstractJpaTests {
private CustomerRepository customerRepository;
private EntityManagerFactory emf;
public void setCustomerRepository(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
public void setEntityManagerFactory(EntityManagerFactory emf) {
this.emf = emf;
}
protected String[] getConfigLocations() {
return new String[] {"repository-test-config.xml"};
}
protected void onSetUpInTransaction() throws Exception {
EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
Customer c = new Customer();
c.setName("Test");
c.setCustomerSince(new Date());
em.persist(c);
super.onSetUpInTransaction();
}
public void testAddCustomer() {
Customer c = new Customer();
...


TestContext with XML
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/repository-config.xml"})
@Transactional
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
public class CustomerRepositoryTest {
@PersistenceContext
private EntityManager em;
@Autowired
private CustomerRepository customerRepository;
@Before
@Transactional
public void onSetUpInTransaction() {
Customer c = new Customer();
c.setName("Test");
c.setCustomerSince(new Date());
em.persist(c);
}
@Test
public void testAddCustomer() {
Customer c = new Customer();
c.setName("New");
c.setCustomerSince(new Date());
customerRepository.save(c);
List<Customer> customers = customerRepository.findAll();
assertTrue(customers.contains(c));
}


TestContext with @Configuration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@Transactional
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
public class CustomerRepositoryTest {
@Configuration
static class ContextConfiguration {
@Bean
public CustomerRepository customerRepository() {
return new CustomerRepositoryImpl();
}
}
@PersistenceContext
private EntityManager em;
@Autowired
private CustomerRepository customerRepository;
@Before
@Transactional
public void onSetUpInTransaction() {
Customer c = new Customer();
c.setName("Test");
c.setCustomerSince(new Date());
em.persist(c);
}
@Test
public void testAddCustomer() {
Customer c = new Customer();

Leave a Reply

Subscribe to Posts | Subscribe to Comments

About This Site

Howdy! My name is Suersh Rohan and I am the developer and maintainer of this blog. It mainly consists of my thoughts and opinions on the technologies I learn,use and develop with.

Blog Archive

Powered by Blogger.

- Copyright © My Code Snapshots -Metrominimalist- Powered by Blogger - Designed by Suresh Rohan -