You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2013/05/01 17:42:53 UTC
svn commit: r1478057 - in /cxf/trunk:
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/blueprint/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/
rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/
rt/frontend/jaxrs/src/main...
Author: sergeyb
Date: Wed May 1 15:42:52 2013
New Revision: 1478057
URL: http://svn.apache.org/r1478057
Log:
[CXF-4988] Support for instantiating providers with non default constructors
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/blueprint/BlueprintResourceFactory.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/AbstractResourceInfo.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ProviderInfo.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/SpringResourceFactory.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/blueprint/BlueprintResourceFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/blueprint/BlueprintResourceFactory.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/blueprint/BlueprintResourceFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/blueprint/BlueprintResourceFactory.java Wed May 1 15:42:52 2013
@@ -70,7 +70,7 @@ public class BlueprintResourceFactory im
public Object getInstance(Message m) {
//TODO -- This is not the BP way.
- Object[] values = ResourceUtils.createConstructorArguments(c, m);
+ Object[] values = ResourceUtils.createConstructorArguments(c, m, !isSingleton());
//TODO Very springish...
Object instance = values.length > 0 ? blueprintContainer.getComponentInstance(beanId)
: blueprintContainer.getComponentInstance(beanId);
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/lifecycle/PerRequestResourceProvider.java Wed May 1 15:42:52 2013
@@ -66,7 +66,7 @@ public class PerRequestResourceProvider
protected Object createInstance(Message m) {
- Object[] values = ResourceUtils.createConstructorArguments(c, m);
+ Object[] values = ResourceUtils.createConstructorArguments(c, m, true);
try {
Object instance = values.length > 0 ? c.newInstance(values) : c.newInstance(new Object[]{});
InjectionUtils.invokeLifeCycleMethod(instance, postConstructMethod);
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/AbstractResourceInfo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/AbstractResourceInfo.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/AbstractResourceInfo.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/AbstractResourceInfo.java Wed May 1 15:42:52 2013
@@ -42,6 +42,7 @@ import org.apache.cxf.jaxrs.utils.Inject
public abstract class AbstractResourceInfo {
private static final String FIELD_PROXY_MAP = "jaxrs-field-proxy-map";
private static final String SETTER_PROXY_MAP = "jaxrs-setter-proxy-map";
+ private static final String CONSTRUCTOR_PROXY_MAP = "jaxrs-constructor-proxy-map";
protected boolean root;
protected Class<?> resourceClass;
@@ -50,6 +51,7 @@ public abstract class AbstractResourceIn
private Map<Class<?>, List<Field>> contextFields;
private Map<Class<?>, Map<Class<?>, Method>> contextMethods;
private Bus bus;
+ private boolean constructorProxiesAvailable;
private boolean contextsAvailable;
protected AbstractResourceInfo(Bus bus) {
@@ -57,26 +59,38 @@ public abstract class AbstractResourceIn
}
protected AbstractResourceInfo(Class<?> resourceClass, Class<?> serviceClass,
- boolean isRoot, Bus bus) {
- this(resourceClass, serviceClass, isRoot, true, bus);
+ boolean isRoot, boolean checkContexts, Bus bus) {
+ this(resourceClass, serviceClass, isRoot, checkContexts, null, bus);
}
- protected AbstractResourceInfo(Class<?> resourceClass, Class<?> serviceClass,
- boolean isRoot, boolean checkContexts, Bus bus) {
+ protected AbstractResourceInfo(Class<?> resourceClass,
+ Class<?> serviceClass,
+ boolean isRoot,
+ boolean checkContexts,
+ Map<Class<?>, ThreadLocalProxy<?>> constructorProxies,
+ Bus bus) {
this.bus = bus;
this.serviceClass = serviceClass;
this.resourceClass = resourceClass;
root = isRoot;
if (checkContexts && resourceClass != null) {
- findContexts(serviceClass);
+ findContexts(serviceClass, constructorProxies);
}
}
- private void findContexts(Class<?> cls) {
+ private void findContexts(Class<?> cls, Map<Class<?>, ThreadLocalProxy<?>> constructorProxies) {
findContextFields(cls);
findContextSetterMethods(cls);
+ if (constructorProxies != null) {
+ Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> proxies = getConstructorProxyMap(true);
+ proxies.put(serviceClass, constructorProxies);
+ constructorProxiesAvailable = true;
+ }
+
+
contextsAvailable = contextFields != null && !contextFields.isEmpty()
- || contextMethods != null && !contextMethods.isEmpty();
+ || contextMethods != null && !contextMethods.isEmpty()
+ || constructorProxiesAvailable;
}
public boolean contextsAvailable() {
@@ -90,7 +104,7 @@ public abstract class AbstractResourceIn
public void setResourceClass(Class<?> rClass) {
resourceClass = rClass;
if (serviceClass.isInterface() && resourceClass != null && !resourceClass.isInterface()) {
- findContexts(resourceClass);
+ findContexts(resourceClass, null);
}
}
@@ -108,7 +122,7 @@ public abstract class AbstractResourceIn
&& AnnotationUtils.isContextClass(f.getType())) {
contextFields = addContextField(contextFields, f);
if (f.getType() != Application.class) {
- addToMap(getFieldProxyMap(), f, InjectionUtils.createThreadLocalProxy(f.getType()));
+ addToMap(getFieldProxyMap(true), f, InjectionUtils.createThreadLocalProxy(f.getType()));
}
}
}
@@ -117,9 +131,9 @@ public abstract class AbstractResourceIn
}
@SuppressWarnings("unchecked")
- private <T> Map<Class<?>, Map<T, ThreadLocalProxy<?>>> getProxyMap(Class<T> keyCls, String prop) {
+ private <T> Map<Class<?>, Map<T, ThreadLocalProxy<?>>> getProxyMap(Class<T> keyCls, String prop, boolean create) {
Object property = bus.getProperty(prop);
- if (property == null) {
+ if (property == null && create) {
Map<Class<?>, Map<T, ThreadLocalProxy<?>>> map
= new ConcurrentHashMap<Class<?>, Map<T, ThreadLocalProxy<?>>>(2);
bus.setProperty(prop, map);
@@ -128,12 +142,32 @@ public abstract class AbstractResourceIn
return (Map<Class<?>, Map<T, ThreadLocalProxy<?>>>)property;
}
- private Map<Class<?>, Map<Field, ThreadLocalProxy<?>>> getFieldProxyMap() {
- return getProxyMap(Field.class, FIELD_PROXY_MAP);
+ public Map<Class<?>, ThreadLocalProxy<?>> getConstructorProxies() {
+ if (constructorProxiesAvailable) {
+ return getConstructorProxyMap(false).get(serviceClass);
+ } else {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> getConstructorProxyMap(boolean create) {
+ Object property = bus.getProperty(CONSTRUCTOR_PROXY_MAP);
+ if (property == null) {
+ Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>> map
+ = new ConcurrentHashMap<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>>(2);
+ bus.setProperty(CONSTRUCTOR_PROXY_MAP, map);
+ property = map;
+ }
+ return (Map<Class<?>, Map<Class<?>, ThreadLocalProxy<?>>>)property;
+ }
+
+ private Map<Class<?>, Map<Field, ThreadLocalProxy<?>>> getFieldProxyMap(boolean create) {
+ return getProxyMap(Field.class, FIELD_PROXY_MAP, create);
}
- private Map<Class<?>, Map<Method, ThreadLocalProxy<?>>> getSetterProxyMap() {
- return getProxyMap(Method.class, SETTER_PROXY_MAP);
+ private Map<Class<?>, Map<Method, ThreadLocalProxy<?>>> getSetterProxyMap(boolean create) {
+ return getProxyMap(Method.class, SETTER_PROXY_MAP, create);
}
private void findContextSetterMethods(Class<?> cls) {
@@ -176,7 +210,7 @@ public abstract class AbstractResourceIn
}
addToMap(contextMethods, contextClass, m);
if (m.getParameterTypes()[0] != Application.class) {
- addToMap(getSetterProxyMap(), m,
+ addToMap(getSetterProxyMap(true), m,
InjectionUtils.createThreadLocalProxy(m.getParameterTypes()[0]));
}
}
@@ -194,11 +228,11 @@ public abstract class AbstractResourceIn
}
public ThreadLocalProxy<?> getContextFieldProxy(Field f) {
- return getProxy(getFieldProxyMap(), f);
+ return getProxy(getFieldProxyMap(true), f);
}
public ThreadLocalProxy<?> getContextSetterProxy(Method m) {
- return getProxy(getSetterProxyMap(), m);
+ return getProxy(getSetterProxyMap(true), m);
}
public abstract boolean isSingleton();
@@ -215,12 +249,17 @@ public abstract class AbstractResourceIn
if (property != null) {
((Map)property).clear();
}
+ property = bus.getProperty(CONSTRUCTOR_PROXY_MAP);
+ if (property != null) {
+ ((Map)property).clear();
+ }
}
}
public void clearThreadLocalProxies() {
- clearProxies(getFieldProxyMap());
- clearProxies(getSetterProxyMap());
+ clearProxies(getFieldProxyMap(false));
+ clearProxies(getSetterProxyMap(false));
+ clearProxies(getConstructorProxyMap(false));
}
private <T> void clearProxies(Map<Class<?>, Map<T, ThreadLocalProxy<?>>> tlps) {
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ProviderInfo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ProviderInfo.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ProviderInfo.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/model/ProviderInfo.java Wed May 1 15:42:52 2013
@@ -19,14 +19,23 @@
package org.apache.cxf.jaxrs.model;
+import java.util.Map;
+
import org.apache.cxf.Bus;
+import org.apache.cxf.jaxrs.impl.tl.ThreadLocalProxy;
public class ProviderInfo<T> extends AbstractResourceInfo {
private T provider;
public ProviderInfo(T provider, Bus bus) {
- super(provider.getClass(), provider.getClass(), true, bus);
+ this(provider, null, bus);
+ }
+
+ public ProviderInfo(T provider,
+ Map<Class<?>, ThreadLocalProxy<?>> constructorProxies,
+ Bus bus) {
+ super(provider.getClass(), provider.getClass(), true, true, constructorProxies, bus);
this.provider = provider;
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/SpringResourceFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/SpringResourceFactory.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/SpringResourceFactory.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/SpringResourceFactory.java Wed May 1 15:42:52 2013
@@ -71,7 +71,7 @@ public class SpringResourceFactory imple
* {@inheritDoc}
*/
public Object getInstance(Message m) {
- Object[] values = ResourceUtils.createConstructorArguments(c, m);
+ Object[] values = ResourceUtils.createConstructorArguments(c, m, !isSingleton());
Object instance = values.length > 0 ? ac.getBean(beanId, values) : ac.getBean(beanId);
if (!isSingleton || m == null) {
InjectionUtils.invokeLifeCycleMethod(instance, postConstructMethod);
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/InjectionUtils.java Wed May 1 15:42:52 2013
@@ -963,6 +963,7 @@ public final class InjectionUtils {
if (resource.contextsAvailable()) {
injectContextMethods(requestObject, resource, message);
injectContextFields(requestObject, resource, message);
+ injectConstructorProxies(requestObject, resource, message);
}
}
@@ -1008,6 +1009,20 @@ public final class InjectionUtils {
}
}
+ @SuppressWarnings("unchecked")
+ public static void injectConstructorProxies(Object o,
+ AbstractResourceInfo cri,
+ Message m) {
+
+ Map<Class<?>, ThreadLocalProxy<?>> proxies = cri.getConstructorProxies();
+ if (proxies != null) {
+ for (Map.Entry<Class<?>, ThreadLocalProxy<?>> entry : proxies.entrySet()) {
+ Object value = JAXRSUtils.createContextValue(m, entry.getKey(), entry.getKey());
+ ((ThreadLocalProxy<Object>)entry.getValue()).set(value);
+ }
+ }
+ }
+
public static MultivaluedMap<String, Object> extractValuesFromBean(Object bean, String baseName) {
MultivaluedMap<String, Object> values = new MetadataMap<String, Object>();
fillInValuesFromBean(bean, baseName, values);
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/ResourceUtils.java Wed May 1 15:42:52 2013
@@ -614,7 +614,7 @@ public final class ResourceUtils {
return op;
}
- public static Object[] createConstructorArguments(Constructor<?> c, Message m) {
+ public static Object[] createConstructorArguments(Constructor<?> c, Message m, boolean perRequest) {
Class<?>[] params = c.getParameterTypes();
Annotation[][] anns = c.getParameterAnnotations();
Type[] genericTypes = c.getGenericParameterTypes();
@@ -624,8 +624,14 @@ public final class ResourceUtils {
Object[] values = new Object[params.length];
for (int i = 0; i < params.length; i++) {
if (AnnotationUtils.getAnnotation(anns[i], Context.class) != null) {
- values[i] = JAXRSUtils.createContextValue(m, genericTypes[i], params[i]);
+ if (perRequest) {
+ values[i] = JAXRSUtils.createContextValue(m, genericTypes[i], params[i]);
+ } else {
+ values[i] = InjectionUtils.createThreadLocalProxy(params[i]);
+ }
} else {
+ // this branch won't execute for singletons given that the found constructor
+ // is guaranteed to have only Context parameters, if any, for singletons
Parameter p = ResourceUtils.getParameter(i, anns[i], params[i]);
values[i] = JAXRSUtils.createHttpParameterValue(
p, params[i], genericTypes[i], anns[i], m, templateValues, null);
@@ -646,27 +652,31 @@ public final class ResourceUtils {
List<Object> providers = new ArrayList<Object>();
Map<Class<?>, ResourceProvider> map = new HashMap<Class<?>, ResourceProvider>();
- // Note, app.getClasse() returns a list of per-resource classes
+ // Note, app.getClasses() returns a list of per-request classes
// or singleton provider classes
- for (Class<?> c : app.getClasses()) {
- if (isValidApplicationClass(c, singletons)) {
- if (isValidProvider(c)) {
+ for (Class<?> cls : app.getClasses()) {
+ if (isValidApplicationClass(cls, singletons)) {
+ if (isValidProvider(cls)) {
try {
- providers.add(c.newInstance());
+ Constructor<?> c = ResourceUtils.findResourceConstructor(cls, false);
+ if (c.getParameterTypes().length == 0) {
+ providers.add(c.newInstance());
+ } else {
+ providers.add(c);
+ }
} catch (Throwable ex) {
- throw new RuntimeException("Provider " + c.getName() + " can not be created", ex);
+ throw new RuntimeException("Provider " + cls.getName() + " can not be created", ex);
}
} else {
- resourceClasses.add(c);
- map.put(c, new PerRequestResourceProvider(c));
+ resourceClasses.add(cls);
+ map.put(cls, new PerRequestResourceProvider(cls));
}
}
}
// we can get either a provider or resource class here
for (Object o : singletons) {
- boolean isProvider = o.getClass().getAnnotation(Provider.class) != null;
- if (isProvider) {
+ if (isValidProvider(o.getClass())) {
providers.add(o);
} else {
resourceClasses.add(o.getClass());
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/BookApplication.java Wed May 1 15:42:52 2013
@@ -18,14 +18,19 @@
*/
package org.apache.cxf.systest.jaxrs;
+import java.io.IOException;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.UriInfo;
@ApplicationPath("/thebooks")
public class BookApplication extends Application {
@@ -49,6 +54,7 @@ public class BookApplication extends App
classes.add(org.apache.cxf.systest.jaxrs.BookStorePerRequest.class);
classes.add(org.apache.cxf.systest.jaxrs.jaxws.BookStoreJaxrsJaxws.class);
classes.add(org.apache.cxf.systest.jaxrs.RuntimeExceptionMapper.class);
+ classes.add(BookRequestFilter.class);
return classes;
}
@@ -76,4 +82,21 @@ public class BookApplication extends App
}
defaultId = Long.valueOf(sb.toString());
}
+
+ public static class BookRequestFilter implements ContainerRequestFilter {
+ private UriInfo ui;
+
+ public BookRequestFilter(@Context UriInfo ui) {
+ this.ui = ui;
+ }
+
+ @Override
+ public void filter(ContainerRequestContext context) throws IOException {
+ if (ui.getRequestUri().toString().endsWith("/application11/thebooks/bookstore2/bookheaders")) {
+ context.getHeaders().put("BOOK", Arrays.asList("1", "2", "3"));
+ }
+
+ }
+
+ }
}
Modified: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java?rev=1478057&r1=1478056&r2=1478057&view=diff
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java (original)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSClientServerNonSpringBookTest.java Wed May 1 15:42:52 2013
@@ -154,6 +154,15 @@ public class JAXRSClientServerNonSpringB
}
@Test
+ public void testGetBook123Application11PerRequest() throws Exception {
+ WebClient wc = WebClient.create("http://localhost:" + PORT + "/application11/thebooks/bookstore2/bookheaders");
+ wc.accept("application/xml");
+ Book book = wc.get(Book.class);
+ assertEquals("CXF in Action", book.getName());
+ assertEquals(123L, book.getId());
+ }
+
+ @Test
public void testGetNonExistentBook() throws Exception {
WebClient wc = WebClient.create("http://localhost:" + PORT
+ "/application11/thebooks/bookstore/books/321");