Posts tagged ‘java’

JBoss JMX extensions to EJB3

I don’t particularly like developing on JBoss - I think its bloated and slow. But with EJB3 the platform has become more viable. The turn around time to get a relatively complex application with web services etc. done is great.

One thing I like about JBoss 5.x are the JMX extensions to EJB3. Its really amazing how simple installing a JMX MBean is. Let’s say I have to write  a CalculatorService represented by this interface:

package net.ahlawat.cricket;

import javax.ejb.Remote;

import org.jboss.ejb3.annotation.Management;

@Management
@Remote
public interface CalculatorService {
	public double add(double a, double b);
	public double subtract(double a, double b);
	public double performOperation(double a, double b);
	public String getDefaultOperation();
	public void setDefaultOperation(String operation);
}

The interesting annotations here are @Management which tells JBoss deployer that the interface is to be bound as a JMX MBean. The implementation of this bean can be simple pojo - listed here.

package net.ahlawat.cricket;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.ejb3.annotation.Service;

@Service(objectName = "ahlawat:service=CalculatorService")
public class CalculatorServiceImpl implements CalculatorService {
	static Log logger = LogFactory.getLog(CalculatorServiceImpl.class);

	Method defaultOperation;

	@Override
	public double add(double a, double b) {
		return a+b;
	}

	@Override
	public String getDefaultOperation() {
		return defaultOperation.getName();
	}

	@Override
	public double performOperation(double a, double b) {
		try {
			BigDecimal bd = (BigDecimal) defaultOperation.invoke(new BigDecimal(a), new BigDecimal(b));
			return bd.doubleValue();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}

		return Double.NaN;
	}

	@Override
	public void setDefaultOperation(String operation) {
		try {
			Method m = BigDecimal.class.getMethod(operation, BigDecimal.class);
			logger.info("Setting default operation to " + operation);
			defaultOperation = m;
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}

	}

	@Override
	public double subtract(double a, double b) {
		return a-b;
	}

	//lifecycle methods
	public void create() throws Exception {
		logger.info("Creating service");
	}

	public void start() throws Exception {
		logger.info("Starting service");
		setDefaultOperation("add");
	}
}

The only interesting thing here is @Service - which tells Jboss that this is a singleton bean. And the fact that MBean lifecycle methods like create() and start() are available to be implemented here.

The complete list of life cycle methods are:

   void create() throws Exception;
   void start() throws Exception;
   void stop();
   void destroy();

Once this is jar’d up and deployed to Jboss - you can go to jmx-console and see that the service is visible:

jmx-console

jmx-console

You can also look up the bean using the default JNDI name CalculatorServiceImpl/remote

public class Main {
	public static void main(String[] args) throws Exception {
		InitialContext ctx = new InitialContext();

		CalculatorService cs = (CalculatorService)ctx.lookup("CalculatorServiceImpl/remote");

		System.out.println(cs.add(2.1, 3.2));
	}
}

Here is the jndi.properties:

#jboss JNDI properties
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=jnp://localhost:1099
java.naming.factory.url.pkgs=org.jnp.interfaces

And you can also inject the referece to another EJB using the @EJB annotation like this:

@Stateless
public class PlayerServiceImpl implements PlayerService {
	static Log logger = LogFactory.getLog(PlayerServiceImpl.class);

	@PersistenceContext(unitName = "default")
	EntityManager entityManager;

	@EJB
	CalculatorService calculatorService;

	@PostConstruct
	public void gotCalculator() {
		System.out.println(">>>>>>>>>>>>>>>>>> " + calculatorService.add(1.0, 1.0));
	}

...
}

Really small amount of code and guess what - no XML. I really like it.

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.

High speed file splitting/integration in java using NIO

I have many times been faced with a situation where I am trying to move very large files (ISOs or zips upto 1-4 GB in size) but I don’t have a USB drive of that capacity and for some reason I can’t do it over the network. Of course if you want to P2P broadcast of huge files (think updating 200 machines simultaneously) - splitting them up helps in this case specially if you want to replicate a managed bit-torrent like environment. I have found some commercial file splitters out there but they are too slow and clunky. There is no concievable reason why they have to be so slow or I should live without options.
So I just decided to write one from scratch plus it gave me a reason to refresh my NIO knowledge. With some tweaking and proper usage of buffers and channels I have managed to get a comparable/better throughput in java than even the native operating system tools. I tested the integrity of the file and everything was OK.

The amount of code to do it minuscule and quite straight forward. First the splitter:

