Using Jboss Rules With Spring

http://wiki.jboss.org/wiki/Wiki.jsp?page=RulesWithSpringFramework is an excellent article on how to do this. I have made some slight modifications to this to use excel files instead of drl files and pass in a path rather than specify each file individually. Here is the code and configuration

<bean id=”huntGroupRuleBase” class=”edu.apollogrp.qtask.routing.util.RuleBaseBeanFactory”>
<property name=”drlResourcePath” value=”classpath:hunt-group-rules/*.xls”/>
<property name=”packageBuilderConfiguration”>
<bean class=”org.drools.compiler.PackageBuilderConfiguration”>
<!–<property name=”compiler” value=”PackageBuilderConfiguration.JANINO”/> –>
<property name=”compiler” value=”1″/>
</bean>
</property
</bean>

package edu.apollogrp.qtask.routing.util;

import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.util.List;

import org.apache.log4j.Logger;
import org.drools.RuleBase;
import org.drools.RuleBaseFactory;
import org.drools.compiler.PackageBuilder;
import org.drools.compiler.PackageBuilderConfiguration;
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

/**
* @author Geoffrey De Smet
* @see
http://wiki.jboss.org/wiki/Wiki.jsp?page=RulesWithSpringFramework
*
*/
public class RuleBaseBeanFactory implements FactoryBean, InitializingBean,
ApplicationContextAware {

private static final Logger log = Logger
.getLogger(RuleBaseBeanFactory.class);

private String drlResourcePath;

private RuleBase ruleBase;

private PackageBuilderConfiguration packageBuilderConfiguration;

private ApplicationContext applicationContext;

public void afterPropertiesSet() throws Exception {
Resource[] drlResourceList = applicationContext
.getResources(drlResourcePath);

Assert.notEmpty(drlResourceList, “drlResourceList must not be empty”);

PackageBuilder builder = (packageBuilderConfiguration != null ? new PackageBuilder(
packageBuilderConfiguration)
: new PackageBuilder());

SpreadsheetCompiler compiler = new SpreadsheetCompiler();

for (Resource resource : drlResourceList) {
log.info(“Reading file: ” + resource.getFilename());

Reader input = null;

// check the extension to see if this is a decision table or regular
// drl
if (resource.getFilename().endsWith(“drl”)) {
input = new InputStreamReader(resource.getInputStream());
} else if (resource.getFilename().endsWith(“xls”)) {
String drl = compiler.compile(resource.getInputStream(),
InputType.XLS);
log.debug(drl);
input = new StringReader(drl);
} else {
log.warn(“Drools resource has unknown file type: ”
+ resource.getFilename());
}
if (input != null) {
builder.addPackageFromDrl(input);
}
}
ruleBase = RuleBaseFactory.newRuleBase();
ruleBase.addPackage(builder.getPackage());
}

public RuleBase getObject() {
return ruleBase;
}

public Class getObjectType() {
return RuleBase.class;
}

public boolean isSingleton() {
return true;
}

public void setPackageBuilderConfiguration(
PackageBuilderConfiguration packageBuilderConfiguration) {
this.packageBuilderConfiguration = packageBuilderConfiguration;
}

public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext = applicationContext;
}

public void setDrlResourcePath(String drlResourcePath) {
this.drlResourcePath = drlResourcePath;
}

}

Behind every successful project is a set of really good people

After a lot of thinking and years of experience if it is one thing I have realized it is this, Behind every successful project is a set of really good people.

Software development is like running a kitchen, if you have great cooks and great helpers in your kitchen, no matter how bad the recipes are the dishes will turn out fine. If you have bad cooks no matter how good and detailed your recipes are the dishes are ruined (Read “Big Macs vs. The Naked Chef ” Joel Spolsky).

There are other factors too like using a good methodology and using the right tools, but I think these other factors just add up to 10% .

Like a real good chef a really good programmer is agile, if he finds that there is no Source control, he will just set on up on his machine (or commandeer an old machine set up Linux and SVN on it), if he finds that there is no Wiki, he will set up a TiddlyWiki, if the requirements don’t make sense he will contact the user to clear things up. If he doesn’t have the right tools he will just get it, now it will help if the right tools are already in place.

It also helps to have a good project lead who will be open to adopting new practices but that goes back to having good people on your team, after all a project lead is also part of your team right ?

 

Practices of an Agile Developer

I just finished reading “Practices of an Agile Developer” by Venkat Subramaniam and Andy Hunt, now don’t let the title fool you, this book is not only for developers but for anyone working on the team (yes it is for you too managers, leads and architects)One of the practices they mention is “Deploy your application automatically from the start”

This practice makes total sense, invest in building and deploying automatically, trust me this will save you a whole lot of headache later. If you are still manually building you application then beat yourself with a stick cause every manual step can lead to a mistake and hours of headache.

