Cherry picking r9857 into releases/2.3m1 for GWT issue 5807
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.3@9876 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/requestfactory/server/LocatorServiceLayer.java b/user/src/com/google/gwt/requestfactory/server/LocatorServiceLayer.java
index dbf81ed..aa6c95d 100644
--- a/user/src/com/google/gwt/requestfactory/server/LocatorServiceLayer.java
+++ b/user/src/com/google/gwt/requestfactory/server/LocatorServiceLayer.java
@@ -20,6 +20,7 @@
import com.google.gwt.requestfactory.shared.ProxyFor;
import com.google.gwt.requestfactory.shared.ProxyForName;
import com.google.gwt.requestfactory.shared.Request;
+import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.Service;
import com.google.gwt.requestfactory.shared.ServiceLocator;
import com.google.gwt.requestfactory.shared.ServiceName;
@@ -52,7 +53,11 @@
Class<? extends ServiceLocator> locatorType =
getTop().resolveServiceLocator(contextMethod, domainMethod);
ServiceLocator locator = newInstance(locatorType, ServiceLocator.class);
- return locator.getInstance(domainMethod.getDeclaringClass());
+ // Enclosing class may be a parent class, so invoke on service class
+ Class<?> declaringClass = contextMethod.getDeclaringClass();
+ Class<?> serviceClass =
+ getTop().resolveServiceClass((Class<? extends RequestContext>) declaringClass);
+ return locator.getInstance(serviceClass);
}
@Override
diff --git a/user/src/com/google/gwt/requestfactory/server/ResolverServiceLayer.java b/user/src/com/google/gwt/requestfactory/server/ResolverServiceLayer.java
index dc4fa06..a6490e5 100644
--- a/user/src/com/google/gwt/requestfactory/server/ResolverServiceLayer.java
+++ b/user/src/com/google/gwt/requestfactory/server/ResolverServiceLayer.java
@@ -117,22 +117,9 @@
@Override
public Method resolveDomainMethod(Method requestContextMethod) {
- Class<?> enclosing = requestContextMethod.getDeclaringClass();
-
- Class<?> searchIn = null;
- Service s = enclosing.getAnnotation(Service.class);
- if (s != null) {
- searchIn = s.value();
- }
- ServiceName sn = enclosing.getAnnotation(ServiceName.class);
- if (sn != null) {
- searchIn = forName(sn.value());
- }
- if (searchIn == null) {
- die(null, "The %s type %s did not specify a service type", RequestContext.class
- .getSimpleName(), enclosing.getCanonicalName());
- }
-
+ Class<?> declaringClass = requestContextMethod.getDeclaringClass();
+ Class<?> searchIn =
+ getTop().resolveServiceClass((Class<? extends RequestContext>) declaringClass);
Class<?>[] parameterTypes = requestContextMethod.getParameterTypes();
Class<?>[] domainArgs = new Class<?>[parameterTypes.length];
for (int i = 0, j = domainArgs.length; i < j; i++) {
@@ -179,6 +166,25 @@
}
@Override
+ public Class<?> resolveServiceClass(Class<? extends RequestContext> requestContextClass) {
+ Class<?> searchIn = null;
+ Service s = requestContextClass.getAnnotation(Service.class);
+ // TODO Handle case when both annotations are present
+ if (s != null) {
+ searchIn = s.value();
+ }
+ ServiceName sn = requestContextClass.getAnnotation(ServiceName.class);
+ if (sn != null) {
+ searchIn = forName(sn.value());
+ }
+ if (searchIn == null) {
+ die(null, "The %s type %s did not specify a service type", RequestContext.class
+ .getSimpleName(), requestContextClass.getCanonicalName());
+ }
+ return searchIn;
+ }
+
+ @Override
public String resolveTypeToken(Class<? extends BaseProxy> clazz) {
return clazz.getName();
}
diff --git a/user/src/com/google/gwt/requestfactory/server/ServiceLayer.java b/user/src/com/google/gwt/requestfactory/server/ServiceLayer.java
index 7a58918..753fe1d 100644
--- a/user/src/com/google/gwt/requestfactory/server/ServiceLayer.java
+++ b/user/src/com/google/gwt/requestfactory/server/ServiceLayer.java
@@ -17,6 +17,7 @@
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.Locator;
+import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.ServiceLocator;
import java.lang.reflect.Method;
@@ -333,6 +334,15 @@
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);
+
+ /**
* 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)}
@@ -373,4 +383,4 @@
* @return the violations associated with the domain object
*/
public abstract <T> Set<ConstraintViolation<T>> validate(T domainObject);
-}
\ No newline at end of file
+}
diff --git a/user/src/com/google/gwt/requestfactory/server/ServiceLayerDecorator.java b/user/src/com/google/gwt/requestfactory/server/ServiceLayerDecorator.java
index 27bcbf4..d93f359 100644
--- a/user/src/com/google/gwt/requestfactory/server/ServiceLayerDecorator.java
+++ b/user/src/com/google/gwt/requestfactory/server/ServiceLayerDecorator.java
@@ -17,6 +17,7 @@
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.Locator;
+import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.ServiceLocator;
import java.lang.reflect.InvocationTargetException;
@@ -156,6 +157,11 @@
}
@Override
+ public Class<?> resolveServiceClass(Class<? extends RequestContext> requestContextClass) {
+ return getNext().resolveServiceClass(requestContextClass);
+ }
+
+ @Override
public Class<? extends ServiceLocator> resolveServiceLocator(Method contextMethod,
Method domainMethod) {
return getNext().resolveServiceLocator(contextMethod, domainMethod);
diff --git a/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java b/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
index 5736e21..06285d8 100644
--- a/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
+++ b/user/test/com/google/gwt/requestfactory/RequestFactoryJreSuite.java
@@ -24,6 +24,7 @@
import com.google.gwt.requestfactory.server.RequestFactoryInterfaceValidatorTest;
import com.google.gwt.requestfactory.server.RequestFactoryJreTest;
import com.google.gwt.requestfactory.server.RequestFactoryUnicodeEscapingJreTest;
+import com.google.gwt.requestfactory.server.ServiceInheritanceJreTest;
import com.google.gwt.requestfactory.shared.impl.SimpleEntityProxyIdTest;
import junit.framework.Test;
@@ -50,6 +51,7 @@
suite.addTestSuite(RequestFactoryJreTest.class);
suite.addTestSuite(RequestFactoryModelTest.class);
suite.addTestSuite(RequestFactoryUnicodeEscapingJreTest.class);
+ suite.addTestSuite(ServiceInheritanceJreTest.class);
suite.addTestSuite(SimpleEntityProxyIdTest.class);
return suite;
}
diff --git a/user/test/com/google/gwt/requestfactory/server/ServiceInheritanceJreTest.java b/user/test/com/google/gwt/requestfactory/server/ServiceInheritanceJreTest.java
new file mode 100644
index 0000000..acfeeb7
--- /dev/null
+++ b/user/test/com/google/gwt/requestfactory/server/ServiceInheritanceJreTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.gwt.requestfactory.server;
+
+import com.google.gwt.requestfactory.shared.ServiceInheritanceTest;
+
+/**
+ * A JRE version of {@link ServiceInheritanceTest}.
+ */
+public class ServiceInheritanceJreTest extends ServiceInheritanceTest {
+ @Override
+ public String getModuleName() {
+ return null;
+ }
+
+ @Override
+ protected Factory createFactory() {
+ return RequestFactoryJreTest.createInProcess(Factory.class);
+ }
+}
diff --git a/user/test/com/google/gwt/requestfactory/shared/ServiceInheritanceTest.java b/user/test/com/google/gwt/requestfactory/shared/ServiceInheritanceTest.java
new file mode 100644
index 0000000..88dce99
--- /dev/null
+++ b/user/test/com/google/gwt/requestfactory/shared/ServiceInheritanceTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.gwt.requestfactory.shared;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.event.shared.SimpleEventBus;
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Tests the ability of instance services to inherit methods
+ * from a base class.
+ */
+public class ServiceInheritanceTest extends GWTTestCase {
+
+ /**
+ * Generic locator returns an instance of the class named in
+ * the @{@link Service} annotation
+ */
+ public static class AnyServiceLocator implements ServiceLocator {
+
+ @Override
+ public Object getInstance(Class<?> clazz) {
+ assertTrue(BaseImpl.class.isAssignableFrom(clazz));
+ try {
+ return clazz.newInstance();
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * The factory under test.
+ */
+ protected interface Factory extends RequestFactory {
+ SumService sumContext();
+ SumServiceBase sumBaseContext();
+ }
+
+ /**
+ * Specifies a service which extends a base class
+ */
+ @Service(value = SubclassImpl.class, locator = AnyServiceLocator.class)
+ interface SumService extends RequestContext {
+ Request<Integer> add(int n);
+ }
+
+ /**
+ * Specifies a service which is a base class
+ */
+ @Service(value = BaseImpl.class, locator = AnyServiceLocator.class)
+ interface SumServiceBase extends RequestContext {
+ Request<Integer> add(int n);
+ }
+
+ static class BaseImpl {
+ protected int base;
+
+ public BaseImpl() {
+ base = 5;
+ }
+
+ public Integer add(int n) {
+ return base + n;
+ }
+ }
+
+ static class SubclassImpl extends BaseImpl {
+ public SubclassImpl() {
+ // Distinguish from base service
+ base = 8;
+ }
+ }
+
+ private static final int TEST_DELAY = 5000;
+
+ private Factory factory;
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.requestfactory.RequestFactorySuite";
+ }
+
+ /**
+ * Verify that the method can be invoked on the base class
+ * as well as the subclass
+ */
+ public void testInvokeMethodOnBaseClass() {
+ delayTestFinish(TEST_DELAY);
+ factory.sumBaseContext().add(13).fire(new Receiver<Integer>() {
+ @Override
+ public void onSuccess(Integer response) {
+ assertEquals((Integer) 18, response);
+ finishTest();
+ }
+ });
+ }
+
+ /**
+ * Verify that the method is invoked on the subclass,
+ * not the base class
+ */
+ public void testInvokeMethodOnSubclass() {
+ delayTestFinish(TEST_DELAY);
+ factory.sumContext().add(13).fire(new Receiver<Integer>() {
+ @Override
+ public void onSuccess(Integer response) {
+ assertEquals((Integer) 21, response);
+ finishTest();
+ }
+ });
+ }
+
+ protected Factory createFactory() {
+ Factory toReturn = GWT.create(Factory.class);
+ toReturn.initialize(new SimpleEventBus());
+ return toReturn;
+ }
+
+ @Override
+ protected void gwtSetUp() throws Exception {
+ factory = createFactory();
+ }
+
+}