package net.ahlawat.file;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Program that splits the file
 * User: Pranay Ahlawat
 * Date: Jan 18, 2010
 * Time: 8:14:03 PM
 */
public class Splitter {
    static long BYTE_TO_MB  = 1024 * 1024;
    static long BUFER_SIZE = 128 * 1024;

    public static void main(String[] args) throws Exception {
        if (args.length < 3) {
            System.out.println("splitter [fileName] [split size in MB] [out dir]");
            System.exit(1);
        }

        //create the local variables to be used in the rest of the application
        File inFile = new File(args[0]);
        long partitionSize = Long.parseLong(args[1]) * BYTE_TO_MB;
        File outDir = new File(args[2]);

        //create inital counters
        final long totalFileSize = inFile.length();

        //create the out dirs if they dont exist
        if (!outDir.exists()) {
            System.out.println("Creating directory : " + outDir.getName());
            outDir.mkdirs();
        }

        FileChannel inChannel =  new FileInputStream(inFile).getChannel();

        long currentPosition = 0;
        int ctr = 0;
        ByteBuffer buff = ByteBuffer.allocate((int)BUFER_SIZE);
        long start = System.currentTimeMillis();

        while(currentPosition < totalFileSize) {
            //get the out channel for the file - roughly is the "originalFileName.ext.n" where 'n' is the partition number
            FileChannel outChannel = getChannel(inFile, outDir, ++ctr); //init the out channel
            //the size of the nth partition
            long size = currentPosition + partitionSize < totalFileSize? partitionSize : totalFileSize - currentPosition;
            //sout
            System.out.print(String.format("Creating part %s of size %s MB", ctr, size/BYTE_TO_MB));
            long start2 = System.currentTimeMillis();

            //the end position of the nth partition w.r.t the entire file
            long endPosition = currentPosition + size;

            //write partition in BUFFER_SIZE chunks
            while(currentPosition < endPosition) {
                //read the chunk into the buffer
                long subSize = (currentPosition + BUFER_SIZE) < endPosition ? BUFER_SIZE : endPosition - currentPosition;
                inChannel.read(buff, currentPosition);
                //prepare for writing
                buff.flip();
                //write
                outChannel.write(buff);
                currentPosition += subSize;
                //clear the buffer - so we can write again
                buff.clear();
            }

            outChannel.close(); //close

            //print throughput for this file partition
            double delta = (double)(System.currentTimeMillis() - start2)/1000;
            System.out.println(String.format(" -> Transferred in %.2f s @ %.2f MB/s", delta,
                    (double) size/BYTE_TO_MB/delta));
        }

        //calculate time
        double delta =  (double)(System.currentTimeMillis() - start)/1000;

        //print out the total throughput
        System.out.println(String.format("Copied %.2f MB in %.2f s @ %.2f MB/s", (double)totalFileSize/BYTE_TO_MB, delta, (double)totalFileSize/BYTE_TO_MB/delta));

        //finally close the channel
        inChannel.close();
    }

    private static FileChannel getChannel(File inFile, File outDir, int ctr) throws FileNotFoundException {
        return new FileOutputStream(new File(outDir, (inFile.getName() + "." + ctr))).getChannel();
    }
}

There are a couple of things I would like to mention about this code. First I tried a variety of things - I tried the MappedMemoryBuffers which was not giving me good performance so I reverted to using vanilla byte buffers. Next I tried a variety of buffer sizes unsurprisingly too low a buffer size means too many reads and too high meant very slow buffer manipulation - vanilla byte buffers of 128K seemed to be just right and gave me great speed and memory numbers.

The file under experiment was the open solaris ISO - about 700 MB in size. Here is the output:

Creating part 1 of size 100 MB -> Transferred in 0.27 s @ 366.30 MB/s
Creating part 2 of size 100 MB -> Transferred in 0.25 s @ 403.23 MB/s
Creating part 3 of size 100 MB -> Transferred in 0.24 s @ 413.22 MB/s
Creating part 4 of size 100 MB -> Transferred in 0.25 s @ 406.50 MB/s
Creating part 5 of size 100 MB -> Transferred in 1.19 s @ 84.32 MB/s
Creating part 6 of size 100 MB -> Transferred in 2.16 s @ 46.38 MB/s
Creating part 7 of size 76 MB -> Transferred in 2.21 s @ 34.85 MB/s
Copied 676.99 MB in 6.69 s @ 101.21 MB/s

