Monday, September 28, 2009

Camel Castor component

I have mentioned several times in this blog that Castor is one of my favorites option for java OXM. Recently I have contributed to create a castor component for Apacahe Camel project, this will enable to use Camel's powerful routing features together with Castor framework.

  1. Camel-castor data format simplify development work and reduce required time and effort. You can use OXM features without writing any Castor Specific codes with a mapping file or in a simple case without any mapping files.
  2. You have extra advantage to use powerful features of Camel. As an example you can convert your XML data into Java bean using camel-castor component and then possible to convert the same bean into a JMS or a Mail message using other existing fetures of Camel very easily.
This component is officially available with Camel 2.1 version but if you want it is possible to try out using 2.1 snapshots , you can download them from here or simply use Maven.

Also this wiki page describe some of the example scenarios and configuration options. I will plan to publish a full detail example to illustrate usage of this component in near future.

Tuesday, September 08, 2009

Testing Spring injected Servlets

Writing unit test cases is a really necessary step with the agile practices, but writing test cases for Servlets is little bit hard; because those are intend to run inside a container. There are few test frameworks such as Apache Cactus , HttpUnit, XMLUnit to facilitate to these requirements, specially ServletUnit provided by HttpUnit is a very smart and easy way to test Servlets.

But ServletUnit does not facilitate to inject Spring ApplicationContext into Servlet Context and hence testing Spring injected Servlets is not possible with ServletUnit (AFAIK).

But Spring-mock package provide some of the mock web component such as MockHttpServletRequest , MockHttpServletResponse and MockServletContext ..etc to test web applications. Also Spring test package provide features like auto-wiring, transactional supports etc. It is possible to use those two packages to test Spring injected Servlets.

Spring Test class such as AbstractDependencyInjectionSpringContextTests
Can be used to retrieve ApplicationContext for our test cases then we can set it in to a MockServletContext object as a attribute with key value WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE so that the Spring context is available to our servlet.

Normally in a container WebApplicationContextUtil is used to retrieve WebAplicationContext through the ServletContext using above WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE attribute.


One of the basic problem with this approach is WebApplicationContextUtils only accepts ApplicationContext classes that implement the WebApplicationContext interface, here AbstractDependencyInjectionSpringContextTests returns a org.springframework.context.support.GenericApplicationContext object as the ApplicationContext . Since GenericApplicationContext doesn’t implement the WebApplicationContext interface we can’t use this ApplicatioContext.

There are few remedies here.

1. Instead of Spring test package use kind of a WebApplicationContext class to load the test configuration. I tried with XmlWebApplicationContext but after several attempts I gave up.


String[] ctx= new String[]{"/WEB-INF/app.xml"};
webApplicationContext = new XmlWebApplicationContext();
webApplicationContext.setConfigLocations( ctx);
webApplicationContext.setServletContext(
new MockServletContext(
new FileSystemResourceLoader() ) );
webApplicationContext.refresh();


2. Use Spring test package to load the ApplicationContext (e.g – AbstractDependencyInjectionSpringContextTests ) and manually copy the bean definitions in to a WebApplicationContext object and set it in to the ServletContext.


Above second approach is worked with me and I used GenericWebApplicationContext as my WebApplicationContext. If you are interested in go through the following code segments.


This is a simple servlet I used to test, it utilize Spring bean called “helloService”.


public class SimpleService extends HttpServlet {

private HelloService helloService;

public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
// retrieve Spring AppContext through the ServletContext.
ServletContext servletContext = servletConfig.getServletContext();
ApplicationContext applicationContext = WebApplicationContextUtils
.getWebApplicationContext(servletContext);
// retrieve Spring service
helloService = (HelloService) applicationContext.getBean("helloService");
}

public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/xml");
PrintWriter pr = resp.getWriter();
String text = req.getParameter("text");
System.out.println(" recived : " + text);
pr.println(helloService.doService(text));
pr.flush();
pr.close();

}

}


Now we can create a reusable abstract Test class for our approach.

public abstract class AbstractSpringServeletTest extends
AbstractDependencyInjectionSpringContextTests {

private ServletConfig servletConfig;

protected abstract void init() throws Exception;

protected void onSetUp() throws Exception {

ServletContext sctx = new MockServletContext();
servletConfig = new MockServletConfig(sctx, "simple");
sctx.setAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
getWebApplicationContext());
init();

}

protected WebApplicationContext getWebApplicationContext() {
ApplicationContext ctx = getApplicationContext();
System.out.println(ctx.getClass().getName());
GenericWebApplicationContext wac = (GenericWebApplicationContext) BeanUtils
.instantiateClass(GenericWebApplicationContext.class);

String[] defNames = ctx.getBeanDefinitionNames();
for (String defName : defNames) {
wac.getBeanFactory().registerSingleton(defName,
ctx.getBean(defName));
}
return wac;

}

protected ServletConfig getServletConfig() {
return servletConfig;
}

protected ServletContext getServletContext() {
return servletConfig.getServletContext();
}

}


Here I derived AbstractSpringServeletTest class from AbstractDependencyInjectionSpringContextTests but it is possible to derive from any other test classes according to the requirements. Finally we can write concrete TestCase for out SimpleServlet as follows.


public class ServletTest extends AbstractSpringServeletTest {

private SimpleService simpleServlet;

protected String[] getConfigLocations() {
return new String[] { "classpath:app.xml" };
}

public void init() throws Exception {
simpleServlet = new SimpleService();
simpleServlet.init(getServletConfig());

}

public void testDoGet() throws Exception, IOException {
MockHttpServletRequest request = new MockHttpServletRequest(
getServletContext(), "GET", "/service");
request.addParameter("text", "sagara");
MockHttpServletResponse response = new MockHttpServletResponse();
simpleServlet.doGet(request, response);
String res = response.getContentAsString();
System.out.println(res);
assertEquals("Hello : sagara", res.trim());

}

}