Friday, October 23, 2009

JMS and Spring 3.0 rc1 and some recommendations

So, I got to play with Spring and ActiveMQ this sprint for a little application we are writing at work. I've been looking for a project which could use JMS for a while, and this one seemed to fit the bill perfectly. Like I said in my last post, I found the experience doing the configuration to be very straight forward and there were lots of information out there to set this up (especially Spring in Action).

The few pieces that I found scattered about in many places which I would recommend are:
  1. Use a pooled connection factory with Spring. The JMS Template is rather heavy as it opens and closes a connection every message as well as other over head. A serious waste and ActiveMQ recommends using theirs.
  2. With the message listener, be sure to include the destroy-method="shutdown" attribute as without it, there is no guarantee that your consumers will be terminated correctly (a problem we ran into without realizing it for a few days)
  3. Add maxConcurrentConsumers to increase the number of consumers to help process the messages. This will dynamically change the number of consumers based on need and has tested to be a big win for us.
Otherwise, this is really simple to get up and running. It has been a HUGE help in terms of performance and seems to be very stable under our load tests thus far. I included my configuration below in case you would like to use it as a template.

Some resources:
http://activemq.apache.org/
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/ch21.html

<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
   <constructor-arg index="0" value="${activemq.destination.name}">
</bean>

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
   <property name="connectionFactory" ref="jmsFactory">
   <property name="defaultDestination" ref="pruneDestination">
</bean>

<bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" method="stop">
   <property name="connectionFactory">
   <bean class="org.apache.activemq.ActiveMQConnectionFactory">
      <property name="brokerURL" value="${activemq.broker.url}">
   </bean>
   </property>
</bean>

<bean id="messageListener" class="some.path.to.a.MessageListener">
   <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer" method="shutdown">
   <property name="connectionFactory" ref="jmsFactory">
   <property name="destination" ref="destination">
   <property name="messageListener" ref="messageListener">
   <property name="maxConcurrentConsumers" value="5">
</bean>

XStream and Spring 3.0

I have spent my last three weeks happily using Spring 3 rc1 getting to know some new features and using some old features that I have not had the opportunity to use before. Specifically I enjoyed the greatly reduced xml used when using annotations. Also, the REST handling in the controllers is worth the move.

However, I ran into a bit of problem when trying to use Spring's ContentNegotiatingViewResolver to return XML. I quickly got Spring wired to use a Marshalling view and I chose the XStreamMarshaller. Everything was going great. Development was quick and easy. I had JSON and XML responses going quickly (I did find a bug with declaring the defaultContentType, but they say they will fix this asap). I was able to focus on the business problem I was trying to solve instead of getting bogged down in framework muck.

Then I noticed a slight problem with my results in XML, there was no XML declaration in the response ( was missing). Going over the documentation lead me to the fact that the MarshallingView assumes that the Marshaller knows how to write the response document, but in this case, the Marshaller is an XStream implementation, and the XStream guys explicitly say "this is not my problem".

Seems like a case of the hot potato being passed back and forth. I didn't find anything in the documentation or forums on how to fix this. It feels like this should just be a boolean or String property to be set on the XStreamMarshaller which Spring provides, but it is not (maybe in 3.1?).

So I created a hack to fix this, I extended XStreamMarshaller and over wrote the following method:

/**
* {@inheritDoc}
*/
@Override
protected void marshalWriter(Object graph, Writer writer) throws XmlMappingException, IOException {
writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
super.marshalWriter(graph, writer);
}

My config file looks like this:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg ref="xstream" />
</bean>
</list>
</property>
<property name="defaultContentType" ref="jsonMediaType" />
<property name="ignoreAcceptHeader" value="true" />
</bean>

<bean id="xstream" class="some.path.to.your.class.which.extends.XStreamMarshaller" >
<property name="autodetectAnnotations" value="true" />
<property name="converters">
<array>
<bean id="someConverter" class="some.path.to.your.class.which.implementds.Converter" />
</array>
</property>
</bean>

It feels hacky, and I hate the solution, but I couldn't find another way to accomplish this task. Am I totally missing something here? Is there a simpler solution? Anyway, I hope this helps someone out down the line.

Sunday, August 30, 2009

Why would you go to a conference that you have to pay for?

A co-worker of mine asked me last week, “You are paying for NFJS (http://www.nofluffjuststuff.com/)? Why would you do that? Why would you go to a conference that you have to pay for?”

This took me aback. How do I answer this? Where do I begin. Was he missing the big picture of being involved with technology? This guy is a very bright guy. Has his Masters from MIT, has worked on open source projects, and continually impresses me with his development skills.

I first began to list out the items laid out in Jared Richardson's talk about Career 2.0 (http://qik.com/video/1009098) which I had just happened to catch at NEJUG (http://www.nejug.org) the previous week. I suggest following the link on qik.com and watching that video as he is a much better presenter than I and can make his case much more eloquently than I could here.

However, one piece of Jared's talk that I felt was missing regarded money. During my college career, I spent over $100,000 on tuition and I didn't even get a degree in Computer Science (Geography for those interested). The biggest lesson I learned coming out of school was that I have to continue to learn or that $100,000 might as well have been thrown away.

So how can I continue to learn? I read books, go to lectures, listen to podcasts, do some side projects to learn new languages, and go to conferences. Conferences tend to be a concentrated time to find out what languages to learn, what practices to improve upon, and what books to read.

I believe the question should not be, “Why am I paying for NFJS?”. The question should be, “How can I afford not to go to NFJS?” If my company is not going to pay for me to improve, who will? How do not waste the initial $100,000 investment?

If you know a better way, then please let me know.

Wednesday, August 19, 2009

Tomcat Sessions and Java objects

Just ran into a problem today where we had a Java Object with transient member variables put into Tomcat's session. According to this thread in Java Ranch (http://www.coderanch.com/t/86379/Tomcat/Problems-disabling-Session-Persistence-Manager), objects put into session should implement Serializable. Member variables which are transient will not be preserved when being retrieved from session, and should be commented as such. This has lead to a few bugs in my code and was a gotcha that I never really thought of before, but makes perfect sense. Hopefully next time I will remember.

Friday, August 14, 2009

How to decode utf-8 entities in javascript

Let's say a request comes back from the server with ø in the response (which is gzip encoded because it is an AJAX call). A quick and dirty way to decode this entity in javascript is:

var encodedText = 'G&#248;&#248;&#248;se'

var temp = document.createElement('span');
temp.innerHTML = encodedText;
var decodedText = temp.innerHTML;
temp = null;

this will set decodedText to: 'Gøøøse'

Introduction

This blog space is going to be used to hold technical finds, solutions to problems I have been running into and things which I don't want to keep trying to remember. I will hopefully be entering information often, and maybe you will find solutions or useful links here as well.

I hope that some of the things written here are useful to others as well.

Jon