http://www.developer.com/

Back to article

The New Spring 3.0 Features You Need to Know


January 29, 2010

The Spring framework is a lightweight, complete solution for building enterprise Java applications. Modularity is its key feature, which allows enterprise application developers to use only the modules they require from the stack. The Spring framework has become popular because it can deliver increased productivity, faster project completion, and improved portability and application quality.

The new Spring framework release, Spring 3.0, is entirely based on Java EE 5 (with backward compatibility for previous versions). In addition to supporting Java 5 features—and offering enhancements to existing APIs, Spring 3.0 also supports some of the new features slated for Java EE 6, such as asynchronous method invocation. The component structure is reorganized from Spring 2.x, and Spring 3.0 introduces some new modules. The Spring 3.0 components are classified as follows:

  • Core Container
  • Data Access/Integration
  • Web
  • Aspect Oriented Programming (AOP)
  • Instrumentation
  • Test

This article examines these notable new features in Spring 3.0:

  • Spring Expression Language (SpEL)
  • Object/XML Mapping (OXM) module
  • Type-conversion system
  • Formatter SPI
  • RESTful web services support

Spring Expression Language

Spring 3.0 introduces Spring Expression Language (SpEL), a powerful expression language that supports querying and manipulating an object graph at runtime. With SpEL, Spring applications can overcome the limitation of using only fixed values in configuration files. SpEL is part of the Spring core container. It can be used for bean definitions in both XML- and annotation-based configurations.

The SpEL syntax to define an expression is #{<expression>}. SpEL supports functions such as literal expressions, regular expressions, relational operators, assignment, boolean and relational operators, and ternary operators. It also supports functions related to classes such as class expression, accessing the properties, invocation of methods, invocation of constructors, and user-defined functions.

While SpEL works for all the products in the Spring portfolio, SpEL is designed to be self-contained and so it can be used independently outside the Spring portfolio as well.

SpEL in Bean Definition

The following is an application context that uses SpEL for bean definition.

  <bean id="customer" class="com.el.Customer">
        <property name="dateOfEnrollment" value="#{new java.util.Date()}" />
    </bean>


Below is a bean class that uses SpEL for bean definition.

public class Customer {
    @Value("#{434}")
    private int customerId;
    private Date dateOfEnrollment;
    …
    @Value("#{new java.util.Date()}")
    public void setDateOfEnrollment(Date dateOfEnrollment) {
        this.dateOfEnrollment = dateOfEnrollment;
    }
}


For the bean class example, the application context should have <context:annotation-config /> .

SpEL in Invocation of Constructor

The following SpEL code snippet instantiates the Customer bean, invoking an overloaded constructor.

