Thursday, June 16, 2011

Experimenting with a Groovy Template Engine and PermGen

I had a Groovy application that was using a SimpleTemplateEngine was running out of PermGen space after running for a long period of time. The app was using version 1.7.10 and was running in a Tomcat 6 container.

Load tests consistently showed a linear increase in the PermGen consumption (monitored by JConsole). Originally, the template engine was used to create the template from the template text with every request. Also, the template was injected as a resource to the class using the engine.

After switching the class to create and cache the created template, we were still experiencing an OutOfMemoryError during the load test. Only after removing the use of the engine in its entirety, where we able to observe the PermGen leveling off.

A run of jmap -permstat PID against the application process showed a large number of entries of the form of:

  0x00000000f96bf800      24      233928  0x00000000f7f19558      dead    groovy/lang/GroovyClassLoader$InnerLoader@0x00000000fd784720

To investigate things, I thought I would try to see if I can reproduce the behavior using only a script run by Maven. As I go, I'll record what I see below. To start, I'll use Groovy 1.8.0.

The script will loop and complete a template with every iteration. The first version of the script will use a singe instance of SimpleTemplateEngine, but will call the createTemplate method with every iteration:

  def runs = 5
def templateText = 'Run number: ${runNumber}'
def engine = new groovy.text.SimpleTemplateEngine()

runs.times { i ->
def binding = [runNumber:"$i"]
engine.createTemplate(templateText).make(binding)
}

We'll start the script with verbose class loading on so we see what classes are loaded into PermGen during execution:

  $ export MAVEN_OPTS="-verbose:class"
$ mvn -o exec:java -Dexec.mainClass=TemplateEngine | tee /tmp/out
$ grep SimpleTemplateScript /tmp/out
[Loaded SimpleTemplateScript1 from file:/groovy/shell]
[Loaded SimpleTemplateScript2 from file:/groovy/shell]
[Loaded SimpleTemplateScript3 from file:/groovy/shell]
[Loaded SimpleTemplateScript4 from file:/groovy/shell]
[Loaded SimpleTemplateScript5 from file:/groovy/shell]

We might suspect that behavior since not only are reading the template everytime through the loop. A new version of the script below again uses the same SimpleTemplateEngine instance and only creates the template once:

  def runs = 5
def engine = new groovy.text.SimpleTemplateEngine()
def createdTemplate = engine.createTemplate(templateText)

runs.times { i ->
def binding = [runNumber:"$i"]
createdTemplate.make(binding)
}

With this version, we only see one class load:

  $ grep SimpleTemplateScript /tmp/out
[Loaded SimpleTemplateScript1 from file:/groovy/shell]

This is encouraging, but I want to make sure PermGen truly doesn't increase linerally over time. To do so, I'll add a sleep at the beginning of the script so I can attach JConsole to the Maven process and set the number of runs to a really high number:

  sleep(30000)
println "Starting..."
def runs = 50000

The PermGen graph is pretty jagged in the case where the createTemplate method is called each time through the loop. However, it appears that space was recovered as well so we do not end up running out of space:

To test the version where we only create the template once, I'm going to up the number of runs to 5,000,000 as execution is much faster without the repeated calls to the createTemplate method. The PermGen graph rises quickly but levels off:

So far, based on the verbose class loading and graph results, it looks like things are a definite improvement over what I was seeing in the original applcation. Just to be sure, I'm going to same experiment creating the template only once with version 1.7.0. as well.

With the single instance approach, the PermGen increased at a very slow rate. Using the approach where we call the createTemplate method with each iteration, the graph is again jagged:

At the end of this little experiment, I don't see any significant differences between Groovy 1.7 and 1.8. My work application was running in a Tomcat container which may also factor into things, along with a slightly different JVM version. Outside of the container, while the PermGen does rise with every load of a SimpleTemplateScript class, the memory is recovered.

I'll likely have to do some more experimentation to understand the behavior I was seeing in the original applcation.

