users@jersey.java.net

Re: [Jersey] strange "double dispatching" problem

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 21 Jan 2009 10:17:26 +0100

Hi Byron,

Is it possible send the output from the thread dump you mention? that
will give me some more clues.

How is the client consuming the Feed, does the client make another
request for the consumption of Atom feed documents and does not make
another request for the consumption of Atom entry documents? That
would be my initial guess because there is nothing in Jersey itself to
result in another dispatch to the resource method.

One way to check if this is the case is to add a logging filter to the
server side, add the following to your init params of your servlet
declaration:

        <init-param>
            <param-
name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
            <param-
value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
        </init-param>
        <init-param>
            <param-
name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
            <param-
value>com.sun.jersey.api.container.filter.LoggingFilter</param-value>
        </init-param>

The logging filter currently prints request and responses to
System.out (perhaps it should use JDK logging by default? as pointed
out by another developer for the client side logging filter).

Another way to check is to use a different client, say curl.

Paul.

On Jan 20, 2009, at 11:58 PM, Bryon Jacob wrote:

> Hi all - I am having an extremely strange problem with Jersey
> dispatching to one of my resource methods TWICE. The strangest
> thing about it seems to be that the problem is related to the return
> type of the method!
>
> This problem is happening pretty deep in my resource hierarchy, so
> I'm not pasting ALL of the code here - but I have boiled it down to
> a pretty simple example. If I have this method defined:
>
> @GET
> @Path("/_/{whatever : .*}")
> public Entry getConfused(@PathParam("whatever")String whatever) {
> System.out.println(whatever);
> Entry entry = AbderaMarshaller.factory().newEntry();
> entry.setId(whatever);
> return entry;
> }
>
> everything works fine -- that is, when I go to the URL http://localhost:8000/A/B/C/_/blah
> (where A/B/C is the path to the resource on which this method is
> defined), I see "blah" printed to the console exactly once, and I
> get an <entry> as a response. When I replace that method with this:
>
> @GET
> @Path("/_/{whatever : .*}")
> public Feed getConfused(@PathParam("whatever")String whatever) {
> System.out.println(whatever);
> Feed feed = AbderaMarshaller.factory().newFeed();
> Entry entry = AbderaMarshaller.factory().newEntry();
> entry.setId(whatever);
> feed.addEntry(entry);
> return feed;
> }
>
> and go to the same URL, I get the <feed> element back, just as I
> expected, but "blah" is printed to the console TWICE! How can this
> be?
>
> The Entry and Feed elements are from Abdera's object model, and my
> registered provider is my custom AbderaMarshaller class (source
> below) - everything seems to work properly, no exceptions are being
> thrown, and my provider is being called to marshall the Abdera
> objects to XML, but with the second variation of the method, it is
> always called TWICE when a matching URL is accessed.
>
> Other variables that might be interesting...
> - I'm using Jersey 1.0.1
> - I'm using jersey-spring (also 1.0.1) to compose the application
> with Spring 2.5 annotations.
> - I'm running java 1.6, and I'm running all of this using the
> com.sun.net.httpserver.HttpServer class.
>
> I figure either I must be doing something blindingly dumb, or
> there's a subtle bug in Jersey, since I can't imagine any reason for
> jersey to dispatch to my methods twice (BTW - I did verify that this
> is exactly what is happening... I did a Thread.dumpStack() in the
> failing method above, and the exact same stack, starting somewhere
> in Jersey and ending up with a call to my method, was repeated
> twice...)
>
> A quick search of the list archives didn't turn up anything
> relevant... so I thought I'd post it here and see if anyone had seen
> this. Anyways - here's the source to my provider class - thanks for
> any help y'all can offer!
>
>
> @Provider
> @Produces({APPLICATION_ATOM_XML, APPLICATION_XML, TEXT_XML})
> @Consumes({APPLICATION_ATOM_XML, APPLICATION_XML, TEXT_XML})
> public class AbderaMarshaller implements MessageBodyWriter,
> MessageBodyReader {
>
> public void writeTo(Object o, Class aClass, Type type,
> Annotation[] annotations, MediaType mediaType,
> MultivaluedMap multivaluedMap, OutputStream
> outputStream)
> throws IOException, WebApplicationException {
> ((ExtensibleElement) o).writeTo(outputStream);
> }
>
> public Object readFrom(Class aClass, Type type, Annotation[]
> annotations, MediaType mediaType,
> MultivaluedMap multivaluedMap,
> InputStream inputStream)
> throws IOException, WebApplicationException {
> return parser().parse(inputStream).getRoot();
> }
>
> public boolean isWriteable(Class aClass, Type type, Annotation[]
> annotations, MediaType mediaType) {
> return isAbderaExtensibleElement(aClass);
> }
>
> public long getSize(Object o, Class aClass, Type type,
> Annotation[] annotations, MediaType mediaType) {
> return -1;
> }
>
> public boolean isReadable(Class aClass, Type type, Annotation[]
> annotations, MediaType mediaType) {
> return isAbderaExtensibleElement(aClass);
> }
>
> private boolean isAbderaExtensibleElement(Class clazz) {
> return ExtensibleElement.class.isAssignableFrom((Class<?>)
> clazz);
> }
>
> private static final transient ThreadLocal<Parser> PARSER = new
> ThreadLocal<Parser>() {
> protected Parser initialValue() {
> return new FOMParser();
> }
> };
>
> public static Parser parser() {
> return PARSER.get();
> }
>
> private static final transient ThreadLocal<FOMFactory> FACTORY =
> new ThreadLocal<FOMFactory>() {
> protected FOMFactory initialValue() {
> return new FOMFactory();
> }
> };
>
> public static FOMFactory factory() {
> return FACTORY.get();
> }
>
> }
>
>