Use Spring @Value annotation for injecting Date properties

By default, Spring does not convert a Date string defined in a property file when using the @Value annotation automatically. For example, if you have the following properties file:

aDateStr=24-10-2010

and codes

@Component
public class ValueExample
{
    @Value(“${aDateStr}”)
    Date myDate;

Spring will generate the following exceptions:

Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'java.util.Date'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date]: no matching editors or conversion strategy found
 at org.springframework.beans.SimpleTypeConverter.convertIfNecessary(SimpleTypeConverter.java:58)
 at org.springframework.beans.SimpleTypeConverter.convertIfNecessary(SimpleTypeConverter.java:43)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:722)
 at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
 ... 15 more
 Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.util.Date]: no matching editors or conversion strategy found
 at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:236)
 at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:94)
 at org.springframework.beans.SimpleTypeConverter.convertIfNecessary(SimpleTypeConverter.java:49)

One possible work around is to use Spring Expression Language (SpEL) as follows

    @Value(“#{new java.text.SimpleDateFormat(‘${aDateFormat}’).parse(‘${aDateStr}’)}”)
    Date myDate;

Note you can also define the date format desired as a property to be injected into @Value annotation. So the new property file will have the following properties defined:

aDateStr=24-10-2010

aDateFormat=dd-MM-yyyy

Advertisements

Using Spring RestTemplate to consume restful webservice

Introduction

I recently have to write a client to consume a restful webservice using Spring RestTemplate class. The task turns out to be non trivial as there are a few gotchas needed to be handled because of the way the webservice is implemented. I managed to put together a solution after searching through some useful articles online. I summarise what I have done in this article.

Problem 1: SSL

The webservice I am consuming is implemented in another web application but has to be accessed via https. As a result, calling the getObject() method in RestTemplate with the url will return the following exception:

org.springframework.web.client.ResourceAccessException: I/O error: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:199)
… 32 more

I decide to bypass the certificate validation by adding the following codes:

    public static void trustSelfSignedSSL()
{
try
{
final SSLContext ctx = SSLContext.getInstance(“TLS”);
final X509TrustManager tm = new X509TrustManager()
{

public void checkClientTrusted(final X509Certificate[] xcs, final String string) throws CertificateException
{
// do nothing
}

public void checkServerTrusted(final X509Certificate[] xcs, final String string) throws CertificateException
{
// do nothing
}

public X509Certificate[] getAcceptedIssuers()
{
return null;
}
};
ctx.init(null, new TrustManager[]
{ tm }, null);
SSLContext.setDefault(ctx);
}
catch (final Exception ex)
{
ex.printStackTrace();
}
}

Note the method is static and needs to be called once before calling the webservice. Now calling RestTemplate.getObject will return something about hostname wrong:

org.springframework.web.client.ResourceAccessException: I/O error: HTTPS hostname wrong:  should be <some url>; nested exception is java.io.IOException: HTTPS hostname wrong:  should be <some url>
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:453)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:401)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:199)

… 32 more

The above error can be removed by providing a custom http client factory by extending Spring class SimpleClientHttpRequestFactory:

public class MySimpleClientHttpRequestFactory extends SimpleClientHttpRequestFactory
{

private final HostnameVerifier verifier;

public MySimpleClientHttpRequestFactory(final HostnameVerifier verifier)
{
this.verifier = verifier;
}

@Override
protected void prepareConnection(final HttpURLConnection connection, final String httpMethod) throws IOException
{
if (connection instanceof HttpsURLConnection)
{
((HttpsURLConnection) connection).setHostnameVerifier(verifier);
}
super.prepareConnection(connection, httpMethod);
}
}

Note we also need to inject a dummy hostname verifier for the above class to bypass the hostname verification:

public class NullHostnameVerifier implements HostnameVerifier
{
@Override
public boolean verify(final String hostname, final SSLSession session)
{
return true;
}

}

All then left to do is the inject the client http request factory to the resttemplate:

RestTemplate template = new RestTemplate();

final MySimpleClientHttpRequestFactory factory = new MySimpleClientHttpRequestFactory(verifier);
template.setRequestFactory(factory);

Problem 2 : List Generic / Type Erasure

My second problem with accessing the webservice is that it returns an array of JSON object in the form

