Wednesday, January 30, 2013

CGLIB and ASM inlined with Spring 3.2

This is a small change, but will go some way with issues that I have faced in the past in getting the correct dependency of CGLIB/ASM with my projects. CGLIB and its dependency ASM are now both inlined with the Spring-Core binaries(as of Spring 3.2+) - their source is not maintained with the spring-core project, but are inlined at build time. From the maven pom.xml perspective, the following can now be kept out of the file:

<dependency>
 <groupId>cglib</groupId>
 <artifactId>cglib</artifactId>
 <version>2.2.2</version>
</dependency>

Thursday, January 24, 2013

Aspectj pointcut expression based on annotation on types/methods

Consider two classes, one with annotation applied on the type and one with annotation on a method:

@CustomAnnotation
public class Class1 {
 
 public void method11(){}

 public void method12(){}
}

public class Class2 {
 
 @CustomAnnotation
 public void method21(){}
 
 public void method22(){}

}


I had to write a Aspectj pointcut which selects the methods on classes where the CustomAnnotation is applied on types - methods of Class1 above. My first gut feel was to write an aspect along these lines:
@Pointcut("execution(@CustomAnnotation  * *.*(..))")
public void methodsInAnnotatedTypes(){}

This pointcut is wrong though, as it ends up selecting methods of Class2.

The reason is this, the pointcut expression signature for execution pointcut type is the following(this is from the Spring documentation site available here):

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?.name-pattern(param-pattern) throws-pattern?)

To select the methods based on annotation on the type, I have to add the annotation to the declaring-type-pattern above like the following:

execution(modifiers-pattern? ret-type-pattern (@CustomAnnotation declaring-type-pattern?).name-pattern(param-pattern) throws-pattern?)

Having it in the beginning will select any methods with Custom annotation on the method:
execution(@CustomAnnotation modifiers-pattern? ret-type-pattern declaring-type-pattern?.name-pattern(param-pattern) throws-pattern?)

So with this fix the correct pointcut expression becomes, and this selects the methods of Class1:

@Pointcut("execution(* (@CustomAnnotation *).*(..))")
public void methodsInAnnotatedTypes(){
 
}


Saturday, January 19, 2013

Mixin in Java with Aspects - for a Scala traits sample

Scala traits allow new behaviors to be mixed into a class.

Consider two traits to add auditing and version related fields to JPA entities:

package mvcsample.domain

import javax.persistence.Version
import scala.reflect.BeanProperty
import java.util.Date

trait Versionable {
  @Version
  @BeanProperty
  var version: Int = _
}

trait Auditable {
  @BeanProperty
  var createdAt: Date = _
 
  @BeanProperty
  var updatedAt: Date = _
}

Now to mix in 'Versionable' and 'Auditable' with their fields and behavior in a Member entity:

@Entity
@Table(name = "members")
class Member(f: String, l: String) extends BaseDomain with Auditable with Versionable {

  def this() = this(null, null)

  @BeanProperty
  var first: String = f

  @BeanProperty
  var last: String = l

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "member")
  @BeanProperty
  var addresses: java.util.List[Address] = _
}

trait BaseDomain {
  @BeanProperty
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "id")
  @Id
  var id: Long = 0
}


The Member class above will now have the behavior of the BaseDomain class, and will have the behavior of Versionable trait and the Auditable trait.

This kind of mixin is not possible with plain Java, as the equivalent of traits with fields and behavior would be an abstract(or concrete) class and Java allows deriving only from 1 base class. However with AspectJ it is possible to achieve an equivalent of mixin.

Consider the following aspects defined using Aspectj language:
package mvcsample.aspect;

import javax.persistence.Column;
import javax.persistence.Version;
import mvcsample.annot.Versioned;

public interface Versionable {
    
    static aspect VersionableAspect {
        declare parents: @Versioned  mvcsample.domain.* implements Versionable;
        
        @Version
        @Column(name = "version")
        private Integer Versionable.version;    
        
        public Integer Versionable.getVersion() {
        return this.version;
            }
        
        public void Versionable.setVersion(Integer version) { 
        this.version = version;
        }
    }
}


package mvcsample.aspect;

import java.util.Date;
import javax.persistence.Column;

import mvcsample.annot.Audited;
public interface Auditable {
    static aspect AuditableAspect {
        declare parents: @Audited mvcsample.domain.* implements Auditable ;
    
        @Column(name="created_at")
        private Date Auditable.createdAt;
        
        @Column(name="updated_at")
        private Date Auditable.updatedAt;
        
        public Date Auditable.getCreatedAt(){
            return this.createdAt;
        }
        
        public void Auditable.setCreatedAt(Date createdAt) {
            this.createdAt = createdAt;
        }
        
        public Date Auditable.getUpdatedAt(){
            return this.updatedAt;
        }
        
        public void Auditable.setUpdatedAt(Date updatedAt) {
            this.updatedAt = updatedAt;
        }
    }
}