Not to mention you will have one guy who knows how to do it god forbid he goes on vacation and if something goes wrong your highly paid programmers will by spending hours trying to figure out what the hell went wrong and that is not a nice way to spend cash.

And with your luck it will happen in the most crucial moment. (99% SLA, Saturday night, 2 hour window to deploy anything and your application takes 2 hours to build) And don’t tell me your build cannot be automated, yes it can !! put you best developers on it and give em some time and see what happens. And if you are going to automate it start from day one.

Using Spring and Quartz

At ASRS we use a combination of spring and quartz to schedule and run many jobs. A job is a java program that we want to run automatically at a specified time/date.

To understand how spring and quartz work together to create jobs take a look at chapter 22 of the spring reference book http://www.springframework.org/docs/reference/scheduling.html , this will give you a good understanding on how it works also take a look at Quartz itself, http://www.opensymphony.com/quartz/

How to define your own Job

Lets say you have a bean

public class MyBean { public void doSomeThing(){ ?.. } }

You want the method doSomeThing to be executed every day, to do this

1. Define your bean in your spring file as you would any other bean

<ean id=?myBean? class=?MyBean?/>

2. Then define a Job Detail bean, this is done to let quartz know what bean and what method to call

<bean id=”myBeanJobDetail” class=”org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean”>

<!–Name of your bean goes here –>

<property name=”targetObject” ref=”myBean “/>

<!– Name of your method goes here –>

<property name=”targetMethod” value=”doSomeThing “/>

<!– This lets quartz know that 2 instances of this job cannot be run at the same time –>

<property name=”concurrent” value=”false”/>

</bean>

3. Now define the trigger, this tells quartz on what schedule you want it to run

<bean id=”myBeanTrigger”

class=”org.springframework.scheduling.quartz.CronTriggerBean”>

<!–Name of the JobDetail you are scheduling–>

<property name=”jobDetail” ref=” myBeanJobDetail “/>

<!– If an job is not fired at the right Time what to do about it –>

<property name=”misfireInstructionName”

value=”MISFIRE_INSTRUCTION_FIRE_ONCE_NOW”/>

<!–Finally at what schedule you want it to run –>

<!– Fire at 00:00 am 1 day of the month –>

<property name=”cronExpression” value=” * 0/5 * * * ?”/>

</bean>

To learn more about using corn expressions please check http://wiki.opensymphony.com/display/QRTZ1/CronTriggers+Tutorial

4. Most important step initiate your trigger , to do this go to the asrs-quartz-jobs project and add your trigger to the already existing triggers

<description>All Quartz Jobs</description>

<bean class=”org.springframework.scheduling.quartz.SchedulerFactoryBean”>

<property name=”triggers”>

<list>

<!– Mail Trigger –>

<ref bean=”mailcronTrigger”/>

<!– Workflow –>

<ref bean=”workflowBatchProcessTrigger”/>

<!–My Trigger –>

<ref bean=”myBeanTrigger”/>

</list>

</property>

</bean>

All the triggers must be added to the spring file, as soon as the spring context is loaded you triggers will be scheduled by the Scheduler Factory and run at your defined times

Reading and Writing Java Property Files With Ruby

Created a simple Class in ruby to help reading and writing property files

class JavaProps
attr :file, :properties

#Takes a file and loads the properties in that file
def initialize file
@file = file
@properties = {}
IO.foreach(file) do |line|
@properties[$1.strip] = $2 if line =~ /([^=]*)=(.*)\/\/(.*)/ || line =~ /([^=]*)=(.*)/
end
end