[{“no”:”00028″,”l”:”201″,”t”:0,”i”:10,”a”:20},…,{“no”:”00028″,”l”:”201″,”t”:5,”i”:15,”a”:25}]

Because of Java type erasure, calling RestTemplate.getObject(url, List.class) will return a list of LinkedHashMap objects. To marshall the returned json objects into domain objects, the default json message converter MappingJacksonHttpMessageConverter has to be extended as follows:

public class MyJsonMessageConverter extends MappingJacksonHttpMessageConverter
{

@Override
protected JavaType getJavaType(final Class<?> clazz)
{
if (List.class.isAssignableFrom(clazz))
{
final TypeFactory typeFactory = getObjectMapper().getTypeFactory();
return typeFactory.constructCollectionType(ArrayList.class, StockInventory.class);
}
else
{
return super.getJavaType(clazz);
}
}

Note the use of TypeFactory.constructCollectionType method to map list type into my domain object type StockInventory.

Problem 3: Custom deserialiser

The last problem I need to solve is to implement a custom deserialiser in my message converter to handle the coded json object. I do this by extending the getObjectMapper method:

 @Override
public void setObjectMapper(final ObjectMapper objectMapper)
{
// add custom json serialiser for ItemInventory response
final SimpleModule module = new SimpleModule(“StockInventoryModule”, new Version(1, 1, 1, null));
module.addDeserializer(StockInventory.class, new JsonDeserializer<StockInventory>()
{

@Override
public StockInventory deserialize(final JsonParser jp, final DeserializationContext cxt) throws IOException,
JsonProcessingException
{
final StockInventory stockInventory = new StockInventory();
//    final DeserializerProvider provider = cxt.getDeserializerProvider();
while (jp.nextToken() != JsonToken.END_OBJECT)
{
final String fieldName = jp.getCurrentName();
jp.nextToken();
if (“no”.equals(fieldName))
{
stockInventory.setNo(jp.getText());
}
else if (“l”.equals(fieldName))
{
stockInventory.setLocation(jp.getText());
}
… // handle other fields
else
{
throw new IllegalStateException(“unrecognized field [” + fieldName + “]”);
}
}
return stockInventory;
}
});
objectMapper.registerModule(module);
super.setObjectMapper(objectMapper);
}

Now the only thing left to do is to use the customer converter in the RestTemplate:

  final List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
final MappingJacksonHttpMessageConverter converter = new MyJsonMessageConverter();
converter.setObjectMapper(new ObjectMapper());
list.add(converter);
template.setMessageConverters(list);
List<StockInventory> stocks = template.getForObject(url, List.class);

That’s it!

Resources

Thanks for the contributors of the following links where I got the codes from:

  1. SSL – http://stackoverflow.com/questions/1725863/ssl-handshake-issue-using-spring-resttemplate
  2. Customer client HTTP request factory codes from http://www.jroller.com/jurberg/entry/using_a_hostnameverifier_with_spring
  3. JSON list – http://stackoverflow.com/questions/7040279/jackson-json-java-generics-get-linkedhashmap
  4. JSON list – http://stackoverflow.com/questions/6173182/spring-json-convert-a-typed-collection-like-listmypojo

Using Spring 3.1 Cache Abstraction and Ehcache

Spring 3.1 supports a new cache abstraction layer which allows you to implement caching in a web application beyond the L2 and query cache in Hibernate. This blog provides a quick walkthrough on how to setup and apply caching  in your codes using Spring and Ehcache.

Getting the jars

First, we need to add the spring context support and ehcache jar files to the project. I am using Maven and include the following dependencies in the pom file:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>

<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.5.2</version>
</dependency>

Configure Spring

As with any other Spring components, we need to configure some beans in a XML file. At a minimum, we will need the followings:

<?xml version=”1.0″ encoding=”UTF-8″?>
<beans xmlns=”http://www.springframework.org/schema/beans&#8221;
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
xmlns:cache=”http://www.springframework.org/schema/cache&#8221;
xsi:schemaLocation=”
http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd”&gt;

<cache:annotation-driven cache-manager=”cacheManager”/>

<bean id=”cacheManager”>
<property name=”cacheManager” ref=”ehcache”/>
</bean>

<!– Ehcache library setup –>
<bean id=”ehcache”
class=”org.springframework.cache.ehcache.EhCacheManagerFactoryBean”>
<property name=”configLocation” value=”classpath:ehcache.xml”/>
</bean>

</beans>

Caching is setup via annotation, as configured in the tag cache:annotation-driven. Next a cache manager is defined and is referenced to a factory bean for instantiating Ehcache. The bean org.springframework.cache.ehcache.EhCacheManagerFactoryBean configLocation property is set to the ehcache.xml setup files where we will define the caches used by the application.

The ehcache.xml config file

I recommend starting with the ehcache-failsafe.xml found in the ehcache-core jar file and add the caches required by the application. An example for this blog is included below:

<!– Sample cache named sampleCache1
This cache contains a maximum in memory of 10000 elements, and will expire
an element if it is idle for more than 5 minutes and lives for more than
10 minutes.

If there are more than 10000 elements it will overflow to the
disk cache,
–>
<cache name=”sampleCache1″
maxElementsInMemory=”10000″
eternal=”false”
overflowToDisk=”true”
timeToIdleSeconds=”300″
timeToLiveSeconds=”600″
/>

It is also necessary to set the directory to store the files when caches overflow into disk storage. To do this, update the path attribute in the diskStore tag:

