January 11, 2011

Spring framework without XML... At all!

First, there was EJB 2.1 with countless XML files all over. It won't be such a big exaggeration to say that for every line of business code you had to create at least 10 lines of framework code and two pages of XML. Local and remote interfaces, manual JNDI lookup, triply nested try-catches, checked RemoteExceptions everywhere... this was enterprise. There were even tools to generate some of this boilerplate automatically.

Then couple of guys came and created Spring framework. After being forced to cast by obscure PortableRemoteObject.narrow() it was like taking a deep breath of fresh air, like writing poetry after working in coal mine. Time went by (BTW do you remember how many years ago was the last major JRE release?) and Sun learnt their lesson. EJB 3.0 was even simpler compared to Spring, XML-free, annotations, dependency injection. 3.1 was another great step toward simplicity, being more and more often compared to Spring. Logically current state of the art EJB specification might be considered as a subset of what Spring offers, I am actually surprised why there is no EJB spec. implementation in plain Spring (oh, wait...), considering its out-of-the-box support for JPA 1.0/2.0, JSR-250, JSR-330, JAX-WS/RS compatible solutions and others. But even though, Spring framework is nowadays perceived as a slow, heavyweight and hard to maintain, mainly due to reliance on XML descriptors. Once simple, now Spring is a whipping boy in the JEE framework battle.

I don't like politics, I won't defend my beloved framework writing lengthy essays. Instead I will take simple, but not trivial Spring application and quickly rewrite it so that it won't use XML. Not reduce the amount of XML, not leave only few untouchable lines. No XML - at all.

For the purposes of this article I created very simple Spring web application (base version under xml branch, final on master on my GitHub account) using JDBC, JMS and JMX, just not to make things trivial. Every change I made to the source code will be reflected in a separate commit to this repository. Step by step I will be removing XML configuration until there will be no Spring XML left. This is where we start:

<?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:tx="http://www.springframework.org/schema/tx"
       xmlns:amq="http://activemq.apache.org/schema/core"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
             http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.4.2.xsd
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:mbean-export />

    <bean id="fooService" class="com.blogspot.nurkiewicz.FooService">
        <property name="jmsOperations" ref="jmsTemplate" />
    </bean>

    <bean id="fooRequestProcessor" class="com.blogspot.nurkiewicz.FooRequestProcessor">
        <property name="fooRepository" ref="fooRepository" />
    </bean>

    <bean id="fooRepository" class="com.blogspot.nurkiewicz.FooRepository" init-method="init">
        <property name="jdbcOperations" ref="jdbcTemplate" />
    </bean>


    <!-- JDBC -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:~/workspace/h2/spring-noxmal;DB_CLOSE_ON_EXIT=FALSE;TRACE_LEVEL_FILE=4;AUTO_SERVER=TRUE" />
        <property name="username" value="sa" />
        <property name="password" value="" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg ref="dataSource" />
    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <constructor-arg ref="dataSource" />
    </bean>

    <tx:annotation-driven />


    <!-- JMS -->
    <bean id="jmsConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
        <constructor-arg>
            <bean class="org.apache.activemq.ActiveMQConnectionFactory">
                <property name="brokerURL" value="tcp://localhost:61616" />
            </bean>
        </constructor-arg>
    </bean>

    <amq:queue id="requestsQueue" physicalName="requests" />

    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <constructor-arg ref="jmsConnectionFactory" />
        <property name="defaultDestination" ref="requestsQueue" />
    </bean>

    <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="jmsConnectionFactory" />
        <property name="destination" ref="requestsQueue" />
        <property name="sessionTransacted" value="true"/>
        <property name="concurrentConsumers" value="5"/>
        <property name="messageListener">
            <bean class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
                <constructor-arg ref="fooRequestProcessor" />
                <property name="defaultListenerMethod" value="process"/>
            </bean>
        </property>
    </bean>

</beans>


January 8, 2011

Activiti processes and executions explained

I was interested in Activiti process engine long before it reached its first stable 5.0 version. Now, when 5.1 was released, I decided to play a bit with this framework, especially paying attention to Spring and JUnit support. But one of the first impediments encountered was the difference between process instance and execution, as well as between sub process and call activity. I am hoping after reading this article you won't encounter the same problems when starting with Activiti.

As you know, even a monkey can learn a new Java framework after reading documentation, but the real fun comes when you meet the technology by studying its source code (often tracking bugs and looking for solutions). And I must admit that Activiti code-base was a pleasure to read, nicely structured and designed. For some reason it is not deployed to Alfresco's repository, so to take full advantage of your BPMN journey, start by:

svn co http://svn.codehaus.org/activiti/activiti/tags/activiti-5.1
cd activiti-5.1
mvn install source:jar -DskipTests -Pdistro


OK, for starters take a look at this process: