Posts tagged ‘spring’

Spring DM deployment problems with schema declaration

OK - so I am trying to learn spring DM and finally got vanilla, non spring OSGI bundles deployed on Spring DM server. Things were finally looking good. Next I tried a basic Spring DM configuration like this:

project

project

Pretty straight forward project setup in STS.

I have a HelloService and a HelloImpl (which is an implementation of this service). My manifest.mf file exposes the net.ahlawat.hello package and looked like this (I am not using my bundle activator for anything):

Manifest-Version: 1.0
Bundle-Version: 1.0.0
Bundle-Name: HelloWorld
Bundle-ManifestVersion: 2
Bundle-SymbolicName: HelloWorld

The spring beans file exposes the osgi service using the osgi namespace and looks like this:

<?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:osgi="http://www.springframework.org/schema/osgi"
	xsi:schemaLocation="http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-2.0-m1.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<osgi:service interface="net.ahlawat.hello.HelloService" ref="helloService" />

	<bean id="helloService" class="net.ahlawat.hello.impl.HelloImpl" />

</beans>

Nothing can possible go wrong. I downloaded spring DM server 2.x and setup the project for running - and got the following exception:

[2010-03-17 18:19:35.207] Thread-5                      Application context creation failure for bundle 'HelloWorld' version '1.0.0'. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean#0': Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'cacheTarget' of bean class [org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean]: Bean property 'cacheTarget' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1341)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1067)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:511)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:450)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:290)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:287)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:189)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:540)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:842)
	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access$1600(AbstractDelegatedExecutionApplicationContext.java:69)
	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext$4.run(AbstractDelegatedExecutionApplicationContext.java:355)
	at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)
	at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)
	at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)
	at com.springsource.kernel.agent.dm.ContextPropagatingTaskExecutor$2.run(ContextPropagatingTaskExecutor.java:106)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:637)
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'cacheTarget' of bean class [org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean]: Bean property 'cacheTarget' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
	at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1012)
	at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:857)
	at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
	at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1338)
	... 18 common frames omitted

It really was baffling - everything was done inside STS and till I introduced the spring DM config file everything worked well.

Some research pointed out what the problem was - the import declaration needed to be changed to 1.2.xsd instead of 2.0.m1.xsd in the xsi:schemaLocation attribute. Making the change leads to a clean deployment:

[2010-03-17 18:21:36.413] TCP Connection(13)-127.0.0.1  Installing bundle 'HelloWorld' version '1.0.0'.
[2010-03-17 18:21:36.461] TCP Connection(13)-127.0.0.1  Installed bundle 'HelloWorld' version '1.0.0'.
[2010-03-17 18:21:36.476] TCP Connection(13)-127.0.0.1  Starting bundle 'HelloWorld' version '1.0.0'.
[2010-03-17 18:21:36.596] start-signalling-3            Started bundle 'HelloWorld' version '1.0.0'.

I think spring needs better error messages.

Manual transactional demarcation in spring and hibernate

Often you are forced to write code where the @Transactional in spring simply does not cut it. You want to execute certain pieces of code in different transactions all with a different propagation and isolation levels. The manual transactional demarcation in spring is stupidly simple after some upfront configuration and works uniformly by enrolling in what ever the enclosing transaction manager is. In case you are running in a JEE server it will tie in with the JTA transaction manager otherwise hibernate transaction manager.

In case you want to integrate with the JTA transaction manager and want the spring @Transactional to work simply put this int he application context:

<!-- configure JTA transaction manager -->
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="allowCustomIsolationLevels" value="true" />
    </bean>

If you are running inside a plain servlet container like tomcat you can configure the hibernate transactions, vanilla JDBC transactions and etc. to use the hibernate transaction manager like this:

<!-- use the hibernate transaction manager -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
        <property name="dataSource" ref="dataSource" />
    </bean>

Notice that the session factory and the data source properties are both set. This then allows jdbcTemplate etc. to all participate in the same transactions as a hibernate call to save() and load().

Once configured its great any spring managed bean with the following annotations on methods will work flawlessly.

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)

This is where the problem starts. Even though you get very granular in the transactions here - calling methods within a service implementation will not be transactionally aware because the demarcation, flushing, commits etc. happen by generating a proxy around the class and internal calls are simply by passed.