Not bad I could split the file up in under 7 seconds - this is better throughput than what the native tool gives me. The result of this code was that the big file was split into 100MB chunks (and change).

Next the integrator -

package net.ahlawat.file;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;
import static net.ahlawat.file.Splitter.*;

/**
 * Integrator - integrate files
 * User: Pranay Ahlawat
 * Date: Jan 18, 2010
 * Time: 10:51:43 PM
 */
public class Integarator {

    public static void main(String[] args) throws Exception {
        if (args.length < 3) {
            System.out.println("integrator [fileName] [dir] [out file name]");
            System.exit(1);
        }

        //create core variables
        File dir = new File(args[1]);
        String baseFileName = args[0];
        File outFile = new File(args[2]);

        //create the out channel - to which the data will be written
        FileChannel outChannel = new FileOutputStream(outFile).getChannel();

        //core buffer
        ByteBuffer buff = ByteBuffer.allocate((int)BUFER_SIZE);

        int ctr = 0;
        long start = System.currentTimeMillis();
        while(true) {
            //some profiling
            long start2 = System.currentTimeMillis();
            //create the file and test to see if it's there
            File file = new File(dir, String.format("%s.%s", baseFileName, ++ctr));
            if (!file.exists()) { //no the file 'n' does not exist - integration complete
                break;
            }

            System.out.print(String.format("Integrating %s", file.getName()));

            //creat the in channel for the partitioned file 'n'
            FileChannel inChannel = new FileInputStream(file).getChannel();

            long currentPosition = 0;
            long fileSize = file.length();

            //read the file in chunks of BUFFER_SIZE
            while(currentPosition < fileSize) {
                long chunkSize = (currentPosition + BUFER_SIZE) < fileSize? BUFER_SIZE : fileSize - currentPosition;
                inChannel.read(buff, currentPosition);
                currentPosition += chunkSize;
                buff.flip(); //flip the buffer we are ready to write
                outChannel.write(buff);
                buff.clear(); //clear
            }

            //close/flush the information
            inChannel.close();

            //print profiling inforamtion
            double delta = (double) (System.currentTimeMillis() - start2)/1000;
            System.out.println(String.format(" -> Integration complete in %.2f s @ %.2f MB/s",
                    delta, file.length()/BYTE_TO_MB/delta));
        }

        outChannel.close();
        double delta = (double) (System.currentTimeMillis() - start)/1000;
        System.out.println(String.format("Integration complete in %.2f @ %.2f MB/s", delta, outFile.length()/BYTE_TO_MB/delta));
    }
}

Again I tried the outChannel.transferFrom() but it just bew up - the performance was horrible. The best results were when I used vanilla buffers and manipulated them myself.

Here are the results:

Integrating osol.iso.1 -> Integration complete in 0.35 s @ 283.29 MB/s
Integrating osol.iso.2 -> Integration complete in 0.26 s @ 378.79 MB/s
Integrating osol.iso.3 -> Integration complete in 0.25 s @ 393.70 MB/s
Integrating osol.iso.4 -> Integration complete in 0.28 s @ 361.01 MB/s
Integrating osol.iso.5 -> Integration complete in 1.68 s @ 59.56 MB/s
Integrating osol.iso.6 -> Integration complete in 2.10 s @ 47.55 MB/s
Integrating osol.iso.7 -> Integration complete in 1.39 s @ 54.87 MB/s
Integration complete in 6.44 @ 104.97 MB/s

Not bad at all. Just to put how fast this in in perspective - using cygwin just copying about 700 MB takes about 15 seconds.

deepti@aanyalaptop /cygdrive/c/test
$ time cp osol.iso cp_of_osol.iso

real    0m16.014s
user    0m0.031s
sys     0m1.825s

deepti@aanyalaptop /cygdrive/c/test
$

And I wrote this little bat script to measure the throughput of native windows command line.

prompt $d $t $_$P$G
copy osol.iso another_cp.iso
prompt $d $t $_$P$G

Here is the output.

C:\test>prompt $d $t $_$P$G

Tue 01/19/2010  1:07:48.86
C:\test>copy osol.iso another_cp.iso
        1 file(s) copied.

Tue 01/19/2010  1:08:00.32
C:\test>prompt $d $t $_$P$G

Tue 01/19/2010  1:08:00.32
C:\test>

Which is approximate 12 seconds… :) - java NIO rocks.

I will package this up with a UI and make it available as a tool on ahlawat.net soon for all interested.

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.

Circumventing creating objects via Reflection vs Direct object manipulation