#Helpfull to string
def to_s
output = “File Name
#{@file} \n”
@properties.each {|key,value| output += ” #{key}= #{value} \n” }
output
end

#Write a property
def write_property (key,value)
@properties[key] = value
end

#Save the properties back to file
def save
file = File.new(@file,”w+”)
@properties.each {|key,value| file.puts “#{key}=#{value}\n” }
end

end

Use of Fit Test to cover Use Cases and Scenarios

We have been using fit tests in my organization for some time now, I think fit test can sometimes be indispensable ,

We were designing an internal accounting system, we had a lot of complex use cases, and a lot of different scenarios. We needed repeatable tests that would test all the scenarios whenever we add new code. We also needed documentation that could explain the system flow, enter FIT tests,

We designed and developed fit tests that could reset the datbase and run a fit test and cover all the use cases, take a look at the following FIT TEST ( sorry I had to name it .html.css , else Jroller would not allow me to upload).

When you read the fit test it is almost like reading documentation, with Red and Green colors in the tables. Apart for a way to show the users how the system meets the requirements , it is also a great way to show someone new how the system flow works.

Dabbling with Ruby

Started dabbling with Ruby this weekend, after a colleague introduced me to it,

I am amazed at some of the features in Ruby.

It was easy to start off, just used the one click windows installer,

then installed the eclipse RDT and I was up and running.

My fist stab at it was, to use it to output every month start andend date

between 2 given dates

## Returns The number Of Days in a month

def numOfDaysInMonth(date)

if(date.strftime(“%m”)==”02″)

if(date.leap?)

return 29

else

return 28

end

else

monthDaysMap = {“01″=>31,”03″=>31,”04″=>30,”05″=>31,”06″=>30,”07″=>31,”08″=>31,

“09”=>30,”10″=>31,”11″=>30,”12″=>31}

return monthDaysMap[date.strftime(“%m”)]

end

end

# Yields Each Month(start and end Date) between 2 given dates

def eachMonth(startDate,endDate)

while(startDate < endDate)

newDate = startDate+(numOfDaysInMonth(startDate)-1)

yield(startDate,newDate)

startDate = newDate + 1

end

end

And the next was to print start and end date of each year in 2 given dates

# Returns the number of Days in a year

def numOfDaysInYear(date)

if(date.leap?)

return 366

else

return 365

end

end

#Yields each year (start and end date) between 2 given dates

def eachYear(startDate,endDate)

while(startDate < endDate)

newDate = startDate+(numOfDaysInYear(startDate)-1)

yield(startDate,newDate)

startDate = newDate + 1

end

end

and some tests

eachMonth(Date.new(2000,01,01),Date.new(2005,01,01)){|startDate,endDate|

puts startDate.to_s()+” “+endDate.to_s()

}

eachYear(Date.new(2000,01,01),Date.new(2005,01,01)){|startDate,endDate|

puts startDate.to_s()+” “+endDate.to_s()

}

The output

2005-01-01 2005-01-31

2005-02-01 2005-02-28

2005-03-01 2005-03-31

2005-04-01 2005-04-30

2005-05-01 2005-05-31

2005-06-01 2005-06-30

2005-07-01 2005-07-31

2005-08-01 2005-08-31

2005-09-01 2005-09-30

2005-10-01 2005-10-31

2005-11-01 2005-11-30

2005-12-01 2005-12-31

2000-01-01 2000-12-31

2001-01-01 2001-12-31

2002-01-01 2002-12-31

2003-01-01 2003-12-31

2004-01-01 2004-12-31

Spring 1.2 Java 5 Based Transaction Annotations

Colin Sampaleanu posted an excellent article on Spring 1.2’s Java 5 Based Transaction Annotations, if you want to follow this approach but don?t want the DefaultAdvisorAutoProxyCreator to pick up every available Advisor in the context, here what you can do

<bean name=”defaultAdvisor”
class=”org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator”>
<property name=”usePrefix” value=”true”/>
</bean>
<bean name=”defaultAdvisor.transactionAttributeSourceAdvisor”
class=”org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor”>
<property name=”transactionInterceptor” ref=”transactionInterceptor”/>
</bean>
<bean id=”transactionInterceptor”
class=”org.springframework.transaction.interceptor.TransactionInterceptor”>
<property name=”transactionManager” ref=”transactionManager”/>
<property name=”transactionAttributeSource”>
<bean
class=”org.springframework.transaction.annotation.AnnotationTransactionAttributeSource”/>
</property>
</bean>

Create you DefaultAdvisorAutoProxyCreator as mentioned but give it a name (defaultAdvisor in this case) and set the usePrefix property to true.

Then in all the advisors that you want to be picked up, change there name to have ‘defaultAdvisor.’ prefix.

The usePrefix property tells the DefaultAdvisorAutoProxyCreator to apply only those Advisors that have a prefix of its own name.

Alternatively you can also use the AdvisorBeanNamePrefix to tell the DefaultAdvisorAutoProxyCreator what prefix to consider.

Hibernate

Found an interesting feature of hibernate that I wanted to share. The problem is I wanted an instance of one of the subclass and not a proxy.

When you define a mapping for an object like say

<class name=”SomeClass”>

<many-to-one name=“account” column=“ACCOUNT_ID” not-null=“false” cascade=“all”/>

</class>

And if Account Class itself can have subclasses

<class name=“asrs.core.account.model.Account” table=“ACCOUNTS” discriminator-value=“null”>

<subclass name=“asrs.core.account.model.PersonAccount” discriminator-value=“PERS”>

<subclass name=“asrs.core.account.model.EmployerAccount” discriminator-value=“ER”>

</class>

When you get an instance of MyClass from hibernate, the under lying account MAY BE an instance of Hibernate generated subclass of account in other words a proxy that delegates all method invocations to a different instance and the type will not be one of the concrete class (i.e PersonAccount or EmployerAccount) but of type Account.

This may not be necessarily a bad thing, but in my situation, I needed a concrete sub class of Account.

To overcome this problem the solution is when you define your mapping do the following

<many-to-one name=“account” column=“ACCOUNT_ID” not-null=“false” cascade=“all” outer-join=“true”/>

Setting outer-join to true, cause hibernate to fetch eagerly even if proxying is enabled (lazy =true)