ExpressionParser parser = new SpelExpressionParser();
        Customer customer = parser.parseExpression("new 
      com.el.Customer(123,'George')").getValue(Customer.class);


The above code snippet replaces the bean creation by using the ApplicationContext and context.getBean() method. Note that the fully qualified class name should be passed to the parseExpression method.

SpEL in Accessing Member Variable

The following code snippet instantiates the Customer bean and sets the customerId to 124.

        ExpressionParser parser = new SpelExpressionParser();
        Customer customer = parser.parseExpression("new 
      com.el.Customer()").getValue(Customer.class);
 
        StandardEvaluationContext context = new 
      StandardEvaluationContext(customer);
        context.setVariable("cid", "124");   // statement 1
        parser.parseExpression("customerId=#cid").getValue(context);   // statement 2


The statement 1 command sets the cid to 124 within the context. The statement 2 command parses the expression string (customerId=#cid) and evaluates the expression against the context, hence setting the customerId of Customer bean.

As mentioned previously, SpEL supports other functions as well. The above are some of the most interesting.

Object/XML Mapping (OXM) Module

The OXM module of Spring 3.0 (in the Data Access / Integration component) supports the marshalling and unmarshalling of Java objects and XML documents. It also supports various O/X mapping frameworks such as Castor, JAXB, JiBX, XMLBeans, and XStream.

Spring OXM enables rapid application development by allowing easy configuration and injection of marshaller and unmarshaller dependencies. Spring OXM's two global interfaces, Marshaller and Unmarshaller, allow the programmer to switch O/X mapping frameworks with almost no change in the code. Similar to the data access exception hierarchy, the Spring OXM module has an exception hierarchy that wraps the exceptions thrown by third-party providers.

Here is the Customer bean that has to be marshaled/unmarshaled:

public class Customer {
    private int customerId;
    private String customerName;
    // setter and getter method
}


The OXM class in Listing 1 marshals and unmarshals this bean.

The marshal() method of marshaller serializes the customer object to XML, and the unmarshal() method of unmarshaller deserializes the XML to the customer object. The saveCustomer() method serializes the Customer object to CustomerBean.xml, and the openCustomer() method deserializes the XML and returns the customer object.

The marshaller and unmarshaller property of the OXM class is set through the application context, as shown here.

<bean id="oxm" class="com.oxm.OXM" >
        <property name="marshaller" ref="castorMarshaller" />
        <property name="unmarshaller" ref="castorMarshaller" />
    </bean>
 
    <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller">
        <property name="mappingLocation" value="classpath:mapping.xml" />
    </bean>


In this example, the application context uses the Castor O/X mapping framework for both marshalling and unmarshalling. The Castor XML mapping is shown below (mapping.xml).

<mapping>
    <class name="com.oxm.Customer">
      <map-to xml="customer"/>
      <field name="customerId" type="integer">
         <bind-xml name="customerId" node="element"/>
      </field>
      <field name="customerName" type="string">
         <bind-xml name="customerName" node="element"/>
      </field>
    </class>
</mapping>


Type-Conversion System

Typically in a web-based enterprise application, you have to convert string inputs to the corresponding data type and convert the data type back to string when rendering the response. Spring 3.0 has introduced a general type-conversion system to make this process more efficient. The framework provides a converter SPI and API. The converter SPI allows you to implement type-conversion logic, while the API allows you to invoke and execute the type conversions logic provided at runtime.

Spring 3.0 delivers its type-conversion system via three packages:

  • org.springframework.core.convert – contains the type conversion API
  • org.springframework.core.convert.converter – contains the type conversion SPI
  • org.springframework.core.convert.support – contains some robust conversion service implementations

Converter SPI

The converter SPI has the following five interfaces:

  • Converter<S,T> – Implement this interface when you need to convert the source type S to target type T.
  • ConverterFactory<S,R> – Implement this interface when you need to convert a source type S to a class R in the class hierarchy.
  • GenericConverter – This is the most flexible but complex converter SPI interface. It supports conversion between multiple source and target type pairs. In addition, it has access to the source and target field context, enabling you to resolve field metadata such as annotations and generics information.
  • ConditionalGenericConverter – This subinterface of GenericConverter enables the GenericConverter only when a certain defined condition is satisfied. For example, the GenericConverter can be invoked only if the source type has the definition of a specific method.
  • ConverterRegistry – Use this interface to register a converter with the conversion system.

Here is a typical example of converting a string to an integer.

public class StringToInteger implements Converter<String, Integer> {
    public Integer convert(String source) {
        return Integer.valueOf(source);
    }
}


Converter API

The converter API has the ConversionService interface and TypeDescriptor class. The Spring 3.0 conversion system implements the ConversionService interface from the converter API and the registry available in the Converter SPI. The ConversionService implementation delegates requests to the converter, which is registered with the registry, while the TypeDescriptor specifies the context of a type. The GenericConversionService, which implements the ConversionService and the registry classes, is a conversion service suitable for most environments.

Injecting the Converters

The converters created can be injected into the Spring container (ApplicationContext) or into the individual beans. The ConversionServiceFactoryBean factory class installs default converters that are appropriate for most environments. To override the converters, you can inject the converters dependency into ConversionServiceFactoryBean.

The following configuration (with a bean ID of conversionService) would inject the default ConversionService to the Spring container.

<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean" />


This code snippet accesses the conversionService to convert an integer to string.

ConversionService service = (ConversionService)context.
getBean("conversionService");
if (service.canConvert(Integer.class, String.class)){
             value = (String)service.convert(12.3, String.class);
}


You can configure the ConversionService programmatically as well, using the @Autowired annotation.

Formatter SPI and APIs

Spring 3.0 has also introduced a general-purpose type formatter system to format the response to be rendered back to the user.

Formatter SPI

The Spring 3.0 framework offers a separate Formatter SPI. The Formatter SPI can be used in client environments such as a web application that requires data to be parsed and localized.

The Formatter SPI contains the interface Formatter, which extends Printer and Parser. The Printer<T> interface would display the object of type <T>. The Parser<T> interface would produce the instances of T, thereby parsing the text.

Formatter API

The Formatter API has subpackages for datetime and number formatting. It also has a joda subpackage within datetime that supports the Joda types format. The number formatting subpackage has CurrencyFormatter, NumberFormatter, and PercentFormatter.

Annotation can be bound to the formatter by implementing AnnotationFormatterFactory.

Format Annotation API

The Format Annotation API has the subpackage annotation for annotation types. It supports DateTimeFormat and NumberFormat.

The following code snippet demonstrates the usage of the DateTimeFormat annotation.

@DateTimeFormat(iso=ISO.DATE)
    private Date date;


RESTful Web Services Support

REST is a compelling alternate to SOAP for web services. Spring 3.0 has added RESTful functionality to Spring MVC. It supports both server-side applications that provide the service and client-side web applications that consume the service using RESTful principles.

Providing Server-side RESTful Services

The @PathVariable annotation binds the method parameters to a URI template variable.

@RequestMapping(value="/welcome/{uName}", 
      method=RequestMethod.GET)
    public ModelAndView display(@PathVariable String uName){
        System.out.println("Hello " + uName);
        String msg = "Hello " + uName;
        return new ModelAndView("/WEB-INF/jsp/Success.jsp","msg",msg);
    }


When the client raises a request to /welcome/John, the John will be bound to uName.

Accessing RESTful Services from the Client

The RestTemplate is the core class for client-side HTTP access. The consumer can invoke the RESTful web service using the RestTemplate class and HttpMessageConverter.

The following code invokes a RESTful web service.

String uri = "http://hostname/ApplicationContext/welcome/{uName}";
            RestTemplate template = new RestTemplate();
            template.getForObject(uri, String.class, "John");


The getForObject method retrieves the representation by performing GET on the specified URL. The RestTemplate also has support for other HTTP methods. The HttpMessageConverter converts the HTTP request and responses between the provider and the consumer.

Spring 3.0 supports various HttpMessageConverter implementations, such as MarshallingHttpMessageConverter for XML, StringHttpMessageConverter for text/plain content type, MappingJacksonHttpMessageConverter for JSON, Jaxb2RootElementHttpMessageConverter for XML using JAXB2, and others.

Spring 3.0 Honorable Mention

The following are some other noteworthy features and enhancements in Spring 3.0:

  • Spring 3.0 supports the JMS integration framework, which simplifies the use of the JMS API within the application.
  • Spring 3.0 includes Spring Portlet (part of the Spring Web component).
  • Spring supports integration with the Struts web tier, but Spring 3.0 has deprecated its support for Struts 1.x. However, you can replace it with Struts 2.0 and its Spring integration.
  • Spring 3.0 supports Java EE 6, with packages that enable Spring 3.0 applications to integrate with the Java Persistence API, JavaServer Faces 2.0, and Servlet 3.0. Spring 3.0 also provides support for asynchronous method invocation via the @Async annotation.
  • Spring AOP offers a separate Aspect module, which allows you to integrate Spring with AspectJ.
  • Spring 3.0 has deprecated the legacy JUnit 3.8 class hierarchy. Instead, it provides a separate module test that allows you to test components developed in Spring with JUnit and TestNG.

Acknowledgments

The author would like to thank Raghavendran N. and Sangeetha S. for their guidance, support, and constant encouragement.

About the Author

Yuvarani Meiyappan works as a lead in the E&R division of Infosys Technologies Limited. She has over eight years of experience in design and development of Java and Java EE applications.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date