Friday, September 28, 2012

Scala Iteration - step by 2*previous loop index

I had a basic Scala related question about how to replicate the following Java loop in Scala:

for (int i=1;i<100000;i=2*i){
    System.out.println(i);
}

I knew one way to go about doing this using a recursive loop this way:

def loopByTwiceBefore(from:Int, to:Int)(f:Int=>Unit):Unit = {
    if (from<to){
        f(from)
        loopByTwiceBefore(from*2, to)(f);
    }
}
loopByTwiceBefore(1, 100000)(println)

I asked this question in StackOverflow and immediately got back two better ways of doing this:

for (n <- Iterator.iterate(1)(2*).takeWhile(100000>)) println(n)

OR

Iterator.iterate(1)(_*2).takeWhile(_ < 100000) foreach {println(_)}

and the link to the Iterator companion object at the Scala API site for more information

Sunday, September 23, 2012

Spring Testing Support and Context caching

Spring provides a comprehensive support for unit and integration testing - through annotations to load up a Spring application context, integrate with unit testing frameworks like JUnit and TestNG. Since loading up a large application context for every test takes time, Spring intelligently caches the application context for a test suite - typically when we execute tests for a project, say through ant or maven, a suite is created encompassing all the tests in the project.

There are a few points to note with caching which is what I intend to cover here, this is not likely to be comprehensive but is based on some situations which I have encountered:

1. Caching is based on the locations of Spring application context files

Consider a sample Spring configuration file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
 <bean id="user1"  class="org.bk.lmt.domain.TaskUser" p:username="user1" p:fullname="testUser1" />
 <bean name="user2" class="org.bk.lmt.domain.TaskUser" p:username="user2" p:fullname="testUser" />
 
 <bean class="org.bk.contextcaching.DelayBean"/>
 
</beans>


And a sample test to load up this context file and verify something.:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "contexttest.xml" })
public class Test1 {
 @Autowired Map<String, TaskUser> usersMap;

 @Test
 public void testGetAUser() {
  TaskUser user = usersMap.get("user1");
  assertThat(user.getFullname(), is("testUser1"));
 }
}

I have deliberately added in an additional bean(DelayBean) which takes about 2 seconds to instantiate, to simulate Spring Application Contexts which are slow to load up.

If I now run a small test suite with two tests, both using the same application context, the behavior is that the first test takes about 2 seconds to run through, but the second test runs through quickly because of context caching.

If there were a third test using a different application context, this test would again take time to run through as the new application context has to be loaded up:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "contexttest2.xml" })
public class Test3 {
...
}



2. Caching of application contexts respects the active profile under which the test is run - essentially the profile is also part of the internal key that Spring uses to cache the context, so if two tests use the exact same application context, but different profiles are active for each of the tests, then the cached application context will not be used for the second test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "contexttest.xml" })
@ActiveProfiles("dev1")
public class Test1 {
....


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "contexttest.xml" })
@ActiveProfiles("dev2")
public class Test2 {
....




3. Caching of application context applies even with the new @Configuration style of defining a application context and using it in tests:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={TestConfiguration.class})
public class Test1 {
...


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={TestConfiguration.class})
public class Test2 {
....



One implication of caching is that if a test class modifies the state of a bean, then another class in the test suite which uses the cached application context will end up seeing the modified bean instead of the bean the way it was defined in the application context:

For eg. consider two tests, both of which modify a bean in the context, but are asserting on a state the way it is defined in the application context - Here one of the tests would end up failing(based on the order in which Junit executes the tests):

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={TestConfiguration.class})
public class Test1 {
 @Autowired Map<String, TaskUser> usersMap;


 @Test
 public void testGetAUser1() {
  TaskUser user = usersMap.get("user1");
  assertThat(user.getFullname(), is("testUser1"));
  user.setFullname("New Name");
 }
 
 @Test
 public void testGetAUser2() {
  TaskUser user = usersMap.get("user1");
  assertThat(user.getFullname(), is("testUser1"));
  user.setFullname("New Name");
 }
}