Wednesday, April 27, 2011

JMeter Plugin: NonGuiDriver NullPointerException & SOAPException

When using the Maven JMeter Plugin to try and send web service requests, I ran into the following exception:

  Error in NonGUIDriver java.lang.NullPointerException

My jmeter.log presented the following:

2011/04/27 14:20:46 ERROR - jmeter.save.SaveService: Conversion error com.thoughtworks.xstream.converters.ConversionException: org/apache/soap/SOAPException : org/apache/sp/SOAPException
---- Debugging information ----
message : org/apache/soap/SOAPException
cause-exception : java.lang.NoClassDefFoundError
cause-message : org/apache/soap/SOAPException
first-jmeter-class : org.apache.jmeter.save.converters.TestElementConverter.unmarshal(TestElementConverter.java:108)
class : org.apache.jmeter.save.ScriptWrapper
required-type : org.apache.jmeter.protocol.http.sampler.WebServiceSampler
path : /jmeterTestPlan/hashTree/hashTree/hashTree[2]/WebServiceSampler
line number : 741
-------------------------------
2011/04/27 14:20:46 ERROR - jmeter.JMeter: java.lang.NullPointerException
at org.apache.jmeter.gui.tree.JMeterTreeModel.addSubTree(JMeterTreeModel.java:91)
at org.apache.jmeter.JMeter.run(JMeter.java:728)
at org.apache.jmeter.JMeter.startNonGui(JMeter.java:706)
...

The solution was to add a dependency on soap:soap:2.3 to my plugin definition:

      <plugin>
<groupId>org.apache.jmeter</groupId>
<artifactId>maven-jmeter-plugin</artifactId>
<version>1.0</version>
<configuration>
<reportDir>${reportDir}</reportDir>
</configuration>
<dependencies>
<dependency>
<groupId>soap</groupId>
<artifactId>soap</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
</plugin>

After adding the dependency, the tests ran fine:

  Starting the test @ Wed Apr 27 14:42:57 EDT 2011 (1303929777586)
Tidying up ... @ Wed Apr 27 14:42:59 EDT 2011 (1303929779839)
... end of run

Sunday, April 17, 2011

Fantom: Getting FWT to run on Linux 64-bit

Today I decided to start playing around with the Fantom language. After working through a couple of examples on the Hello World page, I ran into a problem running the example that uses the Fantom Widget Toolkit on my 64-bit machine.

After following the instructions from the Fantom Setup Page, I set my FAN_HOME in my .bash_profile to:

  FAN_HOME=/opt/fantom-1.0.58

I later tried running the Hello FWT example below:

  using fwt
class FwtHello : Test {
Void main() {
Window { Label { text = "Hello world" }, }.open
}
}

Which produced the following error:

  hello $ fan hello::FwtHello
sys::Err: java.lang.UnsatisfiedLinkError: Cannot load 32-bit SWT libraries on 64-bit JVM

I found a swt.jar here:

  /opt/fantom-1.0.58/lib/java/ext/linux-x86/swt.jar

The setup page recommended running fan to get a read on the platform:

 $ fan -version | grep platform
fan.platform: linux-x86_64

I created a directory, linux-x86_64, under java/ext, and copied the swt.jar downloaded from the Eclipse site to it.

Afterwhich, the example ran fine.

Tuesday, April 12, 2011

Linux Mint 10 & Intel Centrino Wireless Card

Today, I got a new laptop and chose to install Linux Mint 10. While the wired connection worked after the install, I had a little trouble with the wireless card, a Intel Centrino Advanced-N 6200.

For my Google searches, I verified the type of card using:

  $ lspci -v
...
01:00.0 Network controller: Intel Corporation Device 008a (rev 34)
Subsystem: Intel Corporation Device 5325
Flags: bus master, fast devsel, latency 0, IRQ 48
Memory at d1600000 (64-bit, non-prefetchable) [size=8K]
Capabilities: <access denied>

