users@jersey.java.net

Re: [Jersey] Context Notifier reload no longer works on jersey 1.4

From: Guilhem <guilhem.legal_at_geomatys.fr>
Date: Thu, 23 Sep 2010 11:46:02 +0200

I modify your testcase in order to run it only with grizzly and i see
that here too, the list of containerListener is empty.
if you can execute this single class, you can see the log nb=0

package test;


import javax.ws.rs.POST;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.UriInfo;
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.spi.container.WebApplication;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider;
import javax.servlet.ServletConfig;
import javax.ws.rs.core.Context;
import test.ReloadResourceTest.Reloader;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.grizzly.http.SelectorThread;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import javax.ws.rs.Path;
import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;
import com.sun.jersey.spi.container.ContainerListener;
import com.sun.jersey.spi.container.ContainerNotifier;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.core.UriBuilder;
import static org.junit.Assert.*;

public class ReloadResourceTest {

     @Path("/one")
     public static class One {

         @GET
         public String get() {
             return "one";
         }
     }

     @Path("/two")
     public static class Two {

         @GET
         public String get() {
             return "two";
         }
     }

     public static class Reloader implements ContainerNotifier {

         List<ContainerListener> ls;

         public Reloader() {
             ls = new ArrayList<ContainerListener>();
         }

         public void addListener(ContainerListener l) {
             ls.add(l);
         }

         public void reload() {
             System.out.println("nb:" + ls.size());
             for (ContainerListener l : ls) {
                 l.onReload();
             }
         }
     }

     public static class ReloadServletContainer extends ServletContainer {

         @Override
         protected void configure(final ServletConfig sc, ResourceConfig
rc, WebApplication wa) {
             super.configure(sc, rc, wa);

             Reloader r = new Reloader();
             rc.getSingletons().add(new
SingletonTypeInjectableProvider<Context, Reloader>(
                     Reloader.class, r) {
             });
             
rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_NOTIFIER, r);
         }
     }


     @Path("reload")
     public static class ReloaderResource {

         @Context
         ResourceConfig rc;
         @Context
         UriInfo ui;
         @Context
         Reloader r;

         public ReloaderResource(@Context HttpServletRequest r) {
         }

         @POST
         public String postReload() {
             if (rc.getClasses().contains(Two.class)) {
                 rc.getClasses().remove(Two.class);
             } else {
                 rc.getClasses().add(Two.class);
             }

             r.reload();
             return ui.getPath();
         }
     }


     public ReloadResourceTest(String testName) {
     }


     private static URI getBaseURI() {
         return UriBuilder.fromUri("http://localhost/").port(9999).build();
     }
     public static final URI BASE_URI = getBaseURI();

     protected static SelectorThread startServer() throws IOException {
         final Map<String, String> initParams = new HashMap<String,
String>();

         initParams.put("com.sun.jersey.config.property.packages",
                 "test");

         System.out.println("Starting grizzly...");
         SelectorThread threadSelector =
GrizzlyWebContainerFactory.create(BASE_URI,
ReloadServletContainer.class,initParams);
         return threadSelector;
     }

     public static void main(String[] args) throws IOException {
         SelectorThread threadSelector = startServer();
         System.out.println("Jersey started");

         WebResource r = Client.create().resource(getBaseURI());

         for (int i = 0; i < 2; i++) {
             assertEquals("one", r.path("one").get(String.class));
             assertEquals("two", r.path("two").get(String.class));

             assertEquals("reload", r.path("reload").post(String.class));

             assertEquals("one", r.path("one").get(String.class));
             assertEquals(404,
r.path("two").get(ClientResponse.class).getStatus());

             assertEquals("reload", r.path("reload").post(String.class));
         }

         System.in.read();
         threadSelector.stopEndpoint();
         System.exit(0);
     }
}

Guilhem Legal

