Posts Tagged ‘Spring’
Why I Love Spring 2.5′s PropertyPlaceholderConfigurer
I have been a big fan of Spring’s PropertyPlaceholderConfigurer since 2006 when I could wire up a datasource bean, or any bean for that matter, with just some references to properties that I knew were going to be in place. A snippet from a Spring context file for example:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${my.db.driver}"/>
<property name="url" value="${my.db.url}"/>
<property name="username" value="${my.db.username}"/>
<property name="password" value="${my.db.password}"/>
</bean>
Now, I can provide PropertyPlaceholderConfigurer with a .properties file location(s) or I could depend on the properties existing as part of the runtime, like when using JBoss Application Server’s property service. Then one day, I ran into a bit of an issue. Well, now I have an application with a properties file that has datasource connection information for each development region, DEV, TEST and PROD and the region is a ‘prefix’ on each property.
Something like…
DEV.my.db.driver DEV.my.db.url DEV.my.db.username DEV.my.db.password TEST.my.db.driver TEST.my.db.url TEST.my.db.username TEST.my.db.password
… and so on. If you are packaging .properties files into your archive(.war, .jar, .ear), this does help your code be a bit more portable but I usually configure properties outside of an archive but we can’t always have our way. So, now we have a special class that reads the properties file and the region variable from SystemProperties as the region variable, SDLC_REGION, is set in each development region as a VM argument.
-DSDLC_REGION=DEV
And that works great. We can leave our Spring context alone and everything works like we need it to. But, I am always trying to reduce classes or utilities(.jar files) that are no longer needed in our applications. So, I took a look back into Spring 2.5′s PropertyPlaceholderConfigurer and low and behold, there is a better way to do things. Check it out. Here is my Spring context file now:
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${${SDLC_REGION}.my.db.driver}"/>
<property name="url" value="${${SDLC_REGION}.my.db.url}"/>
<property name="username" value="${${SDLC_REGION}.my.db.username}"/>
<property name="password" value="${${SDLC_REGION}.my.db.password}"/>
</bean>
Now, the VM argument, SDLC_REGION, exists in each environment and it can be a part of our PropertyPlaceholderConfigurer expression. We can now load the correct property for each development region from the packaged .properties file without depending on our utility class anymore. Really cool stuff and again, beautiful work from the people at SpringSource.
Spring 3, AspectJ and Hazelcast – Cache Advance
I have been working with Java and related technologies at multiple companies since 2004. Most of the major business problems that I have encountered revolve around working with relatively small data objects and relatively small data stores (less than 50GB). One commonality in the development environment at each of these companies, other than Java, has been some form of legacy data store. In most cases, the legacy data store was not originally designed to support all of the various applications that are now dependent on the legacy system. In some cases, performance issues would arise that were most likely due to over utilization.
One approach to help alleviate utilization issues on legacy resources is with data caching. With data caching we can utilize available memory to keep our data objects closer to our running application. We can take advantage of technologies like Hazelcast, a data distribution platform for Java, to provide support for distributed data caching. In particular, this example focuses on Hazelcast’s distributed Map to manage our in-memory caching. Because Hazelcast is easily integrated with most Web applications, include the hazelcast jar and xml file, the overhead is minimal. When we take advantage of Aspect Oriented Programming(AOP), with the help of Spring and AspectJ, we can leave our current implemented code in place and implement our distributed caching strategy with minimal code changes.
Let’s look at a simple example where we are loading and saving objects in a simple Data Access Object (DAO). Below, PersistentObject, is the persistent data object we are going to use in this example. Note that this object implements Serializable because it is required if we want to put this object into Hazelcast’s distributed Map (it is also a good idea for applications that utilize session replication).
public class PersistentObject implements Serializable {
private static final long serialVersionUID = 7317128953496320993L;
private Long id;
private String field1;
private String field2;
private String field3;
private List<String> fieldList1;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Here is our simple interface for the DAO. Yes, this interface is ridiculously simple, but it does what we need it to do for this example.
public interface DataAccessObject {
public PersistentObject fetch(Long id);
public PersistentObject save(PersistentObject persistentObject);
}
Here is the implementation of the DataAccesObject interface. Again, really simple and in fact, I left out the meat of the implementation for brevity, but it will work for this example. Each of these methods would usually have some JDBC code or ORM related code. The key here is that our DAO code will not change when we re-factor the code to utilize the distributed data cache because it will be implemented with AspectJ and Spring.
public class DataAccessObjectImpl implements DataAccessObject {
private static Log log = LogFactory.getLog(DataAccessObjectImpl.class);
@Override
public PersistentObject fetch(Long id) {
log.info("***** Fetch from data store!");
// do some work to get a PersistentObject from data store
return new PersistentObject();
}
@Override
public PersistentObject save(PersistentObject persistentObject) {
log.info("***** Save to the data store!");
// do some work to save a PersistentObject to the data store
return persistentObject;
}
}
The method below, “getFromHazelcast”, exists in the DataAccessAspect class. It is an “Around” aspect that gets executed when any method “fetch” is called. The purpose of this aspect and pointcut is to allow us to intercept the call to the “fetch” method in the DAO and possibly reduce “read” calls to our data store. In this method, we can get the Long “id” argument from the called “fetch” method, get our distributed Map from Hazelcast and try to return a PersistentObject from the Hazelcast distributed Map, “persistentObjects”. If the object is not found in the distributed Map, we will let the “fetch” method handle the work as originally designed.
@Around("execution(* fetch(..))")
public Object getFromHazelcast(ProceedingJoinPoint pjp) throws Throwable {
// get method args
Object[] args = pjp.getArgs();
// get the id
Long id = (Long) args[0];
// check Hazelcast distributed map
Map<Long, PersistentObject> persistentObjectMap = Hazelcast.getMap("persistentObjects");
PersistentObject persistentObject = persistentObjectMap.get(id);
// if the persistentObject is not null
if(persistentObject != null) {
log.info("***** Found it in Hazelcast distributed map!");
return persistentObject;
}
// continue with the fetch method that was originally called if PersistentObject was not found
return pjp.proceed();
}
The method below, “putIntoHazelcast”, also exists in the DataAccessAspect class. It is an “AfterReturning” aspect that gets executed when any method “save” returns. As each PersistentObject is persisted to the data store in the “save” method, the “putIntoHazelcast” method will insert or update the PersistentObject in the distributed Map “persistentObjects”. This way we have our most recent PersistentObject versions available in the distributed Map. If we just keep inserting/updating all PersistentObject’s into the distributed Map, we would have to eventually look into our distributed Map’s eviction policy to keep more relavent application data in our cache, unless, we have excess or abundant memory.
@AfterReturning(pointcut="execution(* save(..))", returning="retVal")
public void putIntoHazelcast(Object retVal) throws Throwable {
// get the PersistentObject
PersistentObject persistentObject = (PersistentObject) retVal;
// get the Hazelcast distributed map
Map<Long, PersistentObject> persistentObjectMap = Hazelcast.getMap("persistentObjects");
// put the PersistentObject into the Hazelcast distributed map
log.info("***** Put this PersistentObject instance into the Hazelcast distributed map!");
persistentObjectMap.put(persistentObject.getId(), persistentObject);
}
I have also included a snippet from the Spring application-context.xml file that provides a simple way to get AspectJ working in the Spring container.
<aop:aspectj-autoproxy proxy-target-class="true"/>
<bean id="dataAccessAspect" class="org.axiomaticit.aspect.DataAccessAspect"/>
<bean id="dataAccessObject" class="org.axiomaticit.dao.DataAccessObjectImpl"/>
This is a simple example of how Spring, AspectJ and Hazelcast can work together to help reduce “read” calls to a data store. Imagine reducing one application’s “read” executions against a legacy data store while improving read performance metrics. This example doesn’t really answer all questions and concerns that will arise when implementing and utilizing a Hazelcast distributed data cache with Spring and AspectJ, but I think it shows that these technologies can help lower resource utilization and increase performance. Here is a link to the demo project.
SpringOne 2GX 2009 Day Four
Unfortunately, all good things must come to end and that means it is time to pack my things, check-out of my hotel room in NOLA and catch a flight back to Tampa. The good thing is that the excitement of SpringOne / 2GX doesn’t have to end. I am little late to press with completing this post (MacBook battery, sleep, travel, work), but anyone who works with me or who lives with me can tell you that I am still amped about what I saw and experienced at SpringOne / 2GX.
At the beginning of day four, I checked out Hamlet D’Arcy’s presentation on Groovy and OSGI. I have seen a presentation at the Tampa JUG on OSGI, courtesy of my colleague, Vladimir Vivien and Hamlet’s presentation really helped me get a hold of the technology again. He is a wealth of knowledge and a talented software developer / presenter.
One of my favorite presenters, Venkat Subramaniam, discussed design patterns in Java and Groovy. It was a very useful presentation. Venkat is an incredible presenter and the content of his presentations are right on point. He knows what he is doing!
After lunch, I checked out Jeff Brown’s (SpringSource / Grails) presentation on using Grails without a browser. I really enjoyed Jeff’s presentations all week. It is awesome to hear about a technology that I feel passionate about from the source. As Jeff said, Grails is a Web framework but Grails really offers more that just rapid Web development, it is also a platform. He proved that in his presentation.
SpringOne / 2GX 2009 was a great event. My Rod Johnson bobble-head is already on my desk solving enterprise Java problems. The No Fluff Just Stuff crew and SpringSource hosted a great event, at a great venue, in a beautiful city. Looking forward to the 2010 event.
SpringOne 2GX 2009 Day Three
Day three was an exciting day. I attended an awesome presentation about DSL’s in Groovy presented by Guillaume LaForge. I got to speak with him a bit, he is a great guy. I attended Christophe Coneraets and Jeremey Grelle’s presentation on the technical pieces of Flex and Spring. Flex is great (already knew that), but being able to make remote calls to Spring is where it’s at. Spring’s BlazeDS support is very Spring-like and that means you an leverage your spring knowledge to work with Flex remoting. I checked out Keith Donald’s presentation, “Working with Spring Web Flow”. I really like Web Flow. I like Web Flow with JSF because it makes sense when you have to use JSF and I also like the Web Flow hooks inside of Grails. Hamlet D’Arcy’s presentation, “Legacy Code, Groovy and You”, really spoke to me. Some of us work in environments that need to pay attention to some of his key points on re-factoring/re-writing and TESTING. At the end of the day, I attended “Groovy AST Transformations” with Venkat Subramaniam. First, he is a great speaker/presenter and I look forward to attending most of his presentations because he knows what he is doing. Second, AST transformations look really cool, but I need to let it digest a bit before I dig in. It is a great feature of Groovy, like MOP, but it can also be dangerous, like MOP, if you don’t know what you are doing. I am looking forward to attending “OSGI and Groovy Jump Start”, “Design Patterns in Java and Groovy” and “Grails Without a Browser” on the final day of the event.