In short, to fix the problem I had to upgrade to kernel version 2.6.38 from 2.6.35 and install a driver.

To upgrade my kernel, I followed the helpful instructions here: Upgrade Instructions.

After a reboot, the splash screen and dmesg presented the following complaint:

  [   15.131819] iwlagn 0000:01:00.0: request for firmware file 'iwlwifi-6000g2b-5.ucode' failed.
[ 15.131870] iwlagn 0000:01:00.0: no suitable firmware found!

To resolve this issue, I download the driver, iwlwifi-6000g2b-ucode-17.168.5.2 from Intel Wireless WiFi Link drivers for Linux.

After unpacking the tar, I copied the driver to /lib/firmware:

  iwlwifi-6000g2b-ucode-17.168.5.2 $ sudo cp iwlwifi-6000g2b-5.ucode /lib/firmware

After another reboot, I was able to use my wireless card. Hopefully, this post will help anyone else in a similar situation.

Wednesday, April 6, 2011

Groovy 1.8: Playing with the new @Canonical Transformation

Groovy 1.8 introduces some new transformations through the use of annotations. One I came across that I wanted to investigate was @Canonical which gives you an implementation of equals(), hashCode(), and toString(), along with tuple constructors.

These transformations can also be applied individually through the @EqualsHashCode, @ToString(), and @TupleConstructors respectively.

As I have no experience with tuple constructors, I hope to take a look at that one later. On the other hand, I have written a fair share of equals() and toString() methods (some better than others) so I'm always looking for a good shortcut for both.

To start, I took a look at @EqualsAndHashCode. I wrote the simplest of classes that has one property and tried to see if comparing two instances with the same value would work. Since the class does not override equals(), this failed as one would expected:

  class Person {
int age
}

def p1 = new Person(age:30)
def p2 = new Person(age:30)

assert p1 == p2

The failure presented by running the script:

  Assertion failed: 

assert p1 == p2
| | |
| | Person@3040c5
| false
Person@1ec459b

Adding a simple equals() method does the trick for now as the assertion passes:

  class Person {
int age

boolean equals(o) {
age == o.age
}
}

We can use the @EqualsAndHashCode annotation and remove our override of equals(). Here the assertion will stll pass:

  import groovy.transform.EqualsAndHashCode

@EqualsAndHashCode
class Person {
int age
}

The next question I had was whether or not there was a way to exclude some properties from taking part in the comparsion. Turns out we set the annotation to ignore certain properties using excludes.

Let's add a second property, ssn, and give both our Person instances different values:

  @EqualsAndHashCode(excludes='ssn')
class Person {
int age
String ssn
}

def p1 = new Person(age:30, ssn:'1')
def p2 = new Person(age:30, ssn:'2')

assert p1 == p2

No failures here. Turns out the same can be accomplished by declaring the ssn as private:

  @EqualsAndHashCode
class Person {
int age
private String ssn
}

Now let's add @ToString into the mix:

  import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

@EqualsAndHashCode
@ToString
class Person {
int age
String ssn
}

def p1 = new Person(age:30, ssn:'1')
def p2 = new Person(age:30, ssn:'1')

assert p1 == p2
println p1

The above script prints out:

  Person(30, 1)

This is definitely more helpful than the default we get if we don't override toString():

  Person@1e092

But it could be improved perhaps if we tell the annotation to include the name of the properties in the created String:

  @ToString(includeNames=true)

We now get the more helpful:

  Person(age:30, ssn:1)

Now let's see what happens if we replace both annotations with @Canoncial:

  @Canonical
class Person {
int age
String ssn
}

def p1 = new Person(age:30, ssn:'1')
def p2 = new Person(age:30, ssn:'1')

assert p1 == p2
println p1

The assertion passes, but we now are reverted to the String representation that didn't include the field names. An attempt to add the includeNames setting failed with an exception:

  'includeNames'is not part of the annotation groovy.transform.Canonical