On 23/09/2010 11:08, Guilhem wrote:
> I don't succeed to run your test because i don't find the class
> AbstractGrizzlyWebContainerTester
>
> on my side all i see is that the size the ContainerListener in my
> ContainerNotifier is empty.
> so when i call reload it does nothing. i guess the method addListener
> is not called but why.
>
>
> public class ContainerNotifierImpl implements ContainerNotifier {
>
> private List<ContainerListener> cls;
>
> public ContainerNotifierImpl() {
>
> cls = new ArrayList<ContainerListener>();
>
> }
>
> public void addListener(ContainerListener arg0) {
> // this method is never called
> cls.add(arg0);
>
> }
>
> public void reload() {
> // here the size is always 0 that is my problem
> for ( ContainerListener cl : cls) {
> cl.onReload();
> }
> }
> }
>
> Guilhem Legal
>
> On 22/09/2010 23:41, Paul Sandoz wrote:
>> Hi Guilhem,
>>
>> Can you package up a reproducible test case and attach it to an issue?
>>
>> We have a unit test that does virtually the same thing as you have
>> described and it does not fail.
>>
>> package com.sun.jersey.impl.container.grizzly.web;
>>
>> import com.sun.jersey.api.client.Client;
>> import com.sun.jersey.api.client.ClientResponse;
>> import javax.ws.rs.Path;
>> import com.sun.jersey.api.client.WebResource;
>> import com.sun.jersey.api.core.ResourceConfig;
>> import com.sun.jersey.spi.container.ContainerListener;
>> import com.sun.jersey.spi.container.ContainerNotifier;
>> import com.sun.jersey.spi.container.WebApplication;
>> import com.sun.jersey.spi.container.servlet.ServletContainer;
>> import com.sun.jersey.spi.inject.SingletonTypeInjectableProvider;
>> import java.util.ArrayList;
>> import java.util.List;
>> import javax.servlet.ServletConfig;
>> import javax.servlet.http.HttpServletRequest;
>> import javax.ws.rs.GET;
>> import javax.ws.rs.POST;
>> import javax.ws.rs.core.Context;
>> import javax.ws.rs.core.UriInfo;
>>
>> /**
>> *
>> * @author Paul.Sandoz_at_Sun.Com
>> */
>> public class ReloadResourceTest extends
>> AbstractGrizzlyWebContainerTester {
>>
>> @Path("/one")
>> public static class One {
>>
>> @GET
>> public String get() {
>> return "one";
>> }
>> }
>>
>> @Path("/two")
>> public static class Two {
>>
>> @GET
>> public String get() {
>> return "two";
>> }
>> }
>>
>> private static class Reloader implements ContainerNotifier {
>>
>> List<ContainerListener> ls;
>>
>> public Reloader() {
>> ls = new ArrayList<ContainerListener>();
>> }
>>
>> public void addListener(ContainerListener l) {
>> ls.add(l);
>> }
>>
>> public void reload() {
>> for (ContainerListener l : ls) {
>> l.onReload();
>> }
>> }
>> }
>>
>> @Path("reload")
>> public static class ReloaderResource {
>>
>> @Context ResourceConfig rc;
>>
>> @Context UriInfo ui;
>>
>> @Context Reloader r;
>>
>> public ReloaderResource(@Context HttpServletRequest r) {
>> assertNotNull(r);
>> }
>>
>> @POST
>> public String postReload() {
>> if (rc.getClasses().contains(Two.class)) {
>> rc.getClasses().remove(Two.class);
>> } else {
>> rc.getClasses().add(Two.class);
>> }
>>
>> r.reload();
>> return ui.getPath();
>> }
>> }
>>
>> public static class ReloadServletContainer extends
>> ServletContainer {
>>
>> @Override
>> protected void configure(final ServletConfig sc,
>> ResourceConfig rc, WebApplication wa) {
>> super.configure(sc, rc, wa);
>>
>> Reloader r = new Reloader();
>> rc.getSingletons().add(new
>> SingletonTypeInjectableProvider<Context, Reloader>(
>> Reloader.class, r){});
>>
>> rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_NOTIFIER, r);
>> }
>> }
>>
>> public ReloadResourceTest(String testName) {
>> super(testName);
>> }
>>
>> public void testReload() {
>> setServletClass(ReloadServletContainer.class);
>> startServer(One.class, ReloaderResource.class);
>>
>> WebResource r =
>> Client.create().resource(getUri().path("/").build());
>>
>> for (int i = 0; i < 2; i++) {
>> assertEquals("one", r.path("one").get(String.class));
>> assertEquals(404,
>> r.path("two").get(ClientResponse.class).getStatus());
>>
>> assertEquals("reload", r.path("reload").post(String.class));
>>
>> assertEquals("one", r.path("one").get(String.class));
>> assertEquals("two", r.path("two").get(String.class));
>>
>> assertEquals("reload", r.path("reload").post(String.class));
>> }
>> }
>> }
>>
>>
>>
>> On Sep 22, 2010, at 6:38 AM, Guilhem wrote:
>>
>>> Hello,
>>>
>>> Since a long time I use jersey for webservice. In my case i need to
>>> send a request to my WS for reload all the resource.
>>>
>>> here is the solution i was using (based on conversation on this list
>>> called [Jersey] restart a resource ) :
>>>
>>> I have overriden the servlet container :
>>>
>>> public class CstlServletContainer extends ServletContainer {
>>>
>>> public static boolean configured = false;
>>>
>>> @Override
>>>
>>> protected void configure(final ServletConfig sc, ResourceConfig
>>> rc, WebApplication wa) {
>>>
>>> super.configure(sc, rc, wa);
>>>
>>> if (!configured) {
>>>
>>> final ContainerNotifierImpl cnImpl = new
>>> ContainerNotifierImpl();
>>>
>>>
>>> rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_NOTIFIER,
>>> cnImpl);
>>>
>>> rc.getSingletons().add(new
>>> ContextInjectableProvider<ContainerNotifierImpl>(ContainerNotifierImpl.class,
>>> cnImpl));
>>>
>>> configured = true;
>>>
>>> }
>>>
>>> }
>>>
>>>
>>> private static class ContextInjectableProvider<T> extends
>>> SingletonTypeInjectableProvider<Context, T> {
>>>
>>> ContextInjectableProvider(Type type, T instance) {
>>>
>>> super(type, instance);
>>>
>>> }
>>>
>>> }
>>>
>>> }
>>>
>>>
>>>
>>> I have a container notifier :
>>>
>>> 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() {
>>>
>>> for ( ContainerListener cl : cls) {
>>>
>>> cl.onReload();
>>>
>>> }
>>>
>>> }
>>>
>>> }
>>>
>>>
>>> And i one of my resource i call the containerNotifier to restart all
>>> the singleton resource:
>>>
>>> @Path("configuration")
>>>
>>> @Singleton
>>>
>>> public final class ConfigurationService extends AbstractWebService {
>>>
>>> @Context
>>>
>>> private ContainerNotifierImpl cn;
>>>
>>> // this is simplified here
>>>
>>> private Response treatIncommingResponse() {
>>>
>>> cn.reload();
>>>
>>> }
>>>
>>> }
>>>
>>>
>>> Now that i have upgraded to jersey 1.4, the call to cn.reload do
>>> absolutly nothing.
>>> Is this a bug or is there a new way to do so ?
>>>
>>> thanks
>>>
>>> Guilhem Legal (Geomatys)
>>>
>>>
>>> ---------------------------------------------------------------------
>>> 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
>
>
>