In this case you can make use of the spring TransactionTemplate and the PlatformTransactionManager class.

Using it is quite simple - inject the platformTransactionManager into a bean:

<!-- use the hibernate transaction manager -->
    <bean id="xyzService" class="XYZServiceImpl">
        <property name="platformTransactionManager" ref="transactionManager" />
    </bean>

and then directly use transaction templates by specifying custom isolation and propagation levels like this:

public class XYZServiceImpl implements XyzService {
    PlatformTransactionManager platformTransactionManager;

    public void doService() {
        TransactionTemplate template = new TransactionTemplate(platformTransactionManager);
        template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            //annon. inner class
            template.execute(new TransactionCallback() {
            public Object doInTransaction(TransactionStatus status) {
                //your business logic here
            }
        });
    }

    public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
        this.platformTransactionManager = platformTransactionManager;
    }
}

The cool thing is that you could have parts of the same method execute in a different transactions - looking at different isolation levels. No more complex XA/JTA code, hibernate sessions will flush, transactions will commit/rollback at the demarcations you expect - spring makes it too easy.

Spring Roo - first impressions

Ok so another productivity tool hits the market - this time its from the big boys at Spring. Spring Roo is an open source software tool that uses convention-over-configuration principles to provide rapid application development of Java-based enterprise software. The resulting applications use common Java technologies such as Spring Framework, Java Persistence API, Java Server Pages, Apache Maven and AspectJ. Spring Roo is a member of the Spring portfolio of projects.

I was able to install and create an application in under 5 minutes with this thing. Which is great for demo but then I took a look at the generated source code and was not too happy. For a framework that claims to pure java RAD framework there is a bit too much AspectJ in the source folder. In fact its silly the amount of files the generator spits out. The documentation tells you that there is “very little” blackbox and that “you should never be editing” the IDT generated files directly. But for a groovy/java developer who has a lot of web application development experience I am just a little nervous with aspectJ polluting my class files the way i don’t want it too. We use dynamic proxies in more frameworks and places than we can care to think about but there is something about compile time weaving that just makes me a little uncomfortable. Of course this could just be my inexperience with acj and aspectJ talking here.

capture

capture

So for one domain there are a total of 5 source files - 4 of which I should not be touching?

The next thing that was a little bit restrictive was the whole domain modelling - its absoloutely great for simple one-one relationships or many to one relationships but it’s not suitable for slightly more complex types. Also I don’t know how the framework will behave with slightly more advanced but common features of Hibernate (if you are using a Hibernate provider) - like custom hibernate types, hibernate collection of items etc.There is little in the documentation about this - so its hit and try or hit the source code of the project to figure it out.

The scaffold views are not bad but too busy .. from a js/css point - frameworks should ship with minimal style sheets.

I am a little disapointed really I was really excited about this. If I have to choose a RAD framework that will work on a standard JVM I will stick to tomcat + grails.

Here are the advantages of grails as I see it:

1. Cleaner MVC - convention is great /controller/view/id type bindings work great

2. Extremely extensible using plugins, this is a huge advantage and there are some pretty good ones out there from charting to security

3. GORM is great and for the most part works OK

4. Scriptable environment - great little tools like grails console

5. Groovy is great and the framework does not prevent you from using pure java when needed

If you use roo productively - let me know and I will give it a shot again.

Implementing a pagination filter in Hibernate and Spring

Database based pagination is a common requirement in database driven applications. With application frameworks like spring and hibernate and newer language features like generics development of pagination features is seamless.

Lets take a look at this example -

First lets define a data access object (DAO) - an interface used by the application to perform CRUD operations and (in our case) pagination:

public interface Dao {
    public T get(Serializable id);
    public Collection getByExample(T entity);
    public Collection getByExample(T entity, PaginationFilter filter);
    public long countByExample(T entity);
    public void delete(T entity);
    public void persist(T entity);
    public void saveOrUpdate(T entity);
}

The method to note here is

getByExample(T entity, PaginationFilter filter);

The pagination filter is an object that encapsulates:

  1. The start row
  2. The max number of rows
  3. The sorting criteria

Here is the listing of the pagination filter:

public class PaginationFilter {
    public enum Order {
        ASCENDING,
        DESCENDING
    }