The fix is to instruct Spring test support that the application context is now dirty and needs to be reloaded for other tests, and this is done with @DirtiesContext annotation which can specified at the test class level or test method level.

@Test
@DirtiesContext
public void testGetAUser2() {
...



Tuesday, September 11, 2012

Java Annotations - Retention

Consider a Java annotation:


public @interface AnAnnotaton {

}

A class with this annotation applied on it:

@AnAnnotaton
class AnAnnotatedClass{
 
}

And a test which checks if this annotation is present on a class:

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

import java.lang.annotation.Annotation;
import org.junit.Test;

public class AnAnnotationTest {
 
 
 @Test
 public void testAnAnnotation() throws Exception {
  AnAnnotatedClass anAnnotatedClass = new AnAnnotatedClass();
  Annotation[] annotationsOnClass = anAnnotatedClass.getClass().getAnnotations();
  assertThat(annotationsOnClass.length, is(1));
 }

}

Sounds reasonable right, one would expect the above test to pass since the class does have an annotation of AnAnnotation on it.

But, this test fails, and the reason is...


a missing meta annotation(@Retention) on the annotation which indicates how long the annotation is to be retained, if the annotation above is changed as follows, the test would work as expected.

@Retention(RetentionPolicy.RUNTIME)
public @interface AnAnnotaton {

}


So what does @Retention do - to quote from the Javadoc:


Indicates how long annotations with the annotated type are to be retained. If no Retention annotation is present on an annotation type declaration, the retention policy defaults to RetentionPolicy.CLASS

there are three different retention policies:
1. SOURCE - where the annotations are removed by the compiler
2. CLASS - Annotations are present in the bytecode, but are not present at runtime and hence not available when trying to reflectively determine if a class has the annotation.
3. RUNTIME - Annotations are retained in the byte code and is available at runtime and hence can be reflectively found on a class.

This is the reason why when the annotation definition was changed to include @Retention(RetentionPolicy.RUNTIME), the test now runs through.

Something basic, but easy to miss out.

Monday, September 3, 2012

Ways to wire dependencies for an object outside of a Spring Container

There are a few interesting ways of setting the properties and dependencies of an object instantiated outside of a Spring container.

Use Cases

To start with, why would we need to do inject in dependencies outside of a Spring container - I am aware of three use cases where I have instantiated objects outside of the Spring container and needed to inject in dependencies.

Consider first the case of a series of tasks executed using a Spring TaskExecutor, the tasks highlighted below are instantiated outside of a Spring container:

List<Callable<ReportPart>> tasks = new ArrayList<Callable<ReportPart>>();
        List<ReportRequestPart> reportRequestParts = reportRequest.getRequestParts();
        for (ReportRequestPart reportRequestPart : reportRequestParts) {
            tasks.add(new ReportPartRequestCallable(reportRequestPart, reportPartGenerator));
        }

        List<Future<ReportPart>> responseForReportPartList;
        List<ReportPart> reportParts = new ArrayList<ReportPart>();
        try {
            responseForReportPartList = executors.invokeAll(tasks);
            for (Future<ReportPart> reportPartFuture : responseForReportPartList) {
                reportParts.add(reportPartFuture.get());
            }

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw new RuntimeException(e);
        }

public class ReportPartRequestCallable implements Callable<ReportPart> {
 private final ReportRequestPart reportRequestPart;
 private final ReportPartGenerator reportPartGenerator;

 public ReportPartRequestCallable(ReportRequestPart reportRequestPart, ReportPartGenerator reportPartGenerator) {
     this.reportRequestPart = reportRequestPart;
     this.reportPartGenerator = reportPartGenerator;
    }

 @Override
    public ReportPart call() {
    return this.reportPartGenerator.generateReportPart(reportRequestPart);
    } 
}

The second use case is with ActiveRecord pattern say with the samples that come with Spring Roo, consider the following method where a Pet class needs to persist itself and needs an entity manager to do this:
@Transactional
    public void Pet.persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.persist(this);
    }