"declare parents: @Versioned mvcsample.domain.* implements Versionable;" aspectj construct adds 'Versionable' interface as a parent to any class in package 'mvcsampple.domain' annotated with @Versioned, similarly the one for 'Auditable'
Then the aspect goes about adding fields to the Versionable interface which in turn ends up adding(mixing in) the fields to the targeted entity classes, this way the Audit related and Version related fields and methods get mixed into the entity classes.

With these two aspects defined, a target entity class would look like this:
@Entity
@Table(name="members")
@Access(AccessType.FIELD)
@Versioned
@Audited
public class Member extends BaseDomain{
 
 public Member(){}
 
 public Member(String first, String last){
  this.first = first;
  this.last = last;
 }
 
 private String first;
 
 @Size(min=1)
 private String last;
 
 @OneToMany(fetch=FetchType.EAGER, mappedBy="member")
 private List<Address> addresses = new ArrayList<>();
 
    ...
}


The fields and behavior defined in the Versionable and Auditable aspects would be mixed into this entity(more generally into any entity with @Versioned and @Audited annotations)

Probably not as clean as Scala traits but works nicely.

Wednesday, January 16, 2013

Spring Property Placeholder Configurer - A few not so obvious options

Spring's PropertySourcesPlaceholderConfigurer is used for externalizing properties from the Spring bean definitions defined in XML or using Java Config. There are a few options that PlaceholderConfigurer supports that are not obvious from the documentation but are interesting and could be useful.

To start with, an example from Spring's documentation, consider a properties file with information to configure a datasource:
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root

The PropertySourcesPlaceholderConfigurer is configured using a custom namespace:
<context:property-placeholder location="database.properties"/>

A datasource bean making use of these properties can be defined using XML based bean definition this way:

<bean id="dataSource" destroy-method="close"
    class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}"/>
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
</bean>

and using Java based configuration this way:
@Value("${jdbc.driverClassName}") private String driverClassName;
@Value("${jdbc.url}")             private String dbUrl;
@Value("${jdbc.username}")        private String dbUserName;
@Value("${jdbc.password}")        private String dbPassword;

@Bean
public BasicDataSource dataSource() {
 BasicDataSource dataSource = new BasicDataSource();
 dataSource.setDriverClassName(driverClassName);
 dataSource.setUrl(dbUrl);
 dataSource.setUsername(dbUserName);
 dataSource.setPassword(dbPassword);
 return dataSource;
}

The not so obvious options are:

First is the support for default values. Say for eg, if "sa" is to be provided as default for the jdbc user name, the way to do it is this way(using a ${propertyName:default} syntax) :

<property name="username" value="${jdbc.username:sa}"/>

or with Java Config:

..
..
@Value("${jdbc.username:sa}") private String dbUserName;

@Bean
public BasicDataSource dataSource() {
..
}


Second is the support for nested property resolution, for eg consider the following properties:
phase.properties file -
phase=qa
jdbc.username.qa=qasa
jdbc.username.dev=devsa

and using the "phase" property as part of another property in XML bean definition in this nested way:
<property name="username" value="${jdbc.username.${phase}}"/>

These options could be very useful for place holder based configuration.


Monday, January 14, 2013

Workaround for @ContextConfiguration restriction

One of the restrictions when using @ContextConfiguration to specify the location of Spring bean configurations for a Spring based JUnit test is that only one of either the locations attribute(or default value attribute) OR  classes attribute can be specified at a time.

Essentially the following will not run, as both classes and locations attribute is being specified here.

