users@jersey.java.net

Re: [Jersey] restart a resource

From: Guilhem <guilhem.legal_at_geomatys.fr>
Date: Fri, 17 Oct 2008 11:58:37 +0200

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



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