The third use case is for a tag library which is instantiated by a web container, but needs some dependencies from Spring.


Solutions

1. The first approach is actually simple, to provide the dependencies at the point of object instantiation, through constructors or setters. This is what I have used with the first use case where the task has two dependencies which are being provided by the service instantiating the task:

tasks.add(new ReportPartRequestCallable(reportRequestPart, reportPartGenerator));


2. The second approach is a to create a factory that is aware of the Spring container, declaring the beans that are required with a prototype scope within the container and getting the beans by a getBeans method of the application context,

Declaring the bean as a prototype scoped bean:
    <bean name="reportPartRequestCallable" class="org.bk.sisample.taskexecutor.ReportPartRequestCallable" scope="prototype">
     <property name="reportPartGenerator" ref="reportPartGenerator"></property>
    </bean>
    
    <bean name="reportPartRequestCallableFactory" class="org.bk.sisample.taskexecutor.ReportPartRequestCallableFactory"/>

and the factory serving out the bean:
public class ReportPartRequestCallableFactory implements ApplicationContextAware{
 private ApplicationContext applicationContext;

 @Override
 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = applicationContext;
 }
 
 public ReportPartRequestCallable getReportPartRequestCallable(){
  return this.applicationContext.getBean("reportPartRequestCallable", ReportPartRequestCallable.class);
 }
}


3.  The third approach is a variation of the above approach is to instantiate the bean and then inject dependencies using AutoWireCapableBeanFactory.autowireBean(instance), this way:
public class ReportPartRequestCallableFactory implements ApplicationContextAware{
 private GenericApplicationContext applicationContext;

 @Override
 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  this.applicationContext = (GenericApplicationContext)applicationContext;
 }
 
 public ReportPartRequestCallable getReportPartRequestCallable(){
  ReportPartRequestCallable reportPartRequestCallable = new ReportPartRequestCallable();
  applicationContext.getBeanFactory().autowireBean(reportPartRequestCallable);
  return reportPartRequestCallable;
 }
}



4.  The fourth approach is using @Configurable, the catch though is that it requires AspectJ to work. Spring essentially enhances the constructor of the class to inject in the dependencies along the lines of what is being explicitly done in the third approach above:

import org.springframework.beans.factory.annotation.Configurable;

@Configurable("reportPartRequestCallable")
public class ReportPartRequestCallable implements Callable<ReportPart> {
    private ReportRequestPart reportRequestPart;
    @Autowired private ReportPartGenerator reportPartGenerator;

    public ReportPartRequestCallable() {
    }

    @Override
    public ReportPart call() {
       return this.reportPartGenerator.generateReportPart(reportRequestPart);
    }

    public void setReportRequestPart(ReportRequestPart reportRequestPart) {
        this.reportRequestPart = reportRequestPart;
    }

    public void setReportPartGenerator(ReportPartGenerator reportPartGenerator) {
        this.reportPartGenerator = reportPartGenerator;
    }
}

The following is also required to configure the Aspect responsible for @Configurable weaving:
<context:spring-configured/>

With these changes in place, any dependency for a class annotated with @Configurable is handled by Spring even if the construction is done completely outside of the container:

    @Override
    public Report generateReport(ReportRequest reportRequest) {
        List<Callable<ReportPart>> tasks = new ArrayList<Callable<ReportPart>>();
        List<ReportRequestPart> reportRequestParts = reportRequest.getRequestParts();
        for (ReportRequestPart reportRequestPart : reportRequestParts) {
            ReportPartRequestCallable reportPartRequestCallable = new ReportPartRequestCallable(); 
            reportPartRequestCallable.setReportRequestPart(reportRequestPart);
            tasks.add(reportPartRequestCallable);
        }
    .......


Conclusion
All of the above approaches are effective with injecting in dependencies in objects which are instantiated outside of a container. I personally prefer to use Approach 4 (using @Configurable) in cases where AspectJ support is available, else I would go with Approach 2(hiding behind a factory and using a prototype bean).