@WebAppConfiguration
@ContextConfiguration(classes=WebConfig.class, locations={"classpath:/META-INF/spring/applicationContext-security.xml", "classpath:/META-INF/spring/applicationContext.xml", "classpath:/META-INF/spring/applicationContext-jpa.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class MemberJsonControllerTest {
....

}


I am not completely sure why this restriction exists, but a workaround for this is to have an alternate application context where the java configuration and the locations based xml configuration is imported, and to use this new context for tests.

The simplest way is to not specify any attributes for @ContextConfiguration at all, this way the default behavior is to look for any static inner class annotated with @Configuration in the test class and import the other bean definition configurations into the @Configuration class this way:

@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class MemberJsonControllerTest {
....


 @Configuration
 @Import(WebConfig.class)
 @ImportResource({"classpath:/META-INF/spring/applicationContext-security.xml", 
      "classpath:/META-INF/spring/applicationContext.xml", 
      "classpath:/META-INF/spring/applicationContext-jpa.xml"})
 public static class ContextConfig{
  
 }
}

Tuesday, January 8, 2013

JUnit test method ordering

Junit until version 4.10 uses the order of test methods in a test class as returned by the reflection API as the order of test method execution - Class.getMethods(). To quote the Javadoc of getMethods() api:

The elements in the array returned are not sorted and are not in any particular order.

thus the order of test method execution in a test class is not predictable. This in a way is good as it encourages us as developers to write test methods which can stand on its own and to not depend on the order of test method execution.

With version 4.11 of Junit the order of test method execution is not so unpredictable anymore, by default the order though not specified will be deterministic for every run. The order can further be enforced by adding a new annotation @FixMethodOrder to the test class with the following values:

1. @FixMethodOrder(MethodSorters.DEFAULT) - deterministic order based on an internal comparator
2. @FixMethodOrder(MethodSorters.NAME_ASCENDING) - ascending order of method names
3. @FixMethodOrder(MethodSorters.JVM) - pre 4.11 way of depending on reflection based order

Consider the following test case:

public class ATest {
 @Test
 public void b_test_1() {
  System.out.println("b_test_1 called..");
 }

 @Test
 public void r_test_2() {
  System.out.println("r_test_2 called..");
 }

 @Test
 public void z_test_3() {
  System.out.println("z_test_3 called..");
 }


 @Test
 public void l_test_4() {
  System.out.println("l_test_4 called..");
 }
}
Pre 4.11 running this test prints the following in my machine

Running testorder.ATest
r_test_2 called..
z_test_3 called..
b_test_1 called..
l_test_4 called..

With NAME_ASCENDING:
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ATest

this is the output:

Running testorder.ATest
b_test_1 called..
l_test_4 called..
r_test_2 called..
z_test_3 called..


There is still no way to explicitly specify other custom sorting methods which is good as the purpose of providing a predictable order is just that - to make it predictable, not to use it to add dependencies between test methods.

Reference:
JUnit Wiki - https://github.com/KentBeck/junit/wiki/Test-execution-order

Friday, January 4, 2013

Spring MVC - Customizing RequestMappingHandlerMapping

When Spring MVC is configured using <mvc:annotation-driven/> in an xml bean definition file, internally a component called RequestMappingHandlerMapping gets registered with Spring MVC. This component or in general a HandlerMapping component is responsible for routing request URI's to handlers which are the controller methods annotated with @RequestMapping annotation.

There are two specific configurations in RequestMappingHandlerMapping that may be non-intuitive:

The first configuration is "useSuffixPatternMatch", which is if say a uri "/members" maps to method to return a list of entities, "/members.xyz" would map to the same handler method.

The second configuration is "useTrailingSlashMatch" which is that "/members" and "/members/" would map to the same handler method.

If these two behavior need to be modified, the way to do that is to configure the RequestMappingHandlerMapping.

If <mvc:annotation-driven/> has been used to define the RequestMappingHandlerMapping, then the unwieldy way to go about it would be to remove <mvc:annotation-driven/> and instead to configure Spring MVC by expanding out the components that get registered by the custom namespace handler handling the "mvc" namespace, which is something along these lines(this is not complete and is being shown just to demonstrate the complexity of the configuration):

<bean name="handlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
 <property name="webBindingInitializer">
  <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
   <property name="conversionService" ref="conversionService"></property>
   <property name="validator">
    <bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
   </property>
  </bean>
 </property>
 <property name="messageConverters">
  <list>
   <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
   <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
   <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
   <bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
   <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
   <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
   <bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
  </list>
 </property>
</bean>

<bean name="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
 <property name="useTrailingSlashMatch" value="false"></property>
</bean> 

This is definitely not a good way to go about changing the configuration. Instead if faced with the need to configure RequestMappingHandlerMapping a far better approach is to move a part or the entire web-mvc configuration to Java @Configuration this way:

package mvcsample.spring;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;



@Configuration
public class WebConfig extends WebMvcConfigurationSupport{
 @Bean
 public RequestMappingHandlerMapping requestMappingHandlerMapping() {
  RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
  handlerMapping.setUseSuffixPatternMatch(false);
  handlerMapping.setUseTrailingSlashMatch(false);
  return handlerMapping;
 } 
}

and to import this configuration into the rest of the configuration xml(there are other documented ways also):

<bean class="mvcsample.spring.WebConfig"/>

<!-- 
<mvc:annotation-driven>
</mvc:annotation-driven> 
-->

@Configuration thus provides a simpler mechanism to configure the components in Spring MVC and migration from xml based configuration to Java configuration is highly recommended to simplify the configuration and manage customizations.