I found that if added the @ToString annotation back, we get the display we want.

  @Canonical
@ToString(includeNames=true)
class Person {
int age
String ssn
}

So it appears that @Canonical applies both the @EqualsAndHashCode and @ToString annotations, but applies the defaults for each. To be more selective in the behavior of the individual annotations, we need include them individually.

There look's like there are more options for each of the transformations we've used so far. I found the Javadoc for version 1.8-rc-3 in the source release to be very helpful. A link should be made availabe on the Groovy downloads page when 1.8.0 is released.

Installing Groovy 1.8: NoClassDefFoundError: GroovyStarter

Today, I tried installing Groovy 1.8-rc-3 so I could play with some of the new features of the language. On my Ubuntu machine, the current version I had installed from the repositories was 1.7.6, which in itself is pretty recent:

  $ groovy --version
Groovy Version: 1.7.6 JVM: 1.6.0_13

Since I installed Groovy through the Ubunutu repositories using apt-get, the groovy executable was already on my path:

  $ which groovy
/usr/bin/groovy

As I did not want to mess with the default install, to get 1.8 into the picture, I would have to install things manually. After unzipping the install, I expected to be able to run it easily, but I ran into an exception:

  $ /opt/groovy-1.8.0-rc-3/bin/groovy --version
Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/groovy/tools/GroovyStarter
Caused by: java.lang.ClassNotFoundException: org.codehaus.groovy.tools.GroovyStarter
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
...
Could not find the main class: org.codehaus.groovy.tools.GroovyStarter. Program will exit.

Of course by instinct, I went to Google, but before I went to far, it hit me to check GROOVY_HOME:

  $ echo $GROOVY_HOME
/usr/share/groovy

After changing the value to my new install, I was able to verify the install:

  $ export $GROOVY_HOME='/opt/groovy-1.8.0-rc-3'
$ /opt/groovy-1.8.0-rc-3/bin/groovy --version
Groovy Version: 1.8.0-rc-3 JVM: 1.6.0_13

Nothing groundbreaking here, but hopefully I won't forget about this the next time and jump to a search page.

Saturday, February 26, 2011

Spring JMS & Groovy: Sending and Receiving Messages

I recently wrote some code using Spring JMS to send a JMS text message to a queue and to receive a response. The examples in the Spring documentation use Java of course to send and receive the messages. Here I wanted to demonstrate how the code can be simplified using Groovy .

In order to send and receive the messages, a JmsTemplate object is required. In a typical case, the template would be configured thru Spring and injected. Here, I'm going to omit the creation process here for brevity's sake, especially given any example would be specific to a particular JMS provider, but the documentation does a great job explaining how to accomplish the creation of a template using Spring.

When sending a text message, we'll need a list of parameters:

  1. The text the message should contain.
  2. The name of the queue to place the request on.
  3. The name of the queue to have the response sent to.
  4. A correlation ID so that we can receive the response created for the message being sent.

Since its simple to get out of the way here, a correlation ID can be created by creating a unique String using:

  def createCorrelationId() { UUID.randomUUID().toString() }

We'll also need a method to create a MessageCreator to give to the JmsTemplate when sending the mesage. A Java example of doing so my look like this using an inner class:

    void sendMessage(JmsTemplate jmsTemplate, String text, String requestQueue, String responseQueue, String correlationId) throws JMSException { 
jmsTemplate.send(requestQueue, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
TextMessage message = session.createTextMessage(text);
return message;
}
});
}

This example can be made easier on the eyes by using as in Groovy since MessageCreator is an interface (we also get the benefit of not needing the throws declarations):

    def sendMessage(jmsTemplate, text, requestQueue, responseQueue, correlationId) { 
jmsTemplate.send(requestQueue, { session ->
session.createTextMessage(text)
} as MessageCreator)
}

