users@jersey.java.net

Re: [Jersey] restart a resource

From: Guilhem <guilhem.legal_at_geomatys.fr>
Date: Fri, 17 Oct 2008 14:13:01 +0200

Thanks a lot, i used the flag configured and it seems to works fine.

now i have to find a way to do the same things with JAX-WS services and
they don't have as helpful people than you :-(

thank's again

Guilhem Legal

Paul Sandoz a écrit :
> Should be fixed now. See this unit test for an example:
>
> https://jersey.dev.java.net/source/browse/*checkout*/jersey/trunk/jersey/jersey-tests/src/test/java/com/sun/jersey/impl/container/grizzly/web/ReloadResourceTest.java
>
>
> Paul.
>
> On Oct 17, 2008, at 1:05 PM, Paul Sandoz wrote:
>
>>
>> On Oct 17, 2008, at 12:34 PM, Guilhem wrote:
>>
>>> I was about to scream for victory after reloaded five times my
>>> service and then... no more reload.
>>>
>>
>> Sorry about that :-( I just did some more tests and can reproduce the
>> problem.
>>
>> It is due to multiple instances of ContainerNotifierImpl being
>> created because of the issue of configure being called every time
>> there is a reload. But! notification is initiated only at servlet
>> init time. Gosh this reloading area is complex!
>>
>> Try having the following as a field of your servlet:
>>
>> ContainerNotifierImpl cn = new ContainerNotifierImpl();
>>
>> or making sure that the following:
>>
>> ContainerNotifierImpl cn = new ContainerNotifierImpl();
>> rc.getSingletons().add(new
>> ContextInjectableProvider<ContainerNotifierImpl>(
>> ContainerNotifierImpl.class, cn));
>>
>> rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_NOTIFIER, cn);
>>
>> is only called once by checking a boolean field:
>> if (!configured) {
>> ContainerNotifierImpl cn = new ContainerNotifierImpl();
>> rc.getSingletons().add(new
>> ContextInjectableProvider<ContainerNotifierImpl>(
>> ContainerNotifierImpl.class, cn));
>>
>> rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_NOTIFIER, cn);
>> configured = true;
>> }
>>
>> In my workspace i have fixed the multiple calls to configure and have
>> a unit test in place that reproduces your functionality and passes.
>>
>> Paul.
>>
>>
>>> 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
>>>>
>>>>
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> 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
>
>
>