It’s been some time since I last wrote an article here, but after having found this in my InfoQ feed today, I felt the urge to share and discuss my thoughts.

Let me summarize the article for those of you who haven’t yet had the opportunity to read it. To put it in a nutshell, SpringSource is about to or already released as beta their own Java application container based on Spring, Tomcat and OSGi. I’m not actually surprised by this move as there have been a lot of hints pointing into this direction in the past, the acquisition of Covalent probably being the most prominent one.

Anyway, I personally find it exciting news as, if the bundle delivers what is promised in the article, this might mean that there will be a “natural” application container choice for Spring-based projects. Having seen a lot of high-profile app-server installations in the field that were used as mere servlet containers (but with a hefty administration and footprint overhead), I consider this a good thing. Add the SpringSource support offer and you will have a much easier time arguing in favour of Tomcat as a lightweight alternative.
Vice versa, it might be easier to argue in favour of the Spring programming model once you can toss in a fully supported and integrated runtime environment for it too.

I hope I can get my hands on a beta release soon to play around with the OSGi deployment model (and to see whether I can bully Maven into building PAR archives for me). In the meantime I’d really like to hear what you think about the announcement.

While preparing a presentation on test-driven development, I had the chance to play around with the new configuration annotations. Despite my initial aversion against "polluting" my domain classes, the experience was rather pleasant.
The trivial three class example I prepared will hardly be usable as proof of concept for real-life development with Spring 2.5 configuration annotations. Nevertheless I’m rather sure that those annotations will save valuable time during prototyping and early development phases. So without further ado, here’s what the code looks like…

I started with the following integration test:

package com.springify.example;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/com/springify/example/applicationContext.xml"})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
public class UserServiceIntegrationTest {

    @Autowired
    private UserService userService;

    @Test
    public void addUserAndLogin() {
        userService.registerUser("admin", "password");
        assertThat(userService.login("admin", "password"), is(true));
    }    

}



Please note that I only had to use the @TestExecutionListeners annotation because for the purpose of demonstrating TDD I felt no urge to dive into the complexities of transaction management. While this is already pretty concise considering I’m setting up a complete environment here, just have a look at the bean definition:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd"
>

    <context:component-scan base-package="com.springify"/>
    <context:annotation-config/>

</beans>



Not much in there, actually. But it has to be somewhere, doesn’t it? Maybe…

package com.springify.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DefaultUserService implements UserService {

    public boolean login(String userName, String password) {
        throw new UnsupportedOperationException("TODO");
    }

    public void registerUser(String userName, String password) {
        throw new UnsupportedOperationException("TODO");
    }

    @Autowired
    public void injectUserRepository(UserRepository userRepository) {
        // TODO
    }
}



and …

package com.springify.example;

import org.springframework.stereotype.Repository;

@Repository
public class DefaultUserRepository implements UserRepository {

    public User getUser(String username, String password) throws LoginFailedException {
        throw new UnsupportedOperationException("TODO");
    }

    public void addUser(User user, String password) {
        throw new UnsupportedOperationException("TODO");
    }
}



Yes, that looks like it could do the trick. Even if the amount of configuration saved by this approach might not be huge for the few beans used in this example, it still felt a lot more natural and … dare I say… agile, because I was able to concentrate on driving the design with my tests instead of wiring changing bean graphs together.

As a side note, it was fun to use the new Spring TestContext with my favorite acceptance testing framework Concordion. For quick results, all you actually have to do is copy the code from org.concordion.integration.junit3.ConcordionTestCase into a base class:

package com.springify.integration.concordion;

import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.junit.Test;
import org.concordion.Concordion;
import org.concordion.api.ResultSummary;
import org.concordion.internal.ConcordionBuilder;

import java.io.IOException;

public abstract class AbstractSpringConcordionTest extends AbstractJUnit4SpringContextTests {

    @Test
    public void concordion() throws IOException {
        Concordion concordion = new ConcordionBuilder().build();
        ResultSummary resultSummary = concordion.process(this);
        System.out.print("Successes: " + resultSummary.getSuccessCount());
        System.out.print(", Failures: " + resultSummary.getFailureCount());
        if (resultSummary.hasExceptions()) {
            System.out.print(", Exceptions: " + resultSummary.getExceptionCount());
        }
        System.out.println("\n");
        resultSummary.assertIsSatisfied();
    }

}
 



After that, you can create your dependency-injected fixtures like this:

package com.springify.example;

import com.springify.integration.concordion.AbstractSpringConcordionTest;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/com/springify/example/applicationContext.xml"})
public class LoginTest extends AbstractSpringConcordionTest {

    @Autowired
    private UserService userService;

    public void addUser(String userName, String password) {
        userService.registerUser(userName, password);
    }

    public String loginWith(String userName, String password) {
        return (userService.login(userName, password) ? "was successful" : "failed");
    }

}
 

It’s finally there, and with quite a handful of impressive new features, too. I especially like the new configuration options and the way you can actually do something vaguely similar to rapid prototyping even in the Java Enterprise world now. In my humble opinion, annotation-based controllers go a long way towards establishing Spring MVC as a viable web framework alternative. Being a huge fan of Stripes’ “configuration-less” approach, I see some convergence here.

I also appreciate the efford that has gone into obtaining WebSphere certification for Spring 2.5, as lack of server vendor support can - at least with the clients I usually work for - still be an exclusion criterion.

So, to put it in a nutshell: Congratulations on this release to everybody at SpringSource and thanks for the awesome job you’re doing there.

As you will most probably have noticed, I haven’t written all that much recently - nothing at all, actually. This is mainly due to the fact that I have been exceptionally busy with things entirely out of Spring’s scope (yes, they exist). Please give a warm welcome to my son, Leo Wloka, who has been born on the 21st of October. As you can imagine, he and his mom will keep me rather busy for a while.

Nevertheless, I will, as I play around with the recent Spring 2.5 Release Candidate, blog about all noteworthy experiences. In the meantime, my german readers might enjoy reading the Spring Praxishandbuch, which I had the pleasure of writing the JMS chapter for.

This is your host Nils Wloka. Let me welcome you to my humble little Spring blog, which, after months of hesitance - and struggle against various pieces of blog software - I am happy to roll out today. Time permitting, I will periodically entertain you with posts about my various ideas and experiences regarding JEE development with the Spring Framework.

Until then, I would like to point any German readers to the articles I have written for the Advanced Spring series published in the German Java Magazin. Feel free to leave your comments and questions here.