    public class SortingCriteria {
        private String column;
        private Order order;

        public SortingCriteria(String column, Order order) {
            this.column = column;
            this.order = order;
        }

        public String getColumn() {
            return column;
        }

        public Order getOrder() {
            return order;
        }
    }

    private int firstResult;
    private int maxResult;
    private List sortingCriterias;

    public PaginationFilter(int firstResult, int maxResult) {
        this.firstResult = firstResult;
        this.maxResult = maxResult;

        this.sortingCriterias = new ArrayList();
    }

    public PaginationFilter addSortingCriteria(String field, Order order) {
        this.sortingCriterias.add(new SortingCriteria(field, order));
        return this;
    }

    public int getFirstResult() {
        return firstResult;
    }

    public int getMaxResult() {
        return maxResult;
    }

    public List getSortingCriterias() {
        return sortingCriterias;
    }
}

Lets now take a look at the implementation of the DAO - the rest of the methods are not very interesting so lets limit the discussion to the methods with PaginationFilter:

    public Collection getByExample(final T entity, final PaginationFilter filter) {
        if (filter == null)
            return getByExample(entity);
        return (Collection) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Criteria criteria = createCriteria(entity, filter, session);
                return criteria.list();
            }
        });
    }

    public long countByExample(final T entity) {
        return (Long) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Criteria criteria = createCriteria(entity, null, session);
                criteria.setProjection(Projections.rowCount());
                Object object = criteria.uniqueResult();
                return new Long(object.toString());
            }
        });
    }

    private Criteria createCriteria(T entity, PaginationFilter filter, Session session) {
        Criteria criteria = session.createCriteria(entity.getClass());
        criteria.add(Example.create(entity));

        if (filter != null) {
            criteria.setMaxResults(filter.getMaxResult()).setFirstResult(filter.getFirstResult());

            for (PaginationFilter.SortingCriteria sortingCriteria : filter.getSortingCriterias()) {
                criteria.addOrder(
                        sortingCriteria.getOrder() == PaginationFilter.Order.ASCENDING?
                                Order.asc(sortingCriteria.getColumn()) :
                                Order.desc(sortingCriteria.getColumn()));
            }
        }

        return criteria;
    }

That is all the code you need to implement pagination with Hibernate:

So to test this code out - let us consider a test entity:

@Entity
public class TestEntity implements Savable{
    @Id
    @GeneratedValue
    private Long id;
    private String name;
    private String address;
.... //Getters and setters
}

Here is a little test that exercises the PaginationCode with the TestEntity:

    @Test
    public void testSorting() {
        PaginationFilter filter = new PaginationFilter(0,26);
        filter.addSortingCriteria("name", PaginationFilter.Order.DESCENDING);
        TestEntity testEntity = new TestEntity();
        List list = (List) genericDao.getByExample(testEntity, filter);
        assertEquals(26, list.size());
        assertEquals("a", ((TestEntity) list.get(25)).getAddress());
        assertEquals("z", ((TestEntity) list.get(0 )).getAddress());
    }

That is it. Imagine having to write filtering/pagination code for a straight up JDBC. Not so much fun. It also amazes me how nice and clean Java generics can make your code. This sceheme works very nicely for me.

High speed database neutral batch inserts/updates using Spring and Hibernate

I have been working on hibernate for a while now and recently wanted to get some data in really fast (basically using SQL batching). 

Here is the entity:

@Entity(name = "Person")
public class PersonEntity {
    @Id
    int id;
    String fName;
    String lName;
    int age;

    public String getFName() {
        return fName;
    }

    public void setFName(String fName) {
        this.fName = fName;
    }

    public String getLName() {
        return lName;
    }

