Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,10 @@ protected void processMethod(ResourceFactory rf, String base, ResourceLocator me
rootNode.addInvoker(fullpath, locator);
else root.addInvoker(classExpression, fullpath, locator);
}

if (rf instanceof SingletonResource) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @rnetuka,

I'm questioning whether this should be in

   protected void register(ResourceFactory rf, String base, ResourceClass resourceClass)
   {
      for (ResourceMethod method : resourceClass.getResourceMethods())
      {
         processMethod(rf, base, method);
      }
      for (ResourceLocator method : resourceClass.getResourceLocators())
      {
         processMethod(rf, base, method);
      }
   }

Otherwise, you'll be calling registerSingletonResource() for each method, no?

-Ron

providerFactory.registerSingletonResource((SingletonResource) rf);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.jboss.resteasy.plugins.delegates.NewCookieHeaderDelegate;
import org.jboss.resteasy.plugins.delegates.UriHeaderDelegate;
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
import org.jboss.resteasy.plugins.server.resourcefactory.SingletonResource;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages;
import org.jboss.resteasy.specimpl.LinkBuilderImpl;
Expand Down Expand Up @@ -262,6 +263,8 @@ public int compareTo(SortedKey<T> tMessageBodyKey)

protected ResourceBuilder resourceBuilder;

// RESTEASY-1865 resource factories for singleton resources
private Map<Class<?>, SingletonResource> singletonResourceFactories;

public ResteasyProviderFactory()
{
Expand Down Expand Up @@ -351,6 +354,7 @@ protected void initialize()
builtinsRegistered = false;
registerBuiltins = true;

singletonResourceFactories = new HashMap<>();
injectorFactory = new InjectorFactoryImpl();
addHeaderDelegate(MediaType.class, new MediaTypeHeaderDelegate());
addHeaderDelegate(NewCookie.class, new NewCookieHeaderDelegate());
Expand Down Expand Up @@ -2596,6 +2600,16 @@ public <T> ConstructorInjector createConstructorInjector(Class<? extends T> claz
return getInjectorFactory().createConstructor(constructor, this);
}

public void registerSingletonResource(SingletonResource resource)
{
singletonResourceFactories.put(resource.getScannableClass(), resource);
}

private <T> boolean isSingletonResource(Class<T> resourceClass)
{
return singletonResourceFactories.containsKey(resourceClass);
}

/**
* Property and constructor injection using the InjectorFactory.
*
Expand Down Expand Up @@ -2625,8 +2639,16 @@ public <T> T injectedInstance(Class<? extends T> clazz)
*/
public <T> T injectedInstance(Class<? extends T> clazz, HttpRequest request, HttpResponse response)
{
Constructor<?> constructor = PickConstructor.pickSingletonConstructor(clazz);
Object obj = null;

if (isSingletonResource(clazz))
{
SingletonResource factory = singletonResourceFactories.get(clazz);
obj = factory.createResource(request, response, this).toCompletableFuture().getNow(null);
}
else
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've not indented the else branch as it would have caused very confusing diff

Constructor<?> constructor = PickConstructor.pickSingletonConstructor(clazz);
if (constructor == null)
{
// TODO this is solely to pass the TCK. This is WRONG WRONG WRONG! I'm challenging.
Expand Down Expand Up @@ -2684,6 +2706,7 @@ public <T> T injectedInstance(Class<? extends T> clazz, HttpRequest request, Htt
ConstructorInjector constructorInjector = getInjectorFactory().createConstructor(constructor, this);
obj = constructorInjector.construct(request, response, false).toCompletableFuture().getNow(null);

}
}
PropertyInjector propertyInjector = getInjectorFactory().createPropertyInjector(clazz, this);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.jboss.resteasy.test.core;

import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.util.Date;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;

import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockDispatcherFactory;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class DispatcherTest {

private Dispatcher dispatcher;


@Before
public void before() {
dispatcher = MockDispatcherFactory.createDispatcher();
}

// @see https://issues.jboss.org/browse/RESTEASY-1865
@Test
public void testSingletonResource() throws URISyntaxException, UnsupportedEncodingException {
dispatcher.getRegistry().addSingletonResource(new ParentResource());
dispatcher.getRegistry().addSingletonResource(new ChildResource("I'm singleton child"));

MockHttpRequest request = MockHttpRequest.get("/parent");
MockHttpResponse response = new MockHttpResponse();

dispatcher.invoke(request, response);

assertEquals(200, response.getStatus());
assertEquals("I'm singleton child", response.getContentAsString());
}




@Path("/parent")
public static class ParentResource {

@Context
public ResourceContext resourceCtx;


@GET
public String get() {
ChildResource child = resourceCtx.getResource(ChildResource.class);
return child.get();
}

}

@Path("child")
public static class ChildResource {

private final String name;


@SuppressWarnings("unused") // Not used if RESTEASY-1865 is fixed
public ChildResource() {
this.name = "I'm new child created on " + new Date();
}

public ChildResource(String name) {
this.name = name;
}


@GET
public String get() {
return name;
}

}

}