Wednesday, December 3, 2008

Spring, Filters and Configuration easier than you think.

So I needed to add a filter for some cool stuff in my application.

First off I needed to get my filter to play nicely with Spring, so I needed to do the following in my web.xml

<filter>
<filter-name>myCoolNewFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>myCoolNewFilterSpringBean</param-value>
</init-param>
</filter>

So then I go ahead and open up my applicationContext.xml file and wire up the bean like normal

<bean name="myCoolNewFilterSpringBean" class="com.mycompany.filter.MyCoolNewFilter" />

Notice that the bean name in the app context matches the param-value in the filter config: myCoolNewFilterSpringBean

Then instead of trying to do URL patterns for the config of the filter I just tried the following:

<filter-mapping>
<filter-name>myCoolNewFilterSpringBean</filter-name>
<servlet-name>dispatcher</servlet-name>
</filter-mapping>

Which maps this filter to all filter all calls being directed to my dispatcher servlet! No nasty or convoluted URL patterns... Just easily readable servlet names!

Kill your database! Pt. 2

Friend of mine beat me to it... check out the post Kill Your Database with Terracotta over at Will Code 4 Beer.

It is an interesting article challenging the idea that we need a database to begin with. There may be an excuse for a database in some cases, but for many applications it is overkill. When you need a super fast, scalable application to hold on to just enough data then Terracotta can store your objects to disk and allow your entire cluster to share state through the shared Heap. It is an interesting read, so go check it out.

Thursday, November 20, 2008

Kill your database!

Share the heap! For free! Across the farm! Yes!

I am going to put something together over the next couple of weeks that will increase performance, scalability and decrease downtime!


And no I do not work for these guys.

Tuesday, October 7, 2008

...

"If company culture was checked into CVS, I would be the first to commit." -- what.else October 2008

Saturday, September 20, 2008

Tip of the Day! || /etc/hosts is your friend

From time to time I find myself having to deal with tracking down the root cause of a bug in production. While this doesn't happen often, it is something that all of us have to deal with. Today I found myself in that very situation, where I needed to try and figure out the root cause of an issue people all over the world are experiencing.

After a number of hours it finally occurred to me to fire up my server on my dev machine and then edit my /etc/hosts file. Duh! Route all the requests to the prod server back into my local machine! This worked well in my case since I was dealing with a partner site, which uses web services through a flash client. ( I wrote the web services not the flash ). This was pretty much the best/only way to track down the issue, since we were not seeing anything unusual on the server itself. I could go and experience the partner site as anyone would but then when it came to the issue at hand I needed to simulate a particular situation, which I was able to do. So while this is not ground-breaking ( I know ) it is just something to keep in mind. Had I done this sooner I wouldn't have had to work on the weekend. Oh well...


This post brought to you by Anchor Steam!

Friday, July 25, 2008

Externalization

So I am working on a project at work using Java 6, Spring ( DI and MVC ), ehcache, SOAP(Axis), ibatis, and some other cool stuff. But that is the core of it. Anyways. Early on some decisions were made to make so decisions based on tracking parameters passed in by the client of the web application. So lets say request parameter foo would have known values of a,s,d,f...N and so on. But these were always going to be known. Well, of course this decision by the TEAM has been forgotten and I needed a way to add flexibility to the application configuration so that when new "foo's" are added, the configuration could be updated to handle it.

My initial reaction was:

"Well, I could have the values/config stored in the database and then just cache them."



But that solution would require days because I would have to create the tables, get them ok'd by the db ops team, have them put in the different environments( test, integration, stage, and then finally production ). Then on top of that I would have to create some sort of tool to manage the values in the table so that they could be updated as needed. Then I would have to secure the the admin page for the config management. And so on and so forth.

Then it occurred to a co-worker and I that we could just externalize the Spring Bean definition and cache it for a set amount of time ( and of course relying on the last good configuration if the new one fails ). The external config for the Spring Bean could then live anywhere ( local file system, or over http on a server somewhere ).

