users@jersey.java.net

Re: [Jersey] restart a resource

From: Guilhem <guilhem.legal_at_geomatys.fr>
Date: Fri, 17 Oct 2008 12:34:25 +0200

I was about to scream for victory after reloaded five times my service
and then... no more reload.

randomly (sometimes after the first reload, sometimes i reload 20 times
my resources without having the problem).

I don't get an exception its just that the list of containerListener is
empty :



public class ContainerNotifierImpl implements ContainerNotifier {
   
    private List<ContainerListener> cls;

    public ContainerNotifierImpl() {
        cls = new ArrayList<ContainerListener>();
    }
   
    public void addListener(ContainerListener arg0) {
        cls.add(arg0);
    }
   
    public void reload() {
        System.out.println("reloading");
        for ( ContainerListener cl : cls) {
            cl.onReload();
            System.out.println("realoaded");
        }
    }

}


with the system.out i see that at a moment there is only "reloading"
and no "reloaded".




Guilhem a écrit :
> I can't use the following line:
>
> rc.getSingletons().add(new
> ContextInjectableProvider<ContainerNotifierImpl>(ContainerNotifierImpl.class,
> cnImpl));
>
> ContextInjectableProvider has private access in
> com.sun.jersey.spi.container.servlet.ServletContainer
>

