Allow ServiceLocator instantiation to be controlled via RequestFactory ServiceLocator.
http://gwt-code-reviews.appspot.com/1427801/
http://code.google.com/p/google-web-toolkit/issues/detail?id=6264
Patch by: daniel.r.bell
Review by: bobv, t.broyer
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10021 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/web/bindery/requestfactory/server/LocatorServiceLayer.java b/user/src/com/google/web/bindery/requestfactory/server/LocatorServiceLayer.java
index 4a292d2..aa1c5d6 100644
--- a/user/src/com/google/web/bindery/requestfactory/server/LocatorServiceLayer.java
+++ b/user/src/com/google/web/bindery/requestfactory/server/LocatorServiceLayer.java
@@ -50,17 +50,23 @@
@Override
public Object createServiceInstance(Method contextMethod, Method domainMethod) {
- Class<? extends ServiceLocator> locatorType =
- getTop().resolveServiceLocator(contextMethod, domainMethod);
- ServiceLocator locator = newInstance(locatorType, ServiceLocator.class);
+ Class<? extends ServiceLocator> locatorType = getTop().resolveServiceLocator(
+ contextMethod, domainMethod);
+ ServiceLocator locator = getTop().createServiceLocator(locatorType);
// Enclosing class may be a parent class, so invoke on service class
Class<?> declaringClass = contextMethod.getDeclaringClass();
- Class<?> serviceClass =
- getTop().resolveServiceClass(declaringClass.asSubclass(RequestContext.class));
+ Class<?> serviceClass = getTop().resolveServiceClass(
+ declaringClass.asSubclass(RequestContext.class));
return locator.getInstance(serviceClass);
}
@Override
+ public <T extends ServiceLocator> T createServiceLocator(
+ Class<T> serviceLocatorType) {
+ return newInstance(serviceLocatorType, ServiceLocator.class);
+ }
+
+ @Override
public Object getId(Object domainObject) {
return doGetId(domainObject);
}
@@ -94,7 +100,8 @@
* method is non-static.
*/
@Override
- public boolean requiresServiceLocator(Method contextMethod, Method domainMethod) {
+ public boolean requiresServiceLocator(Method contextMethod,
+ Method domainMethod) {
return Request.class.isAssignableFrom(contextMethod.getReturnType())
&& !Modifier.isStatic(domainMethod.getModifiers());
}
@@ -102,7 +109,8 @@
@Override
public Class<? extends Locator<?, ?>> resolveLocator(Class<?> domainType) {
// Find the matching BaseProxy
- Class<?> proxyType = getTop().resolveClientType(domainType, BaseProxy.class, false);
+ Class<?> proxyType = getTop().resolveClientType(domainType,
+ BaseProxy.class, false);
if (proxyType == null) {
return null;
}
@@ -118,12 +126,14 @@
} else if (ln != null && ln.locator().length() > 0) {
try {
@SuppressWarnings("unchecked")
- Class<? extends Locator<?, ?>> found =
- (Class<? extends Locator<?, ?>>) Class.forName(ln.locator(), false,
- getTop().getDomainClassLoader()).asSubclass(Locator.class);
+ Class<? extends Locator<?, ?>> found = (Class<? extends Locator<?, ?>>) Class.forName(
+ ln.locator(), false, getTop().getDomainClassLoader()).asSubclass(
+ Locator.class);
locatorType = found;
} catch (ClassNotFoundException e) {
- return die(e, "Could not find the locator type specified in the @%s annotation %s",
+ return die(
+ e,
+ "Could not find the locator type specified in the @%s annotation %s",
ProxyForName.class.getCanonicalName(), ln.value());
}
} else {
@@ -134,8 +144,8 @@
}
@Override
- public Class<? extends ServiceLocator> resolveServiceLocator(Method contextMethod,
- Method domainMethod) {
+ public Class<? extends ServiceLocator> resolveServiceLocator(
+ Method contextMethod, Method domainMethod) {
Class<? extends ServiceLocator> locatorType;
// Look at the RequestContext
@@ -146,11 +156,12 @@
locatorType = l.locator();
} else if (ln != null && ln.locator().length() > 0) {
try {
- locatorType =
- Class.forName(ln.locator(), false, getTop().getDomainClassLoader()).asSubclass(
- ServiceLocator.class);
+ locatorType = Class.forName(ln.locator(), false,
+ getTop().getDomainClassLoader()).asSubclass(ServiceLocator.class);
} catch (ClassNotFoundException e) {
- return die(e, "Could not find the locator type specified in the @%s annotation %s",
+ return die(
+ e,
+ "Could not find the locator type specified in the @%s annotation %s",
ServiceName.class.getCanonicalName(), ln.value());
}
} else {
@@ -201,7 +212,8 @@
@SuppressWarnings("unchecked")
private <T, I> Locator<T, I> getLocator(Class<T> domainType) {
- Class<? extends Locator<?, ?>> locatorType = getTop().resolveLocator(domainType);
+ Class<? extends Locator<?, ?>> locatorType = getTop().resolveLocator(
+ domainType);
if (locatorType == null) {
return null;
}
@@ -217,7 +229,8 @@
} catch (IllegalAccessException e) {
ex = e;
}
- return this.<T> die(ex, "Could not instantiate %s %s. Is it default-instantiable?", base
- .getSimpleName(), clazz.getCanonicalName());
+ return this.<T> die(ex,
+ "Could not instantiate %s %s. Is it default-instantiable?",
+ base.getSimpleName(), clazz.getCanonicalName());
}
}
diff --git a/user/src/com/google/web/bindery/requestfactory/server/ServiceLayer.java b/user/src/com/google/web/bindery/requestfactory/server/ServiceLayer.java
index 2664b86..484f954 100644
--- a/user/src/com/google/web/bindery/requestfactory/server/ServiceLayer.java
+++ b/user/src/com/google/web/bindery/requestfactory/server/ServiceLayer.java
@@ -61,8 +61,8 @@
public static ServiceLayer create(ServiceLayerDecorator... decorators) {
List<ServiceLayerDecorator> list = new ArrayList<ServiceLayerDecorator>();
// Always hit the cache first
- ServiceLayerDecorator cache =
- ENABLE_CACHE ? new ServiceLayerCache() : new ServiceLayerDecorator();
+ ServiceLayerDecorator cache = ENABLE_CACHE ? new ServiceLayerCache()
+ : new ServiceLayerDecorator();
list.add(cache);
// The the user-provided decorators
if (decorators != null) {
@@ -125,7 +125,18 @@
* @param domainMethod the method that the service object must implement
* @return an instance of the requested service object
*/
- public abstract Object createServiceInstance(Method contextMethod, Method domainMethod);
+ public abstract Object createServiceInstance(Method contextMethod,
+ Method domainMethod);
+
+ /**
+ * Create an instance of the requested {@link ServiceLocator} type.
+ *
+ * @param <T> the requested ServiceLocator type
+ * @param clazz the requested ServiceLocator type
+ * @return an instance of the requested ServiceLocator type
+ */
+ public abstract <T extends ServiceLocator> T createServiceLocator(
+ Class<T> clazz);
/**
* Returns the ClassLoader that should be used when attempting to access
@@ -253,7 +264,8 @@
* @return the requested objects, elements of which may be {@code null} if the
* requested objects were irretrievable
*/
- public abstract List<Object> loadDomainObjects(List<Class<?>> classes, List<Object> domainIds);
+ public abstract List<Object> loadDomainObjects(List<Class<?>> classes,
+ List<Object> domainIds);
/**
* Determines if the invocation of a domain method requires a
@@ -264,7 +276,8 @@
* @param domainMethod a domain method
* @return {@code true} if a ServiceLocator is required
*/
- public abstract boolean requiresServiceLocator(Method contextMethod, Method domainMethod);
+ public abstract boolean requiresServiceLocator(Method contextMethod,
+ Method domainMethod);
/**
* Given a type token previously returned from
@@ -288,8 +301,8 @@
* @return a class that represents {@code domainClass} on the client which is
* assignable to {@code clientType}
*/
- public abstract <T> Class<? extends T> resolveClientType(Class<?> domainClass,
- Class<T> clientType, boolean required);
+ public abstract <T> Class<? extends T> resolveClientType(
+ Class<?> domainClass, Class<T> clientType, boolean required);
/**
* Determine the domain (server-side) type that the given client type is
@@ -318,7 +331,8 @@
* @return the type of Locator to use, or {@code null} if the type conforms to
* the RequestFactory entity protocol
*/
- public abstract Class<? extends Locator<?, ?>> resolveLocator(Class<?> domainType);
+ public abstract Class<? extends Locator<?, ?>> resolveLocator(
+ Class<?> domainType);
/**
* Find a RequestContext method declaration by name.
@@ -330,29 +344,32 @@
* @return the method declaration, or {@code null} if the method does not
* exist
*/
- public abstract Method resolveRequestContextMethod(String requestContextClass, String methodName);
+ public abstract Method resolveRequestContextMethod(
+ String requestContextClass, String methodName);
/**
* Given a {@link RequestContext} method, find the service class referenced in
* the {@link Service} or {@link ServiceName} annotation.
- *
+ *
* @param requestContextClass a RequestContext interface
* @return the type of service to use
*/
- public abstract Class<?> resolveServiceClass(Class<? extends RequestContext> requestContextClass);
+ public abstract Class<?> resolveServiceClass(
+ Class<? extends RequestContext> requestContextClass);
/**
* Given a RequestContext method declaration, resolve the
* {@link ServiceLocator} that should be used when invoking the domain method.
- * This method will only be called if {@link #requiresServiceLocator(Method, Method)}
- * returned {@code true} for the associated domain method.
+ * This method will only be called if
+ * {@link #requiresServiceLocator(Method, Method)} returned {@code true} for
+ * the associated domain method.
*
* @param contextMethod a RequestContext method declaration
* @param domainMethod the domain method that will be invoked
* @return the type of ServiceLocator to use
*/
- public abstract Class<? extends ServiceLocator> resolveServiceLocator(Method contextMethod,
- Method domainMethod);
+ public abstract Class<? extends ServiceLocator> resolveServiceLocator(
+ Method contextMethod, Method domainMethod);
/**
* Return a string used to represent the given type in the wire protocol.
@@ -370,8 +387,8 @@
* @param expectedType the type of the property
* @param value the new value
*/
- public abstract void setProperty(Object domainObject, String property, Class<?> expectedType,
- Object value);
+ public abstract void setProperty(Object domainObject, String property,
+ Class<?> expectedType, Object value);
/**
* Invoke a JSR 303 validator on the given domain object. If no validator is
diff --git a/user/src/com/google/web/bindery/requestfactory/server/ServiceLayerDecorator.java b/user/src/com/google/web/bindery/requestfactory/server/ServiceLayerDecorator.java
index 2bbf261..b2a7f89 100644
--- a/user/src/com/google/web/bindery/requestfactory/server/ServiceLayerDecorator.java
+++ b/user/src/com/google/web/bindery/requestfactory/server/ServiceLayerDecorator.java
@@ -61,6 +61,11 @@
}
@Override
+ public <T extends ServiceLocator> T createServiceLocator(Class<T> clazz) {
+ return getNext().createServiceLocator(clazz);
+ }
+
+ @Override
public ClassLoader getDomainClassLoader() {
return getNext().getDomainClassLoader();
}
@@ -116,12 +121,14 @@
}
@Override
- public List<Object> loadDomainObjects(List<Class<?>> classes, List<Object> domainIds) {
+ public List<Object> loadDomainObjects(List<Class<?>> classes,
+ List<Object> domainIds) {
return getNext().loadDomainObjects(classes, domainIds);
}
@Override
- public boolean requiresServiceLocator(Method contextMethod, Method domainMethod) {
+ public boolean requiresServiceLocator(Method contextMethod,
+ Method domainMethod) {
return getNext().requiresServiceLocator(contextMethod, domainMethod);
}
@@ -131,8 +138,8 @@
}
@Override
- public <T> Class<? extends T> resolveClientType(Class<?> domainClass, Class<T> clientType,
- boolean required) {
+ public <T> Class<? extends T> resolveClientType(Class<?> domainClass,
+ Class<T> clientType, boolean required) {
return getNext().resolveClientType(domainClass, clientType, required);
}
@@ -152,18 +159,21 @@
}
@Override
- public Method resolveRequestContextMethod(String requestContextClass, String methodName) {
- return getNext().resolveRequestContextMethod(requestContextClass, methodName);
+ public Method resolveRequestContextMethod(String requestContextClass,
+ String methodName) {
+ return getNext().resolveRequestContextMethod(requestContextClass,
+ methodName);
}
@Override
- public Class<?> resolveServiceClass(Class<? extends RequestContext> requestContextClass) {
+ public Class<?> resolveServiceClass(
+ Class<? extends RequestContext> requestContextClass) {
return getNext().resolveServiceClass(requestContextClass);
}
@Override
- public Class<? extends ServiceLocator> resolveServiceLocator(Method contextMethod,
- Method domainMethod) {
+ public Class<? extends ServiceLocator> resolveServiceLocator(
+ Method contextMethod, Method domainMethod) {
return getNext().resolveServiceLocator(contextMethod, domainMethod);
}
@@ -173,7 +183,8 @@
}
@Override
- public void setProperty(Object domainObject, String property, Class<?> expectedType, Object value) {
+ public void setProperty(Object domainObject, String property,
+ Class<?> expectedType, Object value) {
getNext().setProperty(domainObject, property, expectedType, value);
}
@@ -194,7 +205,8 @@
* @throws UnexpectedException this method never returns normally
* @see #report(String, Object...)
*/
- protected final <T> T die(Throwable e, String message, Object... args) throws UnexpectedException {
+ protected final <T> T die(Throwable e, String message, Object... args)
+ throws UnexpectedException {
String msg = String.format(message, args);
log.log(Level.SEVERE, msg, e);
throw new UnexpectedException(msg, e);
@@ -217,8 +229,8 @@
* Report an exception thrown by code that is under the control of the
* end-developer.
*
- * @param userGeneratedException an {@link InvocationTargetException} thrown by an invocation of
- * user-provided code
+ * @param userGeneratedException an {@link InvocationTargetException} thrown
+ * by an invocation of user-provided code
* @throws ReportableException this method never returns normally
*/
protected final <T> T report(InvocationTargetException userGeneratedException)
@@ -235,7 +247,8 @@
* @throws ReportableException this method never returns normally
* @see #die(Throwable, String, Object...)
*/
- protected final <T> T report(String msg, Object... args) throws ReportableException {
+ protected final <T> T report(String msg, Object... args)
+ throws ReportableException {
throw new ReportableException(String.format(msg, args));
}
diff --git a/user/test/com/google/web/bindery/requestfactory/server/ServiceLocatorTest.java b/user/test/com/google/web/bindery/requestfactory/server/ServiceLocatorTest.java
new file mode 100644
index 0000000..3fee0cd
--- /dev/null
+++ b/user/test/com/google/web/bindery/requestfactory/server/ServiceLocatorTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.web.bindery.requestfactory.server;
+
+import com.google.web.bindery.requestfactory.shared.ServiceLocator;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests creating of ServiceLocators with custom ServiceLayerDecorators
+ */
+public class ServiceLocatorTest extends TestCase {
+
+ static class CustomLocatorLayer extends ServiceLayerDecorator {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T extends ServiceLocator> T createServiceLocator(Class<T> clazz) {
+ return (T) ServiceLocatorImpl.INSTANCE;
+ }
+ }
+
+ static class ServiceLocatorImpl implements ServiceLocator {
+ static final ServiceLocatorImpl INSTANCE = new ServiceLocatorImpl();
+
+ public Object getInstance(Class<?> clazz) {
+ return new Object();
+ }
+ }
+
+ public void testGetsServiceLocatorFromDecorator() {
+ ServiceLayer layer = ServiceLayer.create(new CustomLocatorLayer());
+ ServiceLocatorImpl locator = layer.createServiceLocator(ServiceLocatorImpl.class);
+ assertSame(ServiceLocatorImpl.INSTANCE, locator);
+ }
+
+ public void testInstantiatesServiceLocatorByDefault() {
+ ServiceLayer layer = ServiceLayer.create();
+ ServiceLocatorImpl locator = layer.createServiceLocator(ServiceLocatorImpl.class);
+ assertNotNull(locator);
+ assertNotSame(ServiceLocatorImpl.INSTANCE, locator);
+ }
+}
diff --git a/user/test/com/google/web/bindery/requestfactory/vm/RequestFactoryJreSuite.java b/user/test/com/google/web/bindery/requestfactory/vm/RequestFactoryJreSuite.java
index 3187318..5b7d5ed 100644
--- a/user/test/com/google/web/bindery/requestfactory/vm/RequestFactoryJreSuite.java
+++ b/user/test/com/google/web/bindery/requestfactory/vm/RequestFactoryJreSuite.java
@@ -24,6 +24,7 @@
import com.google.web.bindery.requestfactory.server.RequestFactoryJreTest;
import com.google.web.bindery.requestfactory.server.RequestFactoryUnicodeEscapingJreTest;
import com.google.web.bindery.requestfactory.server.ServiceInheritanceJreTest;
+import com.google.web.bindery.requestfactory.server.ServiceLocatorTest;
import com.google.web.bindery.requestfactory.shared.impl.SimpleEntityProxyIdTest;
import junit.framework.Test;
@@ -50,6 +51,7 @@
suite.addTestSuite(RequestFactoryJreTest.class);
suite.addTestSuite(RequestFactoryUnicodeEscapingJreTest.class);
suite.addTestSuite(ServiceInheritanceJreTest.class);
+ suite.addTestSuite(ServiceLocatorTest.class);
suite.addTestSuite(SimpleEntityProxyIdTest.class);
return suite;