Archive for the ‘Jan's Blog’ Category

Spring London User Group

Wednesday, June 18th, 2008

As you all know, Aleksa and I presented a case study at the first Spring London User Group meeting (I think we should call it SLUG); we now give you video of our presentation.
Jan and Aleksa presenting

Declarative caching and Hibernate

Wednesday, June 18th, 2008

We successfully use the Caching SpringModule. In short, this allows us to declaratively cache values returned from method calls. The Caching module supports many different cache implementations; we have picked OsCache for development. To get started, let’s take a look at the MemberService and its implementation.

public interface MemberService {
        @Nullable
	Member complicatedLookup(@NotNull ComplexArgument argument);
}

public class DefaultMemberService implements MemberService {
        @Nullable
        @Cacheable(modelId = "Member")
        public Member complicatedLookup(@NotNull ComplexArgument argument) {
                // some complex stuff
        }
}


This code works perfectly well: when you call the DefaultMemberService.complicatedLookup(...) method more than once with the same (read equal(Object)) ComplexArgument object, the caching framework intercepts the call in and only the first call will go to do the // some complex stuff.
The problem is when you return an object from a Hibernate DAO call and that object is enhanced by CGLIB. Now the cache has a reference to an object that references an invalid Session.
We found this when our integration tests worked fine on their own, but started failing when we ran them as part of our automatic build. The prospect of going through every possible code path to find out if there is a cached CGLIB-enhanced object was daunting. Luckily, Spring AOP was quick to rescue. We wrote a simple little aspect that checks that any method with the @Cacheable annotation does not return a CGLIB-enahanced object.

@Aspect
public class CacheManagerAspect {

    @AfterReturning(pointcut =
            "@annotation(org.springmodules.cache.annotations.Cacheable)",
                returning = "ret",
                argNames = "jp, ret")
    public void indicateLazilyLoaded(JoinPoint jp, Object ret) throws Exception {
        checkNotCGLIBEnhanced(jp, ret);
    }

    private void checkNotCGLIBEnhanced(JoinPoint jp, Object o)
        throws IllegalAccessException, InvocationTargetException {
        if (o == null) return;
        String name = o.getClass().getName();
        if (!name.startsWith("uk.co.package")) return;
        if (name.contains("$$Enhancer"))
                 throw new RuntimeException(
                        "You cannot cache a CGLIB-Enhanced object at " + jp);

        PropertyDescriptor[] descriptors =
                 BeanUtils.getPropertyDescriptors(o.getClass());
        for (PropertyDescriptor descriptor : descriptors) {
            Object value = descriptor.getReadMethod().invoke(o);
            checkNotCGLIBEnhanced(jp, value);
        }
    }

}


Simple, but powerful stuff from SpringModules and Spring AOP!

Area51

Monday, June 2nd, 2008

We’ve now ordered a new sub-domain area51.devcake.co.uk. As you can guess from its name, we will publish all experimental code there. In fact, this will give you a read-only access to a subset of our subversion repository. You will be able to download any code that we are thinking about donating to the community, but is not yet up to scratch. The code will work, but it may not be completely documented and it may not have complete unit and integration test coverage.
The first project to appear in area 51 will be the Workflow SpringModule, which we first introduced on Friday at the Spring User Group meeting in London.

Workflow SpringModule

Saturday, May 31st, 2008

I have introduced the Workflow SpringModule at Friday’s Spring User Group meeting in London; I was very pleased to see that people are interested in the module. Unfortunately, it is not available in the main SpringModules project yet, but I will make it available from our subversion repository tomorrow or on Monday.
I look forward to hearing any comments from the early adopters; depending on the feedback, I will include a more detailed discussion of the workflow module in my Spring One talk on Thursday 12th June.

RDBMS

Thursday, May 8th, 2008

Here’s another in the series of our internal talks, this time on our old friends, the relational database management systems — also known under their misleading alias — databases.
In the talk, I’ve explained some of the concepts of relational algebra and shown that if all our tables were indeed relations, the RDBMSs could do a lot of optimisations. For further reading, I recommend an excellent book by C. J. Date Database in Depth — Relational Theory for Practitioners.
To cut a potentially long entry short, download the presentation as PDF.

Service Orchestration

Wednesday, March 26th, 2008

We have the first version of the SO module. We can define flows, states and transitions. If this were all we did, it would make it a vanilla (Cake-vanilla, if you’ll pardon the pun) workflow engine.
We have taken an innovative approach to the configuration of the flows. Just like any other workflow engine, we use the concept of FlowDefinitions with many StateDefinitions with many TransitionDefinitions. Using this structure, we can create a directed graph with cycles (flow) with states as its vertices and transitions as its edges. Simple, eh?
You can obviously manually create the definition beans, but you can use annotation-based configuration. Take this code, for example:


