SignsoftintelliBO

Signsoft intelliBO in a nutshell

The first edition of the "Signsoft intelliBO in a nutshell" series will provide you information on how to integrate Signsoft intelliBO into the Springframework, version 2.

The Springframework [1] is a lightweight application framework with a considerable influence on the architecture of the application to be built. It is positioned clearly against the heavyweight and code-invasive Java J2EE application server. By using Spring, the application code contains less dependencies on the underlying container, testability of the application code is considerably enhanced and the time efforts of deployment will be the same as for an ordinary Java application. And what is most important, you get the same possibilities of declarative resource and transaction management as with an application server.

These features are realized by these fundamental mechanisms:

The essence of the Springframework is the configuration of JavaBeans in XML-based configuration files. In these configuration files all JavaBeans are defined with their dependencies between them. Here also transaction demarcation and other cross cutting concerns are to be defined.

As the PersistenceManagerFactory is a perfectly valid JavaBean, it can be used in the Spring configuration without much ado. In our sample the Spring configuration is stored in file called spring-beans.xml. However, the file name can be chosen freely.

<bean id="iboPMF"  class="com.signsoft.ibo.client.PersistenceManagerFactoryImpl"  destroy-method="close">
  <property name="connectionInfoName" value="com.signsoft.ibo.dbsupport.h2.H2DatabaseInfo" />
  <property name="logging" value="true" />
  <property name="enableSharedCache" value="false" />
</bean>

Looking at the configuration of the PersistenceManagerFactory, you will note that there is no data source defined yet. We will add a javax.sql.DataSource to the Spring configuration and inject that DataSource into the PersistenceManagerFactory.

<bean id="dataSource"  class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="org.h2.Driver" />
  <property name="url" value="jdbc:h2:database/data;LOCK_MODE=3" />
  <property name="username" value="" />
  <property name="password" value="" />
</bean>

<bean id="iboPMF" class="com.signsoft.ibo.client.PersistenceManagerFactoryImpl" destroy-method="close">
  ...
  <property name="connectionFactory" ref="dataSource" />
  ...
</bean>

With the aid of Spring's ApplicationContext, we can obtain a reference to the PersistenceManagerFactory in our application. This procedure resembles a lot the JNDI look-up mechanism in EJB containers. Here you will also always work with the same resource. But, there is still a little hitch: With this Spring configuration you yourself will be responsible for transaction demarcation.

ApplicationContext appContext = new ClassPathXmlApplicationContext("/spring-beans.xml");
PersistenceManagerFactory pmf = (PersistenceManagerFactory) appContext
        .getBean("iboPMF");

PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
//...
pm.currentTransaction().commit();

If you prefer to leave transaction demarcation to Spring, some more configuration is required. For Spring to be able to use AOP for transaction handling, you have to define a Java interface with all the methods that are to be visible to AOP. This interface is owed to the Java reflection proxy mechanism [3] by which Spring is establishing the illusion of AOP.

package com.intellibo.sample.spring2;

public interface PersonService {

  public void sampleInsert();

  public void sampleQuery();

  public void sampleUpdate();

  public void sampleDelete();

}

It will suffice if our service class implements this interface. There is no need to mention it in the Spring configuration in this sample. The service class that implements this interface is called com.intellibo.sample.spring2.Main in our example.

Declaration of transaction demarcation is done this way:

<aop:config>
  <aop:advisor
    pointcut="execution(* com.intellibo.sample.spring2.Main.sample*(..))"
    advice-ref="txAdvice" />
</aop:config>

<tx:advice id="txAdvice" transaction-manager="jdoTXManager">
  <tx:attributes>
    <tx:method name="sample*" propagation="REQUIRED" />
    <tx:method name="sampleQuery*" propagation="SUPPORTS" />
  </tx:attributes>
</tx:advice>

First, a pointcut is defined which comprises all methods in com.intellibo.sample.spring2.Main that start with sample, e.g. sampleUpdate, sampleInsert, ... . For this pointcut an advice called txAdvice is defined. By this, we declare that when executing method sampleQuery an existing transaction is used but no new transcation will be opened. For all other methods starting with sample, a new transaction is begun or an existing one is used. Leaving these methods, the transaction will be committed unless there is a surrounding transaction still open.

The method sampleInsert of class com.intellibo.sample.spring2.Main could look this way:

/**
 * creates a person and makes it persistent
 */
public void sampleInsert() {
  // get persistence manager
  PersistenceManager pm = pmf.getPersistenceManager();
  // create a person
  Person p = new Person();
  p.setLastName("Holmes");
  p.setFirstName("Sherlock");
  p.setAge(45);
  System.out.println("creating " + p);
  // make this person persistent
  pm.makePersistent(p);
  pm.close();
}

Here you can clearly see that no transaction is begun or committed explicitly. Even there is a method call to close the PersistenceManager when leaving the method. The code of an EJB SessionBean would exactly look the same. But how can all this work outside of an EJB container?

Before we can answer this question, two other questions are still to be answered:

  1. What is the transaction manager jdoTXManager in the above-stated snipped of Spring's configuration?
  2. Where is the variable pmf in the methode sampleInsert from?

To the first question: Spring, contrary to EJB containers, does not have its own transaction monitor. Therefore, it depends on the transaction facilities of the underlying data access frameworks. To provide an unified view on these transaction facilities, Spring ships with a bundle of framework specific facades for transaction managers. To take advantage of JDO's transaction management, Spring provides a org.springframework.orm.jdo.JdoTransactionManager. However, this aspect is only relevant for the configuration of Spring. There is no need to use this transaction manager in application code.

<bean id="jdoTXManager"
  class="org.springframework.orm.jdo.JdoTransactionManager">
  <property name="persistenceManagerFactory" ref="iboPMF" />
</bean>

Answering the second question is much easier: The PersistenceManagerFactory is simply injected into the PersonService bean, so it can be used in the method sampleInsert:

<bean id="personService"
  class="com.intellibo.sample.spring2.Main">
  <property name="pmf" ref="iboPMFProxy" />
</bean>

Admittedly, not the PersistenceManagerFactory itself but a proxy of it was injected:

<bean id="iboPMFProxy"
  class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
  <property name="targetPersistenceManagerFactory" ref="iboPMF" />
  <property name="allowCreate" value="false" />
</bean>

This proxy of type TransactionAwarePersistenceManagerFactoryProxy encapsulates a PersistenceManagerFactory so that each call to PersistenceManagerFactory#getPersistenceManager() returns an encapsulated PersistenceManager. The returned PersistenceManager will then always be part of an ongoing transaction.

By using the TransactionAwarePersistenceManagerFactoryProxy, explicit handling of transaction demarcation in the application code is no longer necessary. All methods that need to be transaction-aware can be externally declared in the Spring configuration. To prevent the usage of a PersistenceManager in case of no preset transaction configuration, you can set the property allowCreate to false with the iboPMFProxy.


The complete sample is shipped with Signsoft intelliBO 4.1.1. It can be found in the directory IBO_HOME/samples/architecture/spring2. You can run the sample out of the box. Please

On the command line you can then call

ant clean all

to run the sample. All necessary configuration artifacts for Spring and Signsoft intelliBO will be generated by the Ant-script.

If you like to see more log messages of Spring, please set the following line in IBO_HOME/samples/architecture/spring2/lib/log4j.properties to DEBUG:

log4j.logger.org.springframework=INFO

[1] http://www.springframework.org/

[2] http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html

[3] http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/Proxy.html

© Signsoft Softwareentwicklungs- und Vertriebsgesellschaft mbH