    public void setLName(String lName) {
        this.lName = lName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

1. Modify the *context.xml file to include the following hibernate jdbc parameter:

<prop key="hibernate.jdbc.batch_size">20</prop>

2. Write the code with session clearing every BATCH_SIZE. For convinience sake I am extending the HibernateDaoSupport class but you can use the sessionFactory directly. Here is what I have:

@Transactional
public class HibernateInsertTest extends HibernateDaoSupport implements HibernateInsertInterface {
    private final int BATCH_SIZE = 20;
    private final int NUMBER_OF_ENTITIES = 100000;
    @Transactional(propagation = Propagation.REQUIRED)
    public void init() {
        Session session = getSession();
        StopWatch stopWatch = new StopWatch("Insert test");

        stopWatch.start("Saving entities");
        for (int x = 0; x<NUMBER_OF_ENTITIES; x++) {

            PersonEntity ent = new PersonEntity();
            double rand = Math.random();
            ent.setId(new Long(System.currentTimeMillis() + x).hashCode());
            ent.setFName(""+ rand);
            ent.setLName("" + rand);
            ent.setAge((int) (rand * 100));
            session.persist(ent);
            if (x%BATCH_SIZE == 0) {
                session.flush();
                session.clear(); //<-- IMPORTANT TO CLEAR THE SESSION
            }
        }
        stopWatch.stop();
        System.out.println(stopWatch.prettyPrint());
    }

}

There is something subtle about this code that I want to talk about. Firstly notice that the inserts are in one transaction - although I can use the hibernate session to being and commit a transaction I am instead using the @Transaction spring annotation. The corresponding configuration (since I am using Jboss I can tie this in with the Jta transaction manager) is the following: 

    <!-- configure JTA transaction manager -->
    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    </bean>

Since spring works by generating a proxy for this class I am also implementing an interface (its good practice anyway). The other thing are the periodic calls to session.clear() and session.flush() - they are to prevent an OutOfMemroyException which can occurr if you are inserting a large amount of objects.  

Here is the output of the program:

StopWatch 'Insert test': running time (millis) = 4687

-----------------------------------------
ms     %     Task name
-----------------------------------------
04687  100%  Saving entities

The performance is no different from vanilla JDBC batching because underneath the hood its using the same mechanism. There is however a drawback you cannot use oracle natvie bindings which speeds up batch inserts by 1.5x.

Trasparent remoting using Spring HTTP invoker with Acegi Security

I was investigating remoting for an enterprise java application. Since this was a vanilla tomcat application on Spring I had the following choices:
1. XML RPC
2. RMI
3. Spring HTTP invoker
4. Burlap

For reasons I don’t want to elaborate here I decided to use Spring HTTP invoker. The next step was to integrate this with spring.
The proces is quite straight forward.
First wrap your service in a HttpInvokerServiceExporter

<bean name="/wowservice" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="wowservice"/>
<property name="serviceInterface" value="test.WowService"/>
</bean>

Next consume it at the client using:

<bean id="httpInvokerProxy" class="org.springframework.remoting.httpinvoker.H
ttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="http://xyz:8080/remoting/wowService"/>
<property name="serviceInterface" value="test.WowService"/>
</bean>

Simple enough now you can start to consume this service - directly.

But here is the really awesome thing. Acegi security integrates very well with Spring.

All you have to do is this:
1. Enable the basic auth filter in the Acegi configuraiton
2. Modify your client configuration to make use of the HttpInvokerRequestExecutor property and write an extension to SimpleHttpInvokerRequestExecutor and encode the username:password as base 64 - This can be done by modifying the client configuraiton and adding the following line:

<property name="httpInvokerRequestExecutor"><ref bean="httpInvokerReque
stExecutor"/></property>

to the bean definition of the httpInvokerProxy definition.

To get the encoding correct I simply made use of AuthenticationSimpleHttpInvokerRequestExecutor and it works quite well.

Here is a simple custom executor that simply updates the request with HTTP auth information for every API call. An authentication object is a wrapper class for the username and password that is injected into the executor using Spring.


package com.pranayahlawat.client;

import java.net.HttpURLConnection;

import org.apache.commons.codec.binary.Base64;
import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor;

public class AuthenticationExecutor extends SimpleHttpInvokerRequestExecutor {

private Authentication authentication;

protected void prepareConnection(HttpURLConnection con, int contentLength)
throws java.io.IOException {
super.prepareConnection(con, contentLength);

if (authentication == null)
throw new RuntimeException(”Cannot prepare connection without an authentication object”);

String base64 = authentication.getUsername() + “:” + authentication.getPassword();
con.setRequestProperty(”Authorization”, “Basic ”
+ new String(Base64.encodeBase64(base64.getBytes())));

}

public Authentication getAuthentication() {
return authentication;
}

public void setAuthentication(Authentication authentication) {
this.authentication = authentication;
}
}