users@jersey.java.net

Thread safety of JSON serialization

From: Santtu Vuori <santtu.vuori_at_gmail.com>
Date: Fri, 22 May 2009 10:53:20 +0300

I have been running some very simple tests against Jersey and noticed - by
accident the following:

I've created a simple client using commons http client (v3.1) to connect to
the resource and pull the results. I'm adding "Accept: application/json" to
header to ensure the data comes back JSON formatted. The client spawns 50
parallel threads to do a single HTTP GET and every now and then I get the
following response from the server:


Thread-8 RESPCODE: 500
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Draft//EN">
<HTML>
<HEAD>
<TITLE>Error 500--Internal Server Error</TITLE>
<META NAME="GENERATOR" CONTENT="WebLogic Server">
</HEAD>
<BODY bgcolor="white">
<FONT FACE=Helvetica><BR CLEAR=all>
<TABLE border=0 cellspacing=5><TR><TD><BR CLEAR=all>
<FONT FACE="Helvetica" COLOR="black" SIZE="3"><H2>Error 500--Internal Server
Error</H2>
</FONT></TD></TR>
</TABLE>
<TABLE border=0 width=100% cellpadding=10><TR><TD VALIGN=top WIDTH=100%
BGCOLOR=white><FONT FACE="Courier New"><pre>
java.lang.NullPointerException
        at
com.sun.jersey.core.impl.provider.entity.Inflector$Replacer.replacement(Inflector.java:851)
        at
com.sun.jersey.core.impl.provider.entity.Inflector.pluralize(Inflector.java:519)
        at
com.sun.jersey.core.provider.jaxb.AbstractListElementProvider.getRootElementName(AbstractListElementProvider.java:252)
        at
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider.writeList(JSONListElementProvider.java:106)
        at
com.sun.jersey.core.provider.jaxb.AbstractListElementProvider.writeTo(AbstractListElementProvider.java:144)
        at
com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:254)
        at
com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:693)
        at
com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:616)
        at
com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:607)
        at
com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:309)
        at
com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:425)
        at
com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:590)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
        at
weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
        at
weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
        at
weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
        at
weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
        at
weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3498)
        at
weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
        at weblogic.security.service.SecurityManager.runAs(Unknown Source)
        at
weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
        at
weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
        at
weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
        at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
        at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
</pre></FONT></TD></TR>
</TABLE>

</BODY>
</HTML>

This is the object that I would like to be serialized:
==================
package xxx;

import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement
public class PoJo {

public final String strField = "This is a hardcoded string";
public final int intField = 42;
public final long longField = 0xFFFFFFF;
public final double doubleField = 0.0000000010;
}
==================

And this is the resource:
==================
package xxx;

import java.util.LinkedList;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.MediaType;

import org.apache.log4j.Logger;

import xxx.PoJo;


@Path("/")
public class LoadTestResource {

private static Logger logger = Logger.getLogger(LoadTestResource.class);
 @GET
@Path("/")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public GenericEntity<List<PoJo>> getData(@QueryParam("itemsreturned") Long
itemsReturned) {

List<PoJo> pojoList = new LinkedList<PoJo>();

for(int itemsAdded = 0; itemsAdded < itemsReturned; itemsAdded++) {
pojoList.add(new PoJo());
}
 GenericEntity<List<PoJo>> pojos = new GenericEntity<List<PoJo>>(pojoList)
{};

return pojos;
}
}
==================

I'm using Weblogic 10.3, Jersey 1.1.0-ea and 1.0.3.

/Santtu