@Flow
public class MainFlow {
}

@State(start = true)
public class StartState {

    @Transition
    @Transactional
    public void one() {
    }

    @Transition(to = “end”)
    public void end() {
    }
}

@State(end = true)
public class EndState {

    @Transition
    public void one() {
    }

    @Transition(to = “start”)
    public void restart(@TransitionArgument int i) {
    }
}

Without giving a detailed explanation, you can follow the annotation and infer that we have a flow with two states (start and end); each state has two transitions. To use this flow, we can use the FlowSession like so:


// instantiate flow with id “main”
FlowInstance instance = flowSession.instantiate(”main”); 

// calls StartState.one() and stays in the start state
instance.performTransition(”one”); 

// calls StartState.end() and transitions to end state
instance.performTransition(”end”); 

// calls EndState.restart(5) and transitions to start state
instance.performTransition(”restart”, 5);
…

Now, you can ask where we got the names “main”, “one”, “end” and others; I’m sure you can see that the MainFlow class would be the flow with id “main”, but we never said so explicitly in the code. The BeanPostProcessor uses naming strategies that take the ids explicitly set in the annotations or, if the annotation does not have the id set, it takes the class name or the bean name as the identity of the flow, state or transition.
Also, you may notice that the states somehow get attached to the main flow, even though we never defined this. Again, there is a bit of “intelligence” in the module that automatically registers a state with a flow even if no flow id is set if there is only one flow. In more complex applications (ones that use more than one flow), you must explicitly set the flowId value in the @State annotation.
We are going to put much more work into this module, but we can confidently state that the module is an exciting piece of code. The design of the module will allow us to use service orchestration language in the transitions (take a look at the TransitionAction interface and its implementations for a hint of possible solution).

Spring Modules

Wednesday, March 19th, 2008

We have begun implementation of two new exciting Spring Modules! The first one will be the Service Orchestration module and the second one will be Spring AJAX

Service Orchestration

The SO module will allow the developers to create a workflow-style structure, where the transitions carry business logic. In the transitions — I’m sure you’ll forgive me for the slightly non-technical description — you will be able to call any number of services; naturally, the transition will be able to participate in a JTA transaction.

Spring AJAX

This is a buzz-word like no other, but it is still very clumsy to create rich applications using the Spring Framework. We propose to create a module that will allow declarative AJAX handling code. The handling code will work with AjaxSessions and JsonViews by default, but there will be nothing stopping you from creating much more complex AJAX handling structures. Along with the Java-side support, we will give you JSP tag libraries to handle all mundane AJAX code.

Mockery

Thursday, March 6th, 2008

As a follow-up of my previous JMock post, I give you the internal presentation we held at Cake. Download it here.

Unit testing

Saturday, February 23rd, 2008

Mockery is a new JMock class. It allows you to create mock implementations of your interfaces in your unit tests.

In the days before Mockery, you could still use JMock’s Mock class and then use human-readable style of configuring the expectations. For example, to mock the Sender interface and its send(String s) method, you’d write

Mock sender = new Mock(Sender.class);
PostOffice postOffice = new PostOffice();
postOffice.setSender((Sender)sender.proxy());

sender.expects(once()).method(”send”).with(eq(”Hello”)).isVoid();
postOffice.post(”Hello”);

Now, assuming the PostOffice.post(String s) uses the Sender implementation to ultimately send the message, this test would work. However, if you refactored the Sender.send(String s) method, your IDE would not be able to refactor the JMock expectation.

Enter Mockery

The same code using JMock’s new Mockery class would look like this:

Mockery context = new Mockery();
final PostOffice postOffice = new PostOffice();
final Sender sender = context.mock(Sender.class);
postOffice.setSender(sender);

final String message = “Hello”;
context.checking(new Expectations() { {
    one(sender).send(message);
} });

postOffice.post(message);

Here you can see that the test still reads very well, but most IDEs will automatically refactor the unit test expectations whenever you refactor the Sender interface. Also notice that you do not need to explicitly state with(eq(”Hello”)) or with(eq(message)). Instead, you “call” the mocked method directly, passing it the values to be checked.

There is a lot more to Mockery, we recommend that you give it a fair try in your unit tests.

Clean & tidy

Saturday, February 23rd, 2008

I am sure you remember your mother telling you to clean your room when you were little. This usually involved taking out the hoover (or the vacuum cleaner for the Yahoos) and getting on with the job.

Fast forward a few years and switch to PostgreSQL. It is very good idea to turn on the auto_vacuum parameter or vacuum the tables manually every few days. If you do not do that, you may end up with a database with just a few tens of thousands of rows occupying over 4.5 GB on the hard drive.