users@jersey.java.net

Re: Resource Lifecycle, Providers and Content-Length

From: Jean Aurambault <aurambaj_at_yahoo-inc.com>
Date: Wed, 09 Apr 2008 13:45:51 +0200

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?

>
>> 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.
>