Archive for the ‘ejb3’ Category

Test your EJBs with JMeter

Monday, December 22nd, 2008

Note: This is my first blog post on my newly upgraded Wordpress blog (prior to thijaguar-tachometer.jpgs, I used Blogger). Hopefully everything goes OK!

Sometimes it’s helpful to do some performance benchmarks on your EJBs. There are a few different ways to do this, but I’ve found that Apache’s JMeter is an excellent tool for benchmarking. Unfortunately, JMeter doesn’t come with a general-purpose sampler for testing arbitrary EJBs. Luckily, it isn’t very difficult to create one.

For this article, I’m using the JBoss application server to host my EJBs. The process for using other containers should be quite similar.

1.) Create a factory to lookup your EJBs.

The first thing that you’ll probably want to do is create a simple singleton factory class to create instances of your EJB client for your test. I use something like the following:

public class MyServiceFactory {
  private static final Log log = LogFactory.getLog(MyServiceFactory.class);
  private static MyService service;
  private static MyServiceFactory me;
 
  private MyServiceFactory() { }
 
  static {
    MyServiceFactory.me = new MyServiceFactory();
  }
 
  public static MyServiceFactory getInstance() {
    return MyServiceFactory.me;
  }
 
  public MyService getService() {
    if (MyService.service == null) {
      // Get the remote interface of the music search service
      try {
        log.info("Loading the service...");
 
        // JNDI the old-fashioned way:
        Context ctx = new InitialContext();
        service = (MyService)ctx.lookup("MyAction/remote");
        if (service == null) {
          log.error("Didn't get the service!");
        }
      } catch (NamingException e) {
        log.error("Error looking up the remote service", e);
        return null;
      }
    }
    return service;
  }
}

2.) Write the test

Next, we’ll need to write the test itself. To do this, we’ll extend the AbstractJavaSamplerClient class in JMeter’s org.apache.jmeter.protocol.java.sampler package. This abstract class has a runTest method that we will override, and this method implements the actual test. We will also override the getDefaultParameters method to provide some reasonable defaults values which will be displayed in JMeter’s GUI application.

package us.mikedesjardins.demo.jmeter;
 
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
 
public class DigitalContentServiceEJBTestSampler extends AbstractJavaSamplerClient {
  public SampleResult runTest(JavaSamplerContext context) {
    SampleResult results = new SampleResult();
    MyService service = MyServiceFactory.getInstance().getService();
 
    results.sampleStart();
    Long param1 = context.getLongParameter("PARAM_1");
    String param2 = context.getStringParameter("PARAM_2");
 
    MyResult result = service.myMethod(param1, param2);
    if (result != null) {
       results.setSuccessful(true);
       results.setResponseCodeOK();
       results.setResponseMessage("'myResult:" + myResult);
    } else {
       results.setSuccessful(false);
    }
    results.sampleEnd();
    return results;
  }
 
  @Override
  public Arguments getDefaultParameters() {
    Arguments args = new Arguments();
    args.addArgument("PARAM_1", "4815162342");
    args.addArgument("PARAM_2", "Iculus");
    return args;
  }
}

3.) Setup JMeter

JMeter’s extra libs directory is ${JMETER_INSTALL_LIB}/lib/ext. Into that directory you will need to copy any jars that your EJB client will need. In you’re using JBoss, you will want to copy the jbossall-client.jar into that directory as well (for the JNDI client and other remoting goodies) – presumably other application servers have similar client jar files available.

When you fire up JMeter, your new sampler should appear in the Samplers menu. Enjoy!

Photo Credit: Bill Jacobus

Configure Spring to automatically re-connect to your EJBs

Friday, October 24th, 2008

If you have a service that is a client of a remote EJB, you may have run into the situation where the EJB server shuts down and restarts. When this happens your EJB client may need to be restarted as well, in order to re-discover and reconnect to the EJBs; otherwise you’ll end up with connection exceptions in the client.

If you’re using Spring to autowire your EJB clients, it’s quite easy to configure the service so that the home interface will refresh on connection failures. Note that if you’re using EJB3, you will need to upgrade to at least version 2.5.5 of Spring. There is a bug in earlier versions of Spring which prevented this technique from working with EJB3.

In your spring file, make sure you configure your slsb references to have cache-home disabled, and refresh-home-0n-connect-failure thusly:

<jee:remote-slsb id="myService" jndi-name="MyService/remote"
        business-interface="us.mikedesjardins.services.MyService"
        cache-home="false" lookup-home-on-startup="false"
        home-interface="us.mikedesjardins.services.MyService"
        resource-ref="false" refresh-home-on-connect-failure="true">
    <jee:environment>
           <!-- Include any relevant environment settings here -->
    </jee:environment>
</jee:remote-slsb>

With this, you should be able to restart your EJB hosts without needing to restart your EJB clients!

Photo Credit: Wanko


© 2010 Mike Desjardins. All Rights Reserved.