I didn't see the following mail with static class sorry.
>
>
> Paul Sandoz a écrit :
>>
>> On Oct 17, 2008, at 10:14 AM, Guilhem wrote:
>>
>>> hi paul,
>>>
>>> first I'm not using spring but yes all my resources are singletons.
>>>
>>
>> Ah! I reproduced the same issue in a different context. I just
>> reproduced what you observe using singleton instances explicitly
>> added. The problem is the singleton instance is retaining the old
>> reference on the field. When reloading the old instance of
>> ConfigurationService needs to be removed from the singleton and a new
>> one added.
>>
>> But i just noticed another issue, the reload application is doing:
>>
>> WebApplication _application = create();
>> configure(config, resourceConfig, _application);
>> initiate(resourceConfig, _application);
>> application = _application;
>>
>> which is wrong, i think reload should just do:
>>
>> WebApplication _application = create();
>> initiate(resourceConfig, _application);
>> application = _application;
>>
>> which is why you require the boolean variable (but still see the
>> issue with the old reference). Also i think configure should no
>> longer have WebApplication passed in as a parameter to the method.
>>
>> Perhaps i was being too smart proposing the use of a singleton
>> resource and instead it may be more appropriate to inject a
>> ContainerNotifier implementation as follows in the Servlet configure
>> method:
>>
>> rc.getSingletons().add(new
>> ContextInjectableProvider<ContainerNotifierImpl>(
>> ContainerNotifierImpl.class, cnImpl));
>>
>> and in your ConfigurationService do:
>>
>> @Path("reload")
>> public class ConfigurationService {
>> @Context ContainerNotifierImpl cn;
>>
>> @Context UriInfo u;
>>
>> @POST public void reload() {
>> cn.reload();
>> }
>> }
>>
>> Then you will not get any old reference issues.
>>
>>
>>> i'm using the :
>>> @Context
>>> protected UriInfo context;
>>>
>>> MultivaluedMap parameters = context.getQueryParameters();
>>>
>>> to get a GET parameters like: request=restart or whatever in all
>>> my singletons.
>>>
>>>
>>> the weird thing is that all the other resources restarted does not
>>> throw the illegalStateException by getting parameters, only the
>>> reloadResource launch this.
>>>
>>
>> OK.
>>
>>
>>> for 2), It seems that the resources are well destroyed and
>>> re-instanciated (They all pass in constructor).
>>>
>>> when you say fields for injection you means that : @Context
>>> Protected UriInfo context ?
>>>
>>
>> Yes.
>>
>> Paul.
>>
>>> Guilhem
>>>
>>>
>>>
>>> Paul Sandoz a écrit :
>>>> Hi Guilhem,
>>>>
>>>> This was a bit of a head scratcher. I am guessing you are using a
>>>> Singleton resource with Spring?
>>>>
>>>> The problem is the reference held by the field on the singleton
>>>> resource is longer valid after the reloading. This is because
>>>> reloading will cause the web application to create new references
>>>> for injection, which invalidates any previously help references.
>>>> This is a general problem for singletons whose instances are
>>>> controlled outside of Jersey and for which injection is performed.
>>>> When Jersey performs injection it will not overwrite anything with
>>>> a non-null value.
>>>>
>>>> Three possible ways to directly resolve this:
>>>>
>>>> 1) Don't use fields for injection;
>>>>
>>>> 2) The reload functionality you have implemented needs to destroy
>>>> the singletons so that they are re-
>>>> instantiated; or
>>>>
>>>> 3) Jersey is modified inject on non-null values.
>>>>
>>>> I am not comfortable supporting 3) or doing something more
>>>> complicated around sharing state or detecting reloads and working
>>>> around the issues. In this case i think 2) is required.
>>>>
>>>> Of course the better approach is to support richer notification
>>>> events on changes to resource classes: removal, addition and class
>>>> modification. Changes to provider classes may be more problematic...
>>>>
>>>> Paul.
>>>>
>>>> On Oct 16, 2008, at 6:20 PM, Guilhem wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> i put in place the mecanism described previously, everything
>>>>> working well until i realized that i can restart my WS only one
>>>>> time before getting a IllegalStateException:
>>>>>
>>>>> i just change some pieces of code to get this working :
>>>>>
>>>>> - my resource ReloadResource (ConfigurationService) implementing
>>>>> ContainerNotifier is not in the same class that the servletContainer.
>>>>>
>>>>> - i had to put a boolean flag to add the reload resource only one
>>>>> time (i got an exception else) :
>>>>>
>>>>>
>>>>> public class CstlServletContainer extends ServletContainer {
>>>>>
>>>>> public static boolean reload = false;
>>>>> @Override
>>>>> protected void configure(final ServletConfig sc, ResourceConfig
>>>>> rc, WebApplication wa) {
>>>>> super.configure(sc, rc, wa);
>>>>> ConfigurationService configService = new ConfigurationService();
>>>>> if (!reload) {
>>>>> rc.getSingletons().add(configService);
>>>>> }
>>>>> reload = true;
>>>>>
>>>>> rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_NOTIFIER,
>>>>> configService);
>>>>> }
>>>>> }
>>>>>
>>>>>
>>>>> so the first time the restart works well when i do this (you can
>>>>> see that i don't want to restart my reloadResource in order to
>>>>> send a xml result when the operation is ended):
>>>>>
>>>>> ...................
>>>>>
>>>>> for ( ContainerListener cl : cls) {
>>>>> if (!cl.equals(this))
>>>>> cl.onReload();
>>>>> }
>>>>>
>>>>> .....................
>>>>>
>>>>>
>>>>> and the second time i call this method i get an
>>>>> illegalstateException when i trying to get a parameter in this line :
>>>>>
>>>>> .....................
>>>>>
>>>>> @Context
>>>>> protected UriInfo context;
>>>>>
>>>>> ......................
>>>>>
>>>>>
>>>>> line 352: final MultivaluedMap parameters =
>>>>> context.getQueryParameters();
>>>>>
>>>>>
>>>>> ................
>>>>>
>>>>> exception:
>>>>>
>>>>> java.lang.IllegalStateException
>>>>>
>>>>> com.sun.jersey.impl.ThreadLocalHttpContext.getUriInfo(ThreadLocalHttpContext.java:67)
>>>>>
>>>>>
>>>>> com.sun.jersey.impl.application.WebApplicationImpl$2.invoke(WebApplicationImpl.java:184)
>>>>>
>>>>> $Proxy7.getQueryParameters(Unknown Source)
>>>>>
>>>>> org.constellation.ws.rs.WebService.getParameter(WebService.java:352)
>>>>>
>>>>>
>>>>>
>>>>> Is someone know you know why i'm getting this exception?
>>>>>
>>>>> Guilhem Legal
>>>>>
>>>>> Paul Sandoz a écrit :
>>>>>>
>>>>>> On Oct 3, 2008, at 2:23 PM, Guilhem wrote:
>>>>>>
>>>>>>> hi,
>>>>>>>
>>>>>>> i follow the tutorial i 've found at
>>>>>>> http://blogs.sun.com/sandoz/entry/javarebel_and_jersey_take_2
>>>>>>> this works well, but I don't see how to use this with tomcat
>>>>>>> instead of a lightWebContainer.
>>>>>>>
>>>>>>
>>>>>> You can extend the ServletContainer to register a container
>>>>>> notifier. You need to add an instance of ContainerNotifier to to
>>>>>> the resource config properties
>>>>>> (ResourceConfig.PROPERTY_CONTAINER_NOTIFIER).
>>>>>>
>>>>>> Override the configure methods to do something like this:
>>>>>>
>>>>>> protected void configure(final ServletConfig sc,
>>>>>> ResourceConfig rc, WebApplication wa) {
>>>>>> super.configure(sc, rc, wa);
>>>>>>
>>>>>> ContainerNotifier cn = ....
>>>>>>
>>>>>> rc.getProperties().put(esourceConfig.PROPERTY_CONTAINER_NOTIFIER,
>>>>>> cn);
>>>>>> }
>>>>>>
>>>>>>
>>>>>>> more, the resource are reloaded only when the classes are changed.
>>>>>>>
>>>>>>> For my application I want to make a JSF interface with a button
>>>>>>> "reload" which restart all the resources (i had prefer only
>>>>>>> selected resource but it seems to be unpossible).
>>>>>>>
>>>>>>
>>>>>> Yes, currently it is not possible reload a single resource. Do
>>>>>> you want to log an issue?
>>>>>>
>>>>>> It sounds like you want to have a another resource that triggers
>>>>>> a reload.
>>>>>>
>>>>>> You could have a singleton resource instance you add to the
>>>>>> singletons of ResourceConfig at configuration time that has the
>>>>>> instance of the ContainerNotifier, then when a POST method is
>>>>>> sent to that resource it can perform a reload.
>>>>>>
>>>>>> protected void configure(final ServletConfig sc,
>>>>>> ResourceConfig rc, WebApplication wa) {
>>>>>> super.configure(sc, rc, wa);
>>>>>>
>>>>>> ReloadResource rr = new ReloadResource(cn);
>>>>>> rc.getSingletons().add(rr);
>>>>>>
>>>>>> rc.getProperties().put(esourceConfig.PROPERTY_CONTAINER_NOTIFIER,
>>>>>> rr);
>>>>>> }
>>>>>>
>>>>>> ....
>>>>>>
>>>>>> @Path("reload")
>>>>>> public class ReloadResource implements ContainerNotifier {
>>>>>> List<ContainerListener> cls;
>>>>>> ...
>>>>>>
>>>>>> @POST void reload() {
>>>>>> for (ContainerListener cl : cls) cl.onReload();
>>>>>> }
>>>>>> }
>>>>>>
>>>>>>
>>>>>> Alternatively you could create an injectable provider to inject
>>>>>> the registered container notifier.
>>>>>>
>>>>>>
>>>>>>> is there any tutorial which help me to do this?
>>>>>>>
>>>>>>
>>>>>> Unfortunately not :-(
>>>>>>
>>>>>> Paul.
>>>>>>
>>>>>>
>>>>>>> Guilhem Legal
>>>>>>>
>>>>>>>
>>>>>>> Paul Sandoz a écrit :
>>>>>>>>
>>>>>>>> On Sep 24, 2008, at 4:42 PM, Guilhem wrote:
>>>>>>>>
>>>>>>>>> hi,
>>>>>>>>>
>>>>>>>>> I would know if its possible to dynamically restart a resource
>>>>>>>>> without having to undeploy/deploy or restart the container?
>>>>>>>>>
>>>>>>>>
>>>>>>>> It is currently only possible to reload all resources. What
>>>>>>>> happens is a new web application is created, configured and
>>>>>>>> initiated.
>>>>>>>>
>>>>>>>> See the JavaDoc of the class:
>>>>>>>>
>>>>>>>> com.sun.jersey.spi.container.ContainerNotifier
>>>>>>>>
>>>>>>>> to register a notifier that may reload the container.
>>>>>>>>
>>>>>>>> I have used this in conjunction with JavaRebel. When JavaRebel
>>>>>>>> detects changes to class files i have a hook in that to
>>>>>>>> dynamically reload things using a ContainerNotifier without
>>>>>>>> having to undeploy/deploy the web application.
>>>>>>>>
>>>>>>>> Does that work for you?
>>>>>>>>
>>>>>>>> Paul.
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>
>>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>>
>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>>
>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>>
>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>>
>>>>
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>
>