users@jersey.java.net

Re: Resource Lifecycle, Providers and Content-Length

From: Martin Grotzke <martin.grotzke_at_freiheit.com>
Date: Wed, 09 Apr 2008 21:29:17 +0200

Hi Jean,

On Wed, 2008-04-09 at 13:45 +0200, Jean Aurambault wrote:
> Paul Sandoz wrote:
> > Jean Aurambault wrote:
> >> Hi,
> >>
> >> 1) I read this article
> >> http://weblogs.java.net/blog/mhadley/archive/2007/09/new_jersey_feat.html
> >> about resource lifecycle.
> >> If I have well understood, we have the choice between to| PerRequest
> >> |and |Singleton|. The default value should be |PerRequest.|
> >> In my case the default behaviour seems to be singleton and if I put
> >> the PerRequest annotation there is no difference, the resource
> >> instantiation is not done per request. Do I miss something?
> >>
> >
> > It should be per-request by default. The relevant unit tests are not
> > failing in this respect so it should be working.
> >
> > Did you check if the constructor of the resource class gets called for
> > each request? Can you share some code and the configuration?
> >
> Here is an example:
>
> @Path("/test/")
> public class TestResource {
>
> private static Logger logger =
> Logger.getLogger(TestResource.class.getName());
> @Context
> private UriInfo uriInfo;
>
> private ProductService productService = null;
>
> public void setProductService(ProductService productService) {
> this.productService = productService;
> }
>
> public TestResource() {
> logger.debug("TestResource Constructor");
> }
>
> @GET
> @Path("coucou/")
> public String getCoucou() {
> return "coucou";
> }
> }
>
> The problem seems to be related to spring. As soon as spring is used to
> inject the productService, the lifecycle doesn't work any more (behave
> like @Singleton). I use the spring servlet you have written in a
> previous article. I don't know where I should start the investigation,
> maybe you have some tips?
I'm not sure if this is the same issue I ran into, but perhaps this is
the case.

If the default constructor of your resource is seen as a constructor by
jersey, then the PerRequestProvider invokes

   ComponentProvider.getInstance(Scope, Constructor, Object[])

which returns null in the original example of the
SpringComponentProvider at [1]. You might try to change the
implementation of your ComponentProvider.getInstance(Scope, Constructor,
Object[]) to this:

    public <T> T getInstance(Scope scope, Constructor<T> constructor,
            Object[] parameters)
            throws InstantiationException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException {
        return getInstance( scope, constructor.getDeclaringClass() );
    }

This might do the trick.

I'm just implementing the integration of spring in a separate branch
[2], you might also try to checkout this and just use jersey.jar and
jersey-spring.jar built from the branches subprojects (also you would
have to configure the provided springservlet) - just ask if you want to
use this.

Cheers,
Martin


[1] http://blogs.sun.com/sandoz/entry/integrating_jersey_and_spring_take
[2] https://jersey.dev.java.net/svn/jersey/branches/spring-integration


>
> >
> >> 2) Another question, about Providers. I see in the examples that we
> >> can use the annotation @Provider instead of using the file
> >> META-INF/service in order to define our specific providers. I would
> >> like to now if there is a specification about the order of the
> >> providers in the provider list. I suppose that providers retreived
> >> using annotation are put before the ones defined in the
> >> META-INF/service to allow overloading of default providers.
> >
> > Yes.
> >
> >
> >> It should be interessting to be able to define the order at least
> >> between providers added with annotation. Basicaly, I don't want to
> >> iterate the whole list of providers if I know that I will be likely
> >> to use the same one all the time (eg. application with 95% XML
> >> requests and 5% JSON requests). Maybe it doesn't have a big impact on
> >> performance ... but I was just wondering :-D
> >>
> >
> > The order of the providers is specified by the ApplicationConfig
> > (ResourceConfig) implementation and the set of providers that are
> > returned by that. For the class scanning resource config
> > implementations provided by Jersey i presume the order would be the
> > order of the classes in the classpath (i am not sure that can be fully
> > determined and is consistent over VMs).
> >
> > In this respect one does have to be careful not to register a greedy
> > provider (type == Object.class) for all media types (*/*).
> >
> > The lookup is based on the media type (if present) and the Java type.
> > If you want to make things a little more efficient stick a
> > @ProduceMime on a writer and an @ConsumeMime on a reader.
> >
> > IMHO as a developer you should not have to worry about the efficiency
> > :-) it is really up to the implementation to optimize. For example, an
> > implementation could cache the previously used reader/writer for a
> > resource method and check if it can use that one before doing a more
> > detailed search (Jersey does not do that... yet!).
> >
> >
> >> 3) Last question about Content-Length in httpHeader response.
> >>
> >> When I make a GET on a resource (200) the Content-Length is not set.
> >> When I make a HEAD on the same resource Content-Length is 0.
> >
> > Yes, you have found a bug :-) Would you mind logging an issue?
> >
> >
> >> If I make a HEAD an resource which doesn't exist (404) Content-Length
> >> is 952. I have specific content for 404 with variable size. 952 is
> >> not the size of the returned content, because when the content
> >> changes Content-Length stays at 952.
> >>
> >
> > Is that because the the Web container is handling the HEAD (and the
> > GET) ? I suspect the Web container is returning some HTML as the 404
> > response.
> >
> I don't think so. For 404 I build a specific xml response with jaxb
> bean. And if I understand your following explanation, HEAD request
> should return an unknown content length.
>
> Here is some logs:
>
> *> GET* /V1/product/ids_test_qsdfff/ HTTP/1.1
> > User-Agent: curl/7.15.5 (i686-redhat-linux-gnu) libcurl/7.15.5
> OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
> > Host: xxxxxxxxxxxxxx
> > Accept: */*
> >
> < HTTP/1.1 404 Not Found
> < Server: Apache-Coyote/1.1
> < Content-Type: application/xml
> < Date: Wed, 09 Apr 2008 11:32:41 GMT
> < Connection: close
> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
> <xxxx>
> ...
> </xxxx>
>
>
> *> *HEAD /V1/product/ids_test_qsdfff/ HTTP/1.1
> > User-Agent: curl/7.15.5 (i686-redhat-linux-gnu) libcurl/7.15.5
> OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5
> > Host: xxxxxxxxxxxxxx
> > Accept: */*
> >
> < HTTP/1.1 404 Not Found
> < Server: Apache-Coyote/1.1
> < Content-Type: text/html;charset=utf-8
> *< Content-Length: 952*
> < Date: Wed, 09 Apr 2008 11:33:31 GMT
> < Connection: close
> * transfer closed with 952 bytes remaining to read
> * Closing connection #0
> curl: (18) transfer closed with 952 bytes remaining to read
>
> (note that 952 doesn't match the size of the content return by the GET
> neither, without more analysis it seems to be a magic number :-D)
>
> >
> >> HEAD is supposed to return the Content-Length that a GET request
> >> would have returned. Doesn't it? Is jersey supposed to take in
> >> charge the Content-Length?
> >>
> >
> > It should, when the content length is known upfront (e.g. for File or
> > for byte[]). For efficient Jersey will use chunked transfer encoding
> > when the content length is not known (and one would have to buffer to
> > determine it, e.g. for JAXB beans). In such cases a HEAD response
> > should return information consistent with the GET with an unknown
> > content length.
> Not sure to fully understand what's going on. Can you confirm that GET
> will still return Content-Length even with Jaxb beans? It is only for
> HEAD, that the size cannot be determined (without marshalling) and so is
> not set.
>
> Jean.
>
>
> >
> > Paul.
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net