This of course was by far the most flexible and convenient way of dealing with the situation. So here is how it works.

Step 1: Create Factory.


public class ServiceFactoryFactoryContextLoader
implements ApplicationContextAware, IServiceFactoryFactoryContextLoader
{
private ApplicationContext parentContext;
private IServiceFactory serviceFactory;
private String location;

public IServiceFactory getServiceFactory() {
String [] configs = new String[]{location};
ApplicationContext applicationCtx = new ClassPathXmlApplicationContext(configs,true, parentContext );
try {
serviceFactory = (IServiceFactory)applicationCtx.getBean("serviceFactory");
} catch (Exception e) {
Logger.getLogger(this.getClass()).error("Uh... Houston we have a problem... Remote Config is not good", e);
}
return serviceFactory;
}

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

public void setLocation(String location) {
this.location = location;
}
}


Step 2: Enter the JNDI config for location of your externalized resource in the applicationContext.xml:

<jee:jndi-lookup id="serviceFactoryConfig" startup="true"
name="conf/serviceFactoryConfig"
ref="true"
cache="true"></jee:jndi-lookup>



Step 3: Wire factory up in applicationContext.xml

Set up the ServiceFactoryFactoryContextLoader with the cache proxy of course so that we can cache the retrieval and creation of the object. The property 'location' gets injected with the JNDI config value for the location of the externalized resource. And the cache:proxy allows me t cache any method beginning the 'get'. I am using ehcache for my caching but you can use others if you want/need to.

<bean id="serviceFactoryTarget"
class="com.foo.bar.factory.ServiceFactoryFactoryContextLoader">
<property name="location" ref="serviceFactoryConfig" />
</bean>
<cache:proxy id="serviceFactory" refId="serviceFactoryTarget">
<cache:caching methodName="get*" cacheName="serviceFactoryTarget" />
</cache:proxy>



Step 4: Pull the Bean definition out of the applicationContext.xml and into its own config with the Spring beans tag and xmlns declarations.


<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="serviceFactory" class="com.foo.bar.service.ServiceFactory">
<property name="lookups">
<map>
<entry key="default">
<bean class="com.foo.bar.service.ServiceLookupKey">
<property name="var1" value="foo" />
<property name="var2" value="bar" />
<property name="resourceExt" value="default" />
</bean>
</entry>
<entry key="bar">
<bean class="com.foo.bar.service.ServiceLookupKey">
<property name="var1" value="baz" />
<property name="var2" value="xyz" />
<property name="resourceExt" value="bar" />
</bean>
</entry>
</map>
</property>
</bean>
</beans>



And of course you need to define the JNDI values however you want.

So now that the application is configured we can launch the application and once the ServiceFactoryFactoryContextLoader.getServiceFactory() is called the app will make a call out to the externalized location to get the config, load it with the parent context ( which in this case is the applicationContext ) and then you can make the call to get the bean in the externalized config from Step 4 ( "serviceFactory" ). And there it is... the externalized config is now set so that I can host the config where ever I want it; on the local file system somewhere or over http on another server.





Friday, June 20, 2008

jQuery + JSON == bliss

So I have had the need to work with some more javascript, dhtml and ajax user interactions and have found the the amazing library jQuery. I know this isn't new and tons of people are using it, but I have just recently had a need for something more robust and extensible than prototype and script.aculo.us.

I think the coolest thing about jQuery is that people are writing plugins. This is extremely useful when you are just trying to get something done and there is just a plugin you can use that does what you want to do.

Simple plugins like the DOM Element Creator plugin are just the sort of things that are amazing. Anything that I can use that just makes DOM manipulation easier is much appreciated.

The other thing that is pretty nifty is the jQuery UI stuff that they have going. Definitely check out the demos, there is some cool stuff, especially the carousel they have for the available demos. Just check it out. Pretty impressive.