Or we can store the MessageCreator in a variable:

    def sendMessage(jmsTemplate, text, requestQueue, responseQueue, correlationId) { 
def messageCreator = { session ->
session.createTextMessage(text)
} as MessageCreator

jmsTemplate.send(requestQueue, messageCreator)
}

In order to set the response queue and correlationID though, we'll need access to the text message created by the Session provided by the JmsTemplate:

    def correlationId = createCorrelationId() 

def sendMessage(jmsTemplate, text, requestQueue, responseQueue, correlationId) {
def messageCreator = { session ->
session.createTextMessage(text)
message.with {
setText request
setJMSCorrelationID correlationId
setJMSReplyTo session.createQueue(responseQueue)
}

} as MessageCreator

jmsTemplate.send(requestQueue, messageCreator)
}

Since the MessageCreator is defined by a closure, we can extract a method out that the closure will have access to when its executed to create the text message:

    def correlationId = createCorrelationId() 

def createMessage(session, text, responseQueue, correlationId) {
def message = session.createTextMessage(text)
message.with {
setText text
setJMSCorrelationID correlationId
setJMSReplyTo session.createQueue(responseQueue)
}
message
}

def sendMessage(jmsTemplate, text, requestQueue, responseQueue, correlationId) {
def messageCreator = { session ->
createMessage(session, request, responseQueue, correlationId)
} as MessageCreator

jmsTemplate.send(requestQueue, messageCreator)
}

Now that we have a method for sending the request message, we need a way to grab the response. A Java example:

    void receiveResponse(JmsTemplate jmsTemplate, String responseQueue, String correlationId) throws JMSException {
String selector = "JMSCorrelationID='" + correlationId + "'";
Message message = (TextMessage) jmsTemplate.receiveSelected(parameters.getRetrieveFromQueue(), selector);
String response;
if (message != null) {
response = message.getText();
}
return response;
}

A Groovier way:

  def receiveResponse(jmsTemplate, responseQueue, correlationId) { 
def selector = "JMSCorrelationID='$correlationId'"
def message = (TextMessage)jmsTemplate.receiveSelected(responseQueue, selector)
message?.getText()
}

In both reception examples, the fact we may not get a response or text in the response. This is something the caller can deal with or we can modify the examples to throw an exception:

   def receiveResponse(jmsTemplate, responseQueue, correlationId) {
def selector = "JMSCorrelationID='$correlationId'"
def message = jmsTemplate.receiveSelected(responseQueue, selector) as TextMessage
def response = message?.getText()

if (!response) {
throw new Exception("Got nothing!") // in practice would likely throw a more apt or custom exception
}

response
}

To put it all together, the code examples above can be aggregated to a class:

class JmsMessageSender {

def createCorrelationId() { UUID.randomUUID().toString() }

def createMessage(session, text, responseQueue, correlationId) {
def message = session.createTextMessage(text)
message.with {
setText text
setJMSCorrelationID correlationId
setJMSReplyTo session.createQueue(responseQueue)
}
message
}

def sendMessage(jmsTemplate, text, requestQueue, responseQueue, correlationId) {
def messageCreator = { session ->
createMessage(session, request, responseQueue, correlationId)
} as MessageCreator

jmsTemplate.send(requestQueue, messageCreator)
}

def createSelectorFrom(correlationId) {
"JMSCorrelationID='$correlationId'"
}

void receiveResponse(jmsTemplate, responseQueue, correlationId) {
def selector = createSelectorFrom(correlationId)
def message = jmsTemplate.receiveSelected(responseQueue, selector) as TextMessage
def response = message?.getText()

if (!response) throw new Exception("Got nothing!")

response
}
}

A client code example using the above class through three calls:

    JmsTemplate jmsTemplate // injected
def correlationId = messageSender.createCorrelationId()
messageSender.sendMessage(jmsTemplate, text, requestQueue, responseQueue, correlationId)
def response = messageSender.receiveResponse(jmsTemplate, responseQueue, correlationId)

Thanks for reading!