Wednesday, November 9, 2011

Scheduling and Concurrency with Spring

Here, I am trying to aggregate some of the information I got on Threading, Concurrency and Scheduling concepts using Spring with my example.

I will be using ThreadPoolTaskExecutor, Callable interface, Future Object from java.util.Concurrent package, task scheduled tag from Spring

My Requirement:
I need to have a scheduled processor which fetches huge data from database, on which I need to do a large processing and need to update the database with the process start and completion time. Processing the data can be done in parallel.


Solution:


For scheduling a task in Spring:

I wrote a simple POJO as follows:

@Service("myScheduler")
public class MyScheduler {

public void startProcess(){

}
}

Then in my spring configuration file (for starters, this is the applicationContext file)
< 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"
xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd">

< util:properties id="myProperties" location="file:/C:/cron.properties" />
< task:scheduled-tasks>
myScheduler" method="startProcess"
cron="#{myProperties['scheduler.cron']}" />
< /task:scheduled-tasks>
< / beans>

Here I am getting the scheduling time as a cron expression from a properties file, cron.properties, which is located on the file system under C:\ drive.
So cron.properties will have entry as,
scheduler.cron=0 * * * * *


That's it for scheduling. The startProcess method runs according to your cron expression.


Now for Concurrency:

Now I have huge data (either from database or file reads) in startProcess() and I need to start processing that data in parallel. Also I have the req to get the process completion date, which means, I need to wait in my main thread for the completion of all threads.

First I write a Worker class which implements a Callable interface.

public class Worker implements Callable {
/**
*Callable interface implementation
*/
public Object call() throws Exception {
//Process your data here ..
boolean isCompleted = true;
return isCompleted;
}
}


Then in my spring application context, I mentioned as

worker" keep-alive="300" pool-size="10" queue-capacity="15" rejection-policy="CALLER_RUNS"/>

This indicates to Spring, that a ThreadPoolTaskExecutor needs to be created who will have a pool size of 10, and a queue-capacity of 15. (Here, an initial pool of 10 threads will be created. First 10 requests will be given to 10 threads and their processing starts. The requests 11 - 15 will be set in a queue and as soon as any of the 10 threads are free , one of the queued requests will be assigned to that thread. When all the queue is full, the because we mentioned CALLER_RUNS, the next request runs in the main thread itself.

And in the MyScheduler (Which will be the main thread)


@Service("myScheduler")
public class MyScheduler {

@Autowired
@Qualifier("worker")
private ThreadPoolTaskExecutor worker;
public void startProcess(){
Date startTime = new Date();
Set futureSet = new HashSet();
for (int i = 0; i < 25; i++) {
Worker del = new Worker();
//Set any data to be sent to this worker thread..
futureSet .add(worker.submit(del));
}
for(Future temp: futureSet ){
if(temp.get() instanceof boolean){
boolean isCompleted = (Boolean)temp.get(); //This will wait till the thread completes it //task...
System.out.println("Complete Status :" + successMessage.get("CompletedStatus"));
}
}
Date completedTime = new Date();
}
}




Wednesday, November 2, 2011

Decorator/Wrapper Pattern

Decorator Pattern is a very simple pattern in which a decorator object is wrapped around an object, so that new behaviour/responsibility is added to the original object without changing the original object.

Two simple and good sources for decorator pattern are:


In Liferay, we use the concept of hooks for liferay extensions. We can extend liferay services using hooks with the help of decorator pattern.

Thursday, October 20, 2011

Hibernate - No primary key Table

In Hibernate mapping, It is not possible to create a table without a primary key. If you are using annotations, you definitely need to use @Id in your class. But what happens if there is no primary key in your database table.

There is a workaround for this if your table is having some sort of unique relationship to any other table.

Consider two classes. Parent and a Child.
Parent has a primary key property but Child do not.

@Entity
@Table(name = "ParentTableName")
class Parent{

protected Integer id;
@Id
@Column(name = "PrimaryKeyColumnName", nullable = false)
public Integer getId() {
return id;
}
}



@Entity
@Table(name = "ChildTableName")
class Child{
private Parent parent;

@Id
@OneToOne @JoinColumn(name = "FKColumnNameInChildTable", nullable = false)
public Parent getParent() { return parent; }

public void setParent(Parent parent) { this.parent = parent;
}
}


Here even though, no primary key is specified in the database table, we are informing Hibernate to treat the Foreign Key as the primary key.


But what if you we have a unique relation on multiple columns in the child table?
In that case we can specify @Id annotation to all the relations and specify those relations with @Embeddable annotation.



Thursday, April 28, 2011

Eclipse - Eclipse is running in a JRE, but a JDK is required

Eclipse by default runs on a JRE. But, there may be times you want a full JDK to run it. One example is using Maven Plug-in.

Change the eclipse.ini (Located in the same folder as in your eclipse.exe file) file with a vm argument pointing to your jdk.

The important things are :
1. Enter a new argument "vm" pointing to the java jdk's javaw.exe file
-vm
C:/Program Files/Java/jdk1.6.0_20/bin/javaw.exe
2. vm and the path should be in a separate line. So if you have
-vm C:/Program Files/Java/jdk1.6.0_20/bin/javaw.exe
in a single line, Eclipse can not identify it.
3. "vm" argument should be before "-vmargs" and after" --launcher.XXMaxPermSize"
-vm
C:/Program Files/Java/jdk1.6.0_20/bin/javaw.exe
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx768m
-XX:MaxPermSize=256m


You can point to the java/bin folder also, for the vm argument. Some people got an exception because of a space in the file path location of java, so you might try installing Java into a non-space file path like C:/Java/jdk1.6.0_20.


This also works the same way for the Spring Source Tool Suite and you can see this concerned thread, http://forum.springsource.org/showthread.php?t=86906.