 <diskStore path=”${CACHE_DIR}”/>

Note the use of variable CACHE_DIR above. This will allow us to define the directory using the Java JVM variable (-DCACHE_DIR) on different environments.

Adding Cache Annotations

Now we are ready to do something useful. To add caching to a method, use the @Cacheable annotation as shown below. I typically would add caching in the service layer.

    @Cacheable(value=”sampleCache1″, key=”#id”)
public Product load(String id) {
LOG.info(“load product with id” + id);
return repository.load(id);
}

I recommend setting the key explicitly instead of relying on the default key generator. Alternatively, you could configure your own key generator.

To evict an object in the cache, use @CacheEvict annotation. For example, we would have to evict the object in the cache in the update method.

    @CacheEvict(value=”sampleCache1″, key=”#product.id”, beforeInvocation=false /*default*/, allEntries=false /*default*/)
public void update(Product product) {
repository.update(product);
}

@CacheEvict annotation provides 2 handy attributes: beforeInvocation can be set to evict the object in the cache before or after (default) the method is executed. allEntries can be used to evict all objects in the cache. Only the object with the key is evicted by default.

Active Directory Authentication with Spring Security 3.1

Spring Security v3.1 adds new support for Active Directory authentication with the new authentication provider class ActiveDirectoryLdapAuthenticationProvider. This article will provide a step-to-step on how to set up Spring Security to authenticate users in a J2EE web application using AD. I will also demonstrate how to configure a custom filter to the authentication filter chain.

Getting Spring Security 3.1

I use version 3.1.0.RELEASE with the following Maven setup:

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.1.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
<version>3.1.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.0.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.0.RELEASE</version>
</dependency>

Configure Active Directory Authentication

Configure Spring Security to use class ActiveDirectoryLdapAuthenticationProvider  is rather straight forward:

<beans:bean id=”ldapAuthProvider”
class=”org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider”>
<beans:constructor-arg value=”${ldap.domain}” />
<beans:constructor-arg value=”${ldap.url}” />
</beans:bean>

<authentication-manager alias=”authenticationManager”>
<authentication-provider ref=”ldapAuthProvider”>
</authentication-provider>
</authentication-manager>

So all you need is to set up Spring Security to use the AD class as authentication provider and provide the domain and url as constructor parameters.

Custom Login Filter

Now the fun part. In many cases you would need to customise the authentication/authorisation performed by Spring Security. For example, to use extra information such as user’s company/division as part of the authentictaion/authorisation process. Spring Security allows you to replce the default filter with your own custom filter for this.

First implement your custom filter by extending class UsernamePasswordAuthenticationFilter. See the javadoc for methods supported. For example, to perform some processing on successful authentication:

public class MyUsernamePasswordAuthFilter extends UsernamePasswordAuthenticationFilter {

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain, Authentication authResult)
throws IOException, ServletException {
super.successfulAuthentication(request, response, filterChain, authResult);
String username = super.obtainUsername(request);
// do something with  username


}

In Spring bean configuration, add the following:

<beans:bean id=”navSecurityFilter” class=”com.rlee.example.security.MyUsernamePasswordAuthFilter”>
<beans:property name=”authenticationManager” ref=”authenticationManager” />
<beans:property name=”authenticationFailureHandler” ref=”failureHandler” />
<beans:property name=”authenticationSuccessHandler”ref=”successHandler” />
</beans:bean>

<beans:bean id=”successHandler”
class=”org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler”>
<beans:property name=”defaultTargetUrl” value=”/”/>
<beans:property name=”alwaysUseDefaultTargetUrl” value=”true”/>
</beans:bean>
<beans:bean id=”failureHandler”
class=”org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler”>
<beans:property name=”defaultFailureUrl” value=”/login.jsp?login_error=true”/>
</beans:bean>

Note I also include the success and failure handlers properties to the custom filter. The next step is to include the custom filter in the Spring Security http configs.

<http auto-config=’false‘ entry-point-ref=”LoginUrlAuthenticationEntryPoint“>
<custom-filter ref=”mySecurityFilter” position=”FORM_LOGIN_FILTER” />
<intercept-url pattern=”/login.jsp*” access=”IS_AUTHENTICATED_ANONYMOUSLY” requires-channel=”https” />
<intercept-url pattern=”/**” access=”ROLE_REGISTERD_USER” />
<anonymous />

<logout />
</http>

Note you have to disable the auto-config option and insert the custom-filter tag to replace the default Spring Security filter in the  position FORM_LOGIN_FILTER. See Spring Security documentation here for more details on filter chain. For completeness, the entry point config is shown below:

 <beans:bean id=”LoginUrlAuthenticationEntryPoint”
class=”org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint”>
<beans:property name=”loginFormUrl” value=”/login.jsp” />
<beans:property name=”forceHttps” value=”true” />
</beans:bean>

Conclusions

That’s all. The new Active Directory authentication support in Spring Security 3.1 makes things much easier to configure than using LDAP authentication provider in v3.0. I also show how you can replace the default filter used by Spring Security with your own custom filter. Hope this helps.

Validation in Spring 3 MVC App

Summary

Validating user inputs is an important function for most web applications. Typically, you need to validate the values a user enters, e.g. via a web form, to ensure that all the required fields are provided and that the values are acceptable according to the system’s business rules and logics.

This article demonstrates how to setup Spring 3 MVC web applications to support bean validation with JSR 303, as well as extending the standard validation capability by adding custom validators.

Set up Spring 3 validation support

Enabling JSR-303 bean validation support in Spring 3 is straight forward. Just add the following bean definition in your application context xml file:

    <bean id=”validator” class=”org.springframework.validation.beanvalidation.LocalValidatorFactoryBean”
/>

From the javadoc, the above class is:

the central class for javax.validation (JSR-303) setup in a Spring application context: It bootstraps a javax.validation.ValidationFactory and exposes it through the Spring org.springframework.validation.Validator interface  as well as through the JSR-303 javax.validation.Validator interface and the javax.validation.ValidatorFactory interface itself.

Basically, what it means is it allows you to inject the above bean directly into any other bean without the need to access the factory. We will encounter an example later in this article when writing a custom bean to support cross field validation.

Note you will need to add the following dependency if you are using Maven:

 <dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>

Bean validation in Spring 3 MVC – An Example

Now we can add validation annotations to the bean. For example,

public class MyBean {

@NotNull
private String requiredStr; // cannot be null

@Min(1)
private int positiveInt; // positive integer

Other useful validators include:

  • Digits – a number within a specified range
  • Future – a future date
  • Past – a past date

See javadoc for a complete list of standard annotations supported in JSR-303. You can also use the following non-standard validators if you are using Hibernate:

  • Email – a valid email address
  • Length – a string has length within min and max lengths
  • NotEmpty – string not null or blank
  • Range – between a min and max values

Then, use @Valid in the request mapping method of a Spring MVC controller. To validate the above object:

@RequestMapping(method = RequestMethod.POST)
public String handleFormSubmission(@Valid MyBean mybean, BindingResult result) {
if (result.hasErrors()) {
// model has error(s)
}

Any validation errors are included in the BindingResult object. Validating error messages can be defined using “message” attribute of the validating tag. Alternatively, you can define messages using keys in a properties file. The key is in the format <validator>.<object name>.<property>. For example,

NotNull.myobj.requiredStr=This string is required

Min.myobj.positiveInt=Must be a positive value

Writing Custom validation annotation

It is also possible to write your own validating annotation. First, define the annotation interface. For example:

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=CreditCardValidator.class)
public @interface CreditCard {

String message() default “{com.rlee.CreditCardValidating.message}”;

Class<?>[] groups() default { };

Class<? extends Payload>[] payload() default {};
}

Next write the implementing class

public class CreditCardValidator implements ConstraintValidator<CreditCard, String> {

public void initialize(CreditCard constraintAnnotation) {
}

public boolean isValid(String value, ConstraintValidatorContext context) {

}

Note the validator needs to implement the generic ConstraintValidator class.

Writing custom validator for cross field validation

In many cases, an application will need to perform validations across multiple fields. For example, the minimum value of one field may depend on the chosen value of another field. In such case, a custom bean validator is required. Spring MVC allows you to do this easily by supporting binding of the custom validator to a controller using the @initBinder tag and method:

@Controller
public class MyController {

@Autowired
private MyValidator myValidator;

@InitBinder
protected void initBinder(WebDataBinder webDataBinder) {
webDataBinder.setValidator(myValidator);
}

The custom validator must implement Spring validator interface org.springframework.validation.Validator:

public class MyValidator implements Validator {

@Autowired
private Validator validator;

public boolean supports(Class<?> clazz) {

}

public void validate(Object target, Errors errors) {
// customer validation here

// delegate to standard validator

validator.validate(target, errors);
}

Note the injection of the standard validator, i.e. LocalValidatorFactoryBean.

Using Spring 3.1 Profile to run a web application in different environment

Spring 3.1 introduces a neat bean definition profiles features. Basically, you can define beans with different profiles and then set the active profiles to use at runtime for the application. A typical example would be to have different data source beans for development and production environments. This article will provide a quick how-to on configuring Spring to run a web application in different environments using Spring profiles.

1. Bean Definitions

The Spring 3.1 beans XML schema allow nested <beans/> elements and you can include a profile attribute to define one or more profiles to use for the beans.

<beans …>

<beans profiles=”dev”>

// define beans for dev environment

<bean …>

</beans>

<beans profiles=”prod”>

// define beans for prod environment

<bean …>

</beans>

Note that:

(1) Multiple profiles can be defined by separating profiles with spaces, commas or semi-colons.

(2) The beans defined in the element are ignored if none of the profiles are activated.

(3) Beans without a profile will always be included.

2. Activate Profiles to use

There are 2 ways to activate the profiles to use:

(1) By defining the -D system properties “spring.profiles.active”. For example,

java -Dspring.profiles.active=dev …

(2) By setting the active profiles at runtime programmatically via application context initializer. Register the context intializer class in web.xml file:

<context-param>
<param-name>contextInitializerClasses</param-name>
<param-value>com.blog.example.ContextProfileInitializer</param-value>
</context-param>

and implement class, for example:

public class ContextProfileInitializer implements ApplicationContextInitializer<ConfigurableWebApplicationContext> {

public void initialize(ConfigurableWebApplicationContext ctx) {

ConfigurableEnvironment environment = ctx.getEnvironment();

// logic to decide active profiles

String profiles = getProfiles();

environment.setActiveProfiles(profiles);

}

Obviously, method (2) is more flexible but involves more work.

Setting profile in integration tests

Spring 3.1 M2 introduces the @ActiveProfile tag which comes in handle when writing integration test. For example:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = “classpath:/spring/app-config.xml”)
@ActiveProfiles(“dev”)

public class MyIntegrationTest {

Resources

Spring Blog: Spring Framework 3.1 M1: Introducing @Profile

Spring 3.1 schema xsd

Getting JSON from Spring 3 Controller

Spring 3 controller can generate JSON response transparently. All you need to do is to have jackson jar files in the web app classpath.  For example, a controller will look like:

@RequestMapping(value=”/example/get.action”, method=RequestMethod.GET)
public @ResponseBody Pizza getPizza() {
Pizza pizza = … // create object here
return pizza;
}

To get pizza object in JSON, the request header should have attribute Accept with value application/json.  Then json text will be returned by the controller in the response content, for example:

{

“base”:{“name”:”thin crust”},

“toppings”:[“bacon”,”olive”,”mushroom”],

“name”:”supreme”

}