Of course its no secret that reflection is a lot slower than that direct object manipulation but with java 5 and 6 the speed has dramatically improved I wanted to find out just how much of a penalty hit was it to use reflection rather than direct object manipulation to create objects (from the database end for eg.).

The answer is - substantial.

Here is a code that basically populates an object with random data - first completely via reflection and then by using actual java code:

package net.ahlawat.Main;

import java.lang.reflect.Method;
import java.util.*;

public class Main {
    static class TestClass {
        private String firstname;
        private String lastname;
        private String username;
        private String address;
        private String email;

        public String getFirstname() {
            return firstname;
        }

        public void setFirstname(String firstname) {
            this.firstname = firstname;
        }

        public String getLastname() {
            return lastname;
        }

        public void setLastname(String lastname) {
            this.lastname = lastname;
        }

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getAddress() {
            return address;
        }

        public void setAddress(String address) {
            this.address = address;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }
    }

    public static void main(String[] args) {
        System.out.println("Reflection performance");

        try {
            long start = System.currentTimeMillis();
            Method[] methods = TestClass.class.getMethods();
            List<Method> objectMethods = Arrays.asList(Object.class.getMethods()); 

            List<Method> setters = new ArrayList<Method>();

            for (Method method : methods) {
                String name = method.getName();
                if (objectMethods.contains(method)) {
                    continue;
                } else if (name.startsWith("set") && method.getParameterTypes().length == 1) {
                    setters.add(method);
                }
            }

            System.out.println(String.format("Resolving all methods in %s ms", (System.currentTimeMillis()-start)));

            int objectCount = 10000;
            Random random = new Random();
            start = System.currentTimeMillis();
            for (int x=0; x<objectCount; x++) {
                Object o = TestClass.class.newInstance();
                for (Method getter : setters) {
                    getter.invoke(o, random.nextDouble() + "");
                }
            }
            long refTime = System.currentTimeMillis() - start;
            System.out.println(String.format(Locale.getDefault(),"Creating %d objects via reflection: %d ms",
                    objectCount, refTime));

            start = System.currentTimeMillis();
            for(int x = 0; x<objectCount; x++) {
                TestClass ob = new TestClass();
                ob.setAddress(random.nextDouble() + "");
                ob.setFirstname(random.nextDouble() + "");
                ob.setLastname(random.nextDouble() + "");
                ob.setUsername(random.nextDouble() + "");
                ob.setEmail(random.nextDouble() + "");
            }

            long directTime = System.currentTimeMillis() - start;
            System.out.println(String.format(Locale.getDefault(),"Creating %d objects via direct object manipulation: %d ms",
                    objectCount, directTime));

            System.out.println(String.format("Slowness: %.2f%%", (double)(refTime-directTime)*100/directTime));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

Quite straight forward. Here are the results:

Reflection performance
Resolving all methods in 2 ms
Creating 10000 objects via reflection: 218 ms
Creating 10000 objects via direct object manipulation: 129 ms
Slowness: 68.99%

Oddly internally the compiler optimized the reflective transfer if you do it many times over - I don’t know what exactly causes it but increasing the number to 100,000 instead the slowness is 40%.

Reflection performance
Resolving all methods in 2 ms
Creating 100000 objects via reflection: 1714 ms
Creating 100000 objects via direct object manipulation: 1213 ms
Slowness: 41.30%

If you take a look at just milliseconds it might not seem like a lot - but if you use reflection excessively it will kill the performance of you app. The good thing is you don’t have to live with it.

If you must use reflection due to the dynamic nature of the framework you are putting in place you are much better off writing a one time code generator. Using this generator you can overcome the 50% penalty of using reflection and yet keep the application dynamic.

So use reflection to produce the code that does direct object transfer to a .java file - compile it and use it. I plan to use the same for a data access service object which reads stuff from a table and populates an object using annotations on the class (a hibernate wannabe if you will). The milliseconds will add up pretty fast. I can share the groovy code generator if people are interested.

A flawless Publisher-Subscriber using BlockingQueue

java.util.concurrent simply rocks. I cant believe how simple it has made every day programming tasks.

What is the first thing your learn when you do multi-threading - a producer consumer. It’s a great example to learn notify, wait and understanding the locking semantics of java threading. Its a pity I started earlier because those of us starting out with java 1.5/6 will have their lives too easy. The BlockingQueue is a fantastic addition to the language and using it one can implement a synchronized multi publisher-multi subscriber system using semantics and constructs no different from java collections.

Here is an example with 5 publishers and 2 subscribers:

package net.ahlawat;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.Date;

/**
 * @author Pranay Ahlawat
 */
public class PubSubTest {
    static class Publisher implements Runnable {
        BlockingQueue<String> queue;
        String name;
        public Publisher(BlockingQueue<String> queue, String name) {
            this.queue = queue;
            this.name = name;
        }

        public void run() {
            while(true) {
                queue.add(String.format("Msg from %s: %s [on %s]", name, Math.random(), new Date()));
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }
    }

    static class Subscriber implements Runnable {
       BlockingQueue<String> queue;
        String name;
        public Subscriber(BlockingQueue<String> queue, String name) {
            this.queue = queue;
            this.name = name;
        }

        public void run() {
            while(true) {
                try {
                    String in = queue.take();
                    System.out.println(String.format("[%s GOT MESSAGE] %s",name,in));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }

            }
        }
    }

    public static void main(String[] args) {
        final int numberOfPublishers = 5;
        BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<String>(10);
        for (int x=1; x<=numberOfPublishers; x++) {
            Publisher publisher = new Publisher(blockingQueue, x+"");
            new Thread(publisher).start();
        }

        Subscriber subscriber1 = new Subscriber(blockingQueue, "Subscriber 1");
        new Thread(subscriber1).start();
        Subscriber subscriber2 = new Subscriber(blockingQueue, "Subscriber 2");
        new Thread(subscriber2).start();
    }
}

It’s quite straight forward - there are a total of 7 threads interacting with the queue. 5 publishers are putting stuff on the queue and 2 subscribers are picking up stuff from it and creatively printing it out the standard out. What I want you to see is the number of times I have used ’synchronized’ in the code - 0.

The output is not surprising:

[Subscriber 1 GOT MESSAGE] Msg from 4: 0.6466875854315378 [on Fri Dec 11 02:11:27 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 1: 0.33362845358296433 [on Fri Dec 11 02:11:27 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 2: 0.11207796566244055 [on Fri Dec 11 02:11:27 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 3: 0.6810655758824113 [on Fri Dec 11 02:11:27 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 5: 0.5679631128460616 [on Fri Dec 11 02:11:27 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 1: 0.6304440131162121 [on Fri Dec 11 02:11:28 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 2: 0.021117766277559014 [on Fri Dec 11 02:11:28 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 3: 0.1955294791717468 [on Fri Dec 11 02:11:28 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 4: 0.884529348835637 [on Fri Dec 11 02:11:28 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 5: 0.034690283475101946 [on Fri Dec 11 02:11:28 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 1: 0.5764439934861816 [on Fri Dec 11 02:11:29 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 2: 0.3629499102212388 [on Fri Dec 11 02:11:29 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 4: 0.3770428828123388 [on Fri Dec 11 02:11:29 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 3: 0.9450938944637225 [on Fri Dec 11 02:11:29 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 5: 0.8910317407643176 [on Fri Dec 11 02:11:29 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 1: 0.5785955008786261 [on Fri Dec 11 02:11:30 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 4: 0.9442550853581151 [on Fri Dec 11 02:11:30 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 3: 0.3308239883343358 [on Fri Dec 11 02:11:30 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 5: 0.5450057593023042 [on Fri Dec 11 02:11:30 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 2: 0.13504231409694423 [on Fri Dec 11 02:11:30 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 1: 0.1018850869879191 [on Fri Dec 11 02:11:31 EST 2009]
[Subscriber 1 GOT MESSAGE] Msg from 2: 0.7325884278324815 [on Fri Dec 11 02:11:31 EST 2009]
[Subscriber 2 GOT MESSAGE] Msg from 4: 0.8804538983093999 [on Fri Dec 11 02:11:31 EST 2009]
...

Such an elegant solution to a classic problem - the wonderful BlockingQueue …

Understading table dependencies caused by referential constraints in oracle

At work last week - I was doing some iterative development which required me to start from a clean database every time. The solution provided by the DBA’s in my team was either a complete reinitialization of the schema OR a script that disables every constraint, truncates all the tables and re-enables all the constraints. Both of these solutions were dreadfully slow.

This was a bit of a hassle because we have an extremely complex schema with a lot of inter-dependencies between tables. Therefore like any self respecting developer I decided to script my way out - so the problem was to:

1. Figure out all the referential constraints from the database

2. Order the deletes in a manner that none of the constraints are violated

A little bit of reading and research introduced me to the all_constraints table ..

SQL> desc all_constraints;
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------

 OWNER                                     NOT NULL VARCHAR2(30)
 CONSTRAINT_NAME                           NOT NULL VARCHAR2(30)
 CONSTRAINT_TYPE                                    VARCHAR2(1)
 TABLE_NAME                                NOT NULL VARCHAR2(30)
 SEARCH_CONDITION                                   LONG
 R_OWNER                                            VARCHAR2(30)
 R_CONSTRAINT_NAME                                  VARCHAR2(30)
 DELETE_RULE                                        VARCHAR2(9)
 STATUS                                             VARCHAR2(8)
 DEFERRABLE                                         VARCHAR2(14)
 DEFERRED                                           VARCHAR2(9)
 VALIDATED                                          VARCHAR2(13)
 GENERATED                                          VARCHAR2(14)
 BAD                                                VARCHAR2(3)
 RELY                                               VARCHAR2(4)
 LAST_CHANGE                                        DATE
 INDEX_OWNER                                        VARCHAR2(30)
 INDEX_NAME                                         VARCHAR2(30)
 INVALID                                            VARCHAR2(7)
 VIEW_RELATED                                       VARCHAR2(14)

SQL>

The columns of interest here is the R_CONSTRAINT_NAME  which is the constraint on which the constraint in question relies on. A join with the user_constraint table can then give the actual table on which the current table in question relies on -

select a.constraint_name as acn, a.table_name as atn, b.table_name as btn,
  b.constraint_name  as bcn from all_constraints a, user_constraints b where
  a.r_constraint_name = b.constraint_name

After this its a cake walk - here is the groovy script that deletes the table in the correct order.

import groovy.sql.Sql

def sql = Sql.newInstance("jdbc:oracle:thin:username/password@//localhost:1521/SID",
        "oracle.jdbc.driver.OracleDriver")
long start = System.currentTimeMillis()
def dependencies = [:]
def deleted = new HashSet();

sql.eachRow("select table_name from user_tables where temporary = 'N' and table_name not like 'MVC_%' and table_name not like 'MV_%'") {
  dependencies[it.table_name] = new HashSet();
}

sql.eachRow("""select a.constraint_name as acn, a.table_name as atn, b.table_name as btn,
  b.constraint_name  as bcn from all_constraints a, user_constraints b where
  a.r_constraint_name = b.constraint_name""") {
  dependencies[it.btn] << it.atn
}

println "Getting all tables and resolving referential constraints finished ${System.currentTimeMillis() - start} ms"

start = System.currentTimeMillis();

int size = dependencies.keySet().size()
while (deleted.size() < size) {
  int initSize = deleted.size();
  dependencies.keySet().each {table->
    def reducedSet = dependencies[table].grep {!deleted.contains(it)}
    if (reducedSet.size() ==0 || (reducedSet.size() == 1 && reducedSet.iterator().next() == table)) {
      deleted.add(table)
      println "deleting $table"
      String query = "delete from $table"
      sql.execute(query)
    }
  }

  if (initSize == deleted.size()) {
    println "PROBLEM .. "
    dependencies.keySet().each() {table->
      if (deleted.contains(table)) {
        return;
      }
      println "$table -> ${dependencies[table].grep {!deleted.contains(it)}}"
    }
    throw new IllegalStateException("Cannot delete tables because of cyclic dependencies")
  }
}

println "Deleting all tables completed in ${System.currentTimeMillis() - start}"

I hope this saves you as much time as it has already saved me.

Debugging oracle constraints

On more than one occasion I have been stumped with a message like this.

java.sql.BatchUpdateException: ORA-00001: unique constraint (SYSTEM.SYS_C0089989) violated

Apart from blaming oracle for being lazy and not putting the table/column name in the error message - there is nothing else that comes to mind when I see something like this.

Finding out the table and the constraint - you can connect to plsql and execute this query:

select constraint_name, constraint_type, table_name from user_constraints where constraint_name like 'SYS_C0089989';

The result is something like this:

"CONSTRAINT_NAME","CONSTRAINT_TYPE","TABLE_NAME"
"SYS_C0089989","P","JOBAUDIT"

This information gives you the table name and the constraint type on that table.

Here is what the constraint type columns mean:

C   Check on a table                Column
O   Read Only on a view           Object
P   Primary Key                       Object
R   Referential AKA Foreign Key  Column
U   Unique Key                        Column
V   Check Option on a view       Object

So looking back I know my code is trying to insert a duplicate id in the table.

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.