Revision: 9318
Author: [email protected]
Date: Tue Nov 30 12:13:24 2010
Log: Add ServiceLocator API to allow service methods to be invoked on
non-static methods.
http://code.google.com/p/google-web-toolkit/wiki/RequestFactory_2_1_1
Issue 5680.
Patch by: bobv
Review by: rchandia,rjrjr
Review at http://gwt-code-reviews.appspot.com/1162801
http://code.google.com/p/google-web-toolkit/source/detail?r=9318
Added:
/trunk/user/src/com/google/gwt/requestfactory/shared/ServiceLocator.java
/trunk/user/test/com/google/gwt/requestfactory/server/InstanceService.java
/trunk/user/test/com/google/gwt/requestfactory/server/InstanceServiceImpl.java
/trunk/user/test/com/google/gwt/requestfactory/server/InstanceServiceLocator.java
/trunk/user/test/com/google/gwt/requestfactory/shared/InstanceServiceRequest.java
Deleted:
/trunk/user/src/com/google/gwt/requestfactory/shared/LocatorFor.java
/trunk/user/src/com/google/gwt/requestfactory/shared/LocatorForName.java
Modified:
/trunk/user/src/com/google/gwt/requestfactory/server/LocatorServiceLayer.java
/trunk/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java
/trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayer.java
/trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayerCache.java
/trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayerDecorator.java
/trunk/user/src/com/google/gwt/requestfactory/server/SimpleRequestProcessor.java
/trunk/user/src/com/google/gwt/requestfactory/shared/Locator.java
/trunk/user/src/com/google/gwt/requestfactory/shared/ProxyFor.java
/trunk/user/src/com/google/gwt/requestfactory/shared/ProxyForName.java
/trunk/user/src/com/google/gwt/requestfactory/shared/Service.java
/trunk/user/src/com/google/gwt/requestfactory/shared/ServiceName.java
/trunk/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
/trunk/user/test/com/google/gwt/requestfactory/rebind/model/RequestFactoryModelTest.java
/trunk/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
/trunk/user/test/com/google/gwt/requestfactory/shared/LocatorTest.java
/trunk/user/test/com/google/gwt/requestfactory/shared/SimpleRequestFactory.java
=======================================
--- /dev/null
+++
/trunk/user/src/com/google/gwt/requestfactory/shared/ServiceLocator.java
Tue Nov 30 12:13:24 2010
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 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;
+
+/**
+ * A ServiceLocator provides instances of a type specified by a {...@link
Service}
+ * when {...@link Request} methods declared in a {...@link RequestContext}are
mapped
+ * onto instance (non-static) methods.
+ * <p>
+ * ServiceLocator subtypes must be default instantiable (i.e. public static
+ * types with a no-arg constructor). Instances of ServiceLocators may be
+ * retained and reused by the RequestFactory service layer.
+ *
+ * @see Service#locator()
+ */
+public interface ServiceLocator {
+ /**
+ * Returns an instance of the service object.
+ *
+ * @param clazz the requested type of service object
+ * @return an instance of the service object
+ */
+ Object getInstance(Class<?> clazz);
+}
=======================================
--- /dev/null
+++
/trunk/user/test/com/google/gwt/requestfactory/server/InstanceService.java
Tue Nov 30 12:13:24 2010
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 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;
+
+/**
+ * A service API that doesn't have static methods and that can't be
+ * default-instantiated.
+ */
+public interface InstanceService {
+ Integer add(int value);
+}
=======================================
--- /dev/null
+++
/trunk/user/test/com/google/gwt/requestfactory/server/InstanceServiceImpl.java
Tue Nov 30 12:13:24 2010
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 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;
+
+/**
+ * A service API that doesn't have static methods and that can't be
+ * default-instantiated.
+ */
+public class InstanceServiceImpl implements InstanceService {
+ private final int base;
+
+ public InstanceServiceImpl(int base) {
+ this.base = base;
+ }
+
+ public Integer add(int value) {
+ return base + value;
+ }
+}
=======================================
--- /dev/null
+++
/trunk/user/test/com/google/gwt/requestfactory/server/InstanceServiceLocator.java
Tue Nov 30 12:13:24 2010
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 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.ServiceLocator;
+
+/**
+ * Demonstrates instance-based service objects.
+ */
+public class InstanceServiceLocator implements ServiceLocator {
+
+ public Object getInstance(Class<?> clazz) {
+ assert InstanceService.class.equals(clazz);
+ return clazz.cast(new InstanceServiceImpl(5));
+ }
+}
=======================================
--- /dev/null
+++
/trunk/user/test/com/google/gwt/requestfactory/shared/InstanceServiceRequest.java
Tue Nov 30 12:13:24 2010
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 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.requestfactory.server.InstanceService;
+import com.google.gwt.requestfactory.server.InstanceServiceLocator;
+
+/**
+ * Used to test the ServiceLocator extension hook.
+ */
+...@service(value = InstanceService.class, locator =
InstanceServiceLocator.class)
+public interface InstanceServiceRequest extends RequestContext {
+ Request<Integer> add(int value);
+}
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/LocatorFor.java
Mon Nov 22 08:01:19 2010
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2010 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 java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation on BaseProxy classes specifying the domain (server-side)
object
- * {...@link Locator}. Specifying an explicit {...@code Locator} removes the
- * requirement to have a {...@code findFoo()}, {...@code getId()}, and
- * {...@code getVersion()} method in the domain object type.
- *
- * @see LocatorForName
- */
-...@retention(RetentionPolicy.RUNTIME)
-...@target(ElementType.TYPE)
-public @interface LocatorFor {
- Class<? extends Locator<?, ?>> value();
-}
=======================================
---
/trunk/user/src/com/google/gwt/requestfactory/shared/LocatorForName.java
Mon Nov 22 08:01:19 2010
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2010 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 java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation on BaseProxy classes specifying the domain (server-side)
object
- * {...@link Locator}. This annotation can be used in place of {...@link
LocatorFor}
- * if the domain Locator is not available to the GWT compiler or DevMode
- * runtime.
- *
- * @see LocatorFor
- */
-...@retention(RetentionPolicy.RUNTIME)
-...@target(ElementType.TYPE)
-public @interface LocatorForName {
- String value();
-}
=======================================
---
/trunk/user/src/com/google/gwt/requestfactory/server/LocatorServiceLayer.java
Mon Nov 22 08:01:19 2010
+++
/trunk/user/src/com/google/gwt/requestfactory/server/LocatorServiceLayer.java
Tue Nov 30 12:13:24 2010
@@ -17,12 +17,19 @@
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.Locator;
-import com.google.gwt.requestfactory.shared.LocatorFor;
-import com.google.gwt.requestfactory.shared.LocatorForName;
+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.Service;
+import com.google.gwt.requestfactory.shared.ServiceLocator;
+import com.google.gwt.requestfactory.shared.ServiceName;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
/**
- * Adds support to the ServiceLayer chain for using {...@link Locator} helper
- * objects.
+ * Adds support to the ServiceLayer chain for using {...@link Locator} and
+ * {...@link ServiceLocator} helper objects.
*/
final class LocatorServiceLayer extends ServiceLayerDecorator {
@@ -37,17 +44,15 @@
@Override
public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) {
- Throwable ex;
- try {
- return clazz.newInstance();
- } catch (InstantiationException e) {
- ex = e;
- } catch (IllegalAccessException e) {
- ex = e;
- }
- return this.<T> die(ex,
- "Could not instantiate Locator %s. It is default-instantiable?",
- clazz.getCanonicalName());
+ return newInstance(clazz, Locator.class);
+ }
+
+ @Override
+ public Object createServiceInstance(Method contextMethod, Method
domainMethod) {
+ Class<? extends ServiceLocator> locatorType =
getTop().resolveServiceLocator(
+ contextMethod, domainMethod);
+ ServiceLocator locator = newInstance(locatorType,
ServiceLocator.class);
+ return locator.getInstance(domainMethod.getDeclaringClass());
}
@Override
@@ -79,6 +84,17 @@
return doLoadDomainObject(clazz, domainId);
}
+ /**
+ * Returns true if the context method returns a {...@link Request} and the
domain
+ * method is non-static.
+ */
+ @Override
+ public boolean requiresServiceLocator(Method contextMethod,
+ Method domainMethod) {
+ return Request.class.isAssignableFrom(contextMethod.getReturnType())
+ && !Modifier.isStatic(domainMethod.getModifiers());
+ }
+
@Override
public Class<? extends Locator<?, ?>> resolveLocator(Class<?>
domainType) {
// Find the matching BaseProxy
@@ -90,21 +106,24 @@
// Check it for annotations
Class<? extends Locator<?, ?>> locatorType;
- LocatorFor l = proxyType.getAnnotation(LocatorFor.class);
- LocatorForName ln = proxyType.getAnnotation(LocatorForName.class);
- if (l != null) {
- locatorType = l.value();
- } else if (ln != null) {
+ ProxyFor l = proxyType.getAnnotation(ProxyFor.class);
+ ProxyForName ln = proxyType.getAnnotation(ProxyForName.class);
+ if (l != null && !Locator.class.equals(l.locator())) {
+ @SuppressWarnings("unchecked")
+ Class<? extends Locator<?, ?>> found = (Class<? extends
Locator<?, ?>>) l.locator();
+ locatorType = found;
+ } else if (ln != null && ln.locator().length() > 0) {
try {
@SuppressWarnings("unchecked")
Class<? extends Locator<?, ?>> found = (Class<? extends
Locator<?, ?>>) Class.forName(
- ln.value(), false, domainType.getClassLoader()).asSubclass(
+ ln.locator(), false, domainType.getClassLoader()).asSubclass(
Locator.class);
locatorType = found;
} catch (ClassNotFoundException e) {
- return die(e,
- "Could not find the type specified in the @%s annotation %s",
- LocatorForName.class.getCanonicalName(), ln.value());
+ return die(
+ e,
+ "Could not find the locator type specified in the @%s
annotation %s",
+ ProxyForName.class.getCanonicalName(), ln.value());
}
} else {
// No locator annotation
@@ -112,6 +131,34 @@
}
return locatorType;
}
+
+ @Override
+ public Class<? extends ServiceLocator> resolveServiceLocator(
+ Method contextMethod, Method domainMethod) {
+ Class<? extends ServiceLocator> locatorType;
+
+ // Look at the RequestContext
+ Class<?> requestContextClass = contextMethod.getDeclaringClass();
+ Service l = requestContextClass.getAnnotation(Service.class);
+ ServiceName ln = requestContextClass.getAnnotation(ServiceName.class);
+ if (l != null && !ServiceLocator.class.equals(l.locator())) {
+ locatorType = l.locator();
+ } else if (ln != null && ln.locator().length() > 0) {
+ try {
+ locatorType = Class.forName(ln.locator(), false,
+ requestContextClass.getClassLoader()).asSubclass(
+ ServiceLocator.class);
+ } catch (ClassNotFoundException e) {
+ return die(
+ e,
+ "Could not find the locator type specified in the @%s
annotation %s",
+ ServiceName.class.getCanonicalName(), ln.value());
+ }
+ } else {
+ locatorType = null;
+ }
+ return locatorType;
+ }
private <T> Object doGetId(T domainObject) {
@SuppressWarnings("unchecked")
@@ -162,4 +209,18 @@
}
return (Locator<T, I>) getTop().createLocator(locatorType);
}
-}
+
+ private <T> T newInstance(Class<T> clazz, Class<? super T> base) {
+ Throwable ex;
+ try {
+ return clazz.newInstance();
+ } catch (InstantiationException e) {
+ ex = e;
+ } catch (IllegalAccessException e) {
+ ex = e;
+ }
+ return this.<T> die(ex,
+ "Could not instantiate %s %s. Is it default-instantiable?",
+ base.getSimpleName(), clazz.getCanonicalName());
+ }
+}
=======================================
---
/trunk/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java
Mon Nov 22 11:18:02 2010
+++
/trunk/user/src/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidator.java
Tue Nov 30 12:13:24 2010
@@ -31,8 +31,6 @@
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.InstanceRequest;
-import com.google.gwt.requestfactory.shared.LocatorFor;
-import com.google.gwt.requestfactory.shared.LocatorForName;
import com.google.gwt.requestfactory.shared.ProxyFor;
import com.google.gwt.requestfactory.shared.ProxyForName;
import com.google.gwt.requestfactory.shared.Request;
@@ -44,6 +42,7 @@
import java.io.IOException;
import java.io.InputStream;
+import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -142,6 +141,7 @@
private class DomainMapper extends EmptyVisitor {
private final ErrorContext logger;
private String domainInternalName;
+ private List<Class<? extends Annotation>> found = new
ArrayList<Class<? extends Annotation>>();
private String locatorInternalName;
public DomainMapper(ErrorContext logger) {
@@ -165,65 +165,93 @@
}
}
+ /**
+ * This method examines one annotation at a time.
+ */
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
- final boolean foundLocator =
desc.equals(Type.getDescriptor(LocatorFor.class));
- final boolean foundLocatorName =
desc.equals(Type.getDescriptor(LocatorForName.class));
- boolean foundProxy = desc.equals(Type.getDescriptor(ProxyFor.class));
- boolean foundProxyName =
desc.equals(Type.getDescriptor(ProxyForName.class));
- boolean foundService =
desc.equals(Type.getDescriptor(Service.class));
- boolean foundServiceName =
desc.equals(Type.getDescriptor(ServiceName.class));
-
- if (foundLocator || foundProxy || foundService) {
+ // Set to true if the annotation should have class literal values
+ boolean expectClasses = false;
+ // Set to true if the annonation has string values
+ boolean expectNames = false;
+
+ if (desc.equals(Type.getDescriptor(ProxyFor.class))) {
+ expectClasses = true;
+ found.add(ProxyFor.class);
+ } else if (desc.equals(Type.getDescriptor(ProxyForName.class))) {
+ expectNames = true;
+ found.add(ProxyForName.class);
+ } else if (desc.equals(Type.getDescriptor(Service.class))) {
+ expectClasses = true;
+ found.add(Service.class);
+ } else if (desc.equals(Type.getDescriptor(ServiceName.class))) {
+ expectNames = true;
+ found.add(ServiceName.class);
+ }
+
+ if (expectClasses) {
return new EmptyVisitor() {
@Override
public void visit(String name, Object value) {
if ("value".equals(name)) {
- String found = ((Type) value).getInternalName();
- if (foundLocator) {
- locatorInternalName = found;
- } else {
- domainInternalName = found;
- }
+ domainInternalName = ((Type) value).getInternalName();
+ } else if ("locator".equals(name)) {
+ locatorInternalName = ((Type) value).getInternalName();
}
}
};
}
- if (foundLocatorName || foundProxyName || foundServiceName) {
+ if (expectNames) {
return new EmptyVisitor() {
@Override
public void visit(String name, Object value) {
- if ("value".equals(name)) {
- String sourceName = (String) value;
-
- /*
- * The input is a source name, so we need to convert it to an
- * internal name. We'll do this by substituting dollar signs
for
- * the last slash in the name until there are no more
slashes.
- */
- StringBuffer desc = new
StringBuffer(sourceName.replace('.', '/'));
- while (!loader.exists(desc.toString() + ".class")) {
- logger.spam("Did not find " + desc.toString());
- int idx = desc.lastIndexOf("/");
- if (idx == -1) {
- return;
- }
- desc.setCharAt(idx, '$');
- }
-
- if (foundLocatorName) {
- locatorInternalName = desc.toString();
- } else {
- domainInternalName = desc.toString();
- }
- logger.spam(domainInternalName);
- }
+ String sourceName;
+ if ("value".equals(name) || "locator".equals(name)) {
+ sourceName = (String) value;
+ } else {
+ return;
+ }
+
+ /*
+ * The input is a source name, so we need to convert it to an
+ * internal name. We'll do this by substituting dollar signs
for the
+ * last slash in the name until there are no more slashes.
+ */
+ StringBuffer desc = new
StringBuffer(sourceName.replace('.', '/'));
+ while (!loader.exists(desc.toString() + ".class")) {
+ logger.spam("Did not find " + desc.toString());
+ int idx = desc.lastIndexOf("/");
+ if (idx == -1) {
+ return;
+ }
+ desc.setCharAt(idx, '$');
+ }
+
+ if ("locator".equals(name)) {
+ locatorInternalName = desc.toString();
+ } else {
+ domainInternalName = desc.toString();
+ }
+ logger.spam(domainInternalName);
}
};
}
return null;
}
+
+ @Override
+ public void visitEnd() {
+ // Only allow one annotation
+ if (found.size() > 1) {
+ StringBuilder sb = new StringBuilder();
+ for (Class<?> clazz : found) {
+ sb.append(" @").append(clazz.getSimpleName());
+ }
+ logger.poison("Redundant domain mapping annotations present:%s",
+ sb.toString());
+ }
+ }
}
/**
@@ -536,10 +564,10 @@
*/
private final Map<Type, Type> clientToDomainType = new HashMap<Type,
Type>();
/**
- * Maps client types (e.g. FooProxy) to their locator types (e.g.
FooLocator).
+ * Maps client types (e.g. FooProxy or FooContext) to their locator types
+ * (e.g. FooLocator or FooServiceLocator).
*/
private final Map<Type, Type> clientToLocatorMap = new HashMap<Type,
Type>();
-
/**
* Maps domain types (e.g Foo) to client proxy types (e.g. FooAProxy,
* FooBProxy).
@@ -731,7 +759,8 @@
}
// Check the client method against the domain
- checkClientMethodInDomain(logger, method, domainServiceType);
+ checkClientMethodInDomain(logger, method, domainServiceType,
+ !clientToLocatorMap.containsKey(requestContextType));
maybeCheckReferredProxies(logger, method);
}
@@ -887,7 +916,7 @@
* to the server's domain type.
*/
private void checkClientMethodInDomain(ErrorContext logger, RFMethod
method,
- Type domainServiceType) {
+ Type domainServiceType, boolean requireStaticMethodsForRequestType) {
logger = logger.setMethod(method);
// Create a "translated" method declaration to search for
@@ -905,7 +934,8 @@
logger.poison("The method %s is declared to return %s, but the"
+ " service method is static", method.getName(),
InstanceRequest.class.getCanonicalName());
- } else if (!isInstance && !found.isDeclaredStatic) {
+ } else if (requireStaticMethodsForRequestType && !isInstance
+ && !found.isDeclaredStatic()) {
logger.poison("The method %s is declared to return %s, but the"
+ " service method is not static", method.getName(),
Request.class.getCanonicalName());
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayer.java
Mon Nov 22 11:30:59 2010
+++ /trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayer.java
Tue Nov 30 12:13:24 2010
@@ -17,6 +17,7 @@
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.Locator;
+import com.google.gwt.requestfactory.shared.ServiceLocator;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
@@ -108,6 +109,17 @@
*/
public abstract <T extends Locator<?, ?>> T createLocator(Class<T>
clazz);
+ /**
+ * Create an instance of a service object that can be used as the target
for
+ * the given method invocation.
+ *
+ * @param contextMethod a method defined in a RequestContext
+ * @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);
+
/**
* Return the persistent id for a domain object. May return {...@code null}
to
* indicate that the domain object has not been persisted. The value
returned
@@ -208,6 +220,18 @@
public abstract List<Object> loadDomainObjects(List<Class<?>> classes,
List<Object> domainIds);
+ /**
+ * Determines if the invocation of a domain method requires a
+ * {...@link ServiceLocator} as the 0th parameter when passed into
+ * {...@link #invoke(Method, Object...)}.
+ *
+ * @param contextMethod a method defined in a RequestContext
+ * @param domainMethod a domain method
+ * @return {...@code true} if a ServiceLocator is required
+ */
+ public abstract boolean requiresServiceLocator(Method contextMethod,
+ Method domainMethod);
+
/**
* Given a type token previously returned from
* {...@link #resolveTypeToken(Class)}, return the Class literal associated
with
@@ -277,6 +301,19 @@
public abstract Method resolveRequestContextMethod(
String requestContextClass, String methodName);
+ /**
+ * 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)}
+ * 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);
+
/**
* Return a string used to represent the given type in the wire protocol.
*
=======================================
---
/trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayerCache.java
Mon Nov 22 08:01:19 2010
+++
/trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayerCache.java
Tue Nov 30 12:13:24 2010
@@ -17,6 +17,7 @@
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.Locator;
+import com.google.gwt.requestfactory.shared.ServiceLocator;
import com.google.gwt.rpc.server.Pair;
import java.lang.ref.SoftReference;
@@ -42,20 +43,27 @@
private static SoftReference<Map<Method, Map<Object, Object>>>
methodCache;
private static final Method createLocator;
+ private static final Method createServiceInstance;
private static final Method getIdType;
private static final Method getRequestReturnType;
+ private static final Method requiresServiceLocator;
private static final Method resolveClass;
private static final Method resolveClientType;
private static final Method resolveDomainClass;
private static final Method resolveDomainMethod;
private static final Method resolveLocator;
private static final Method resolveRequestContextMethod;
+ private static final Method resolveServiceLocator;
private static final Method resolveTypeToken;
static {
createLocator = getMethod("createLocator", Class.class);
+ createServiceInstance = getMethod("createServiceInstance",
Method.class,
+ Method.class);
getIdType = getMethod("getIdType", Class.class);
getRequestReturnType = getMethod("getRequestReturnType", Method.class);
+ requiresServiceLocator = getMethod("requiresServiceLocator",
Method.class,
+ Method.class);
resolveClass = getMethod("resolveClass", String.class);
resolveClientType = getMethod("resolveClientType", Class.class,
Class.class, boolean.class);
@@ -64,6 +72,8 @@
resolveLocator = getMethod("resolveLocator", Class.class);
resolveRequestContextMethod = getMethod("resolveRequestContextMethod",
String.class, String.class);
+ resolveServiceLocator = getMethod("resolveServiceLocator",
Method.class,
+ Method.class);
resolveTypeToken = getMethod("resolveTypeToken", Class.class);
}
@@ -96,6 +106,12 @@
public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) {
return getOrCache(createLocator, clazz, clazz, clazz);
}
+
+ @Override
+ public Object createServiceInstance(Method contextMethod, Method
domainMethod) {
+ return getOrCache(createServiceInstance, new Pair<Method, Method>(
+ contextMethod, domainMethod), Object.class, contextMethod,
domainMethod);
+ }
@Override
public Class<?> getIdType(Class<?> domainType) {
@@ -107,6 +123,14 @@
return getOrCache(getRequestReturnType, contextMethod, Type.class,
contextMethod);
}
+
+ @Override
+ public boolean requiresServiceLocator(Method contextMethod,
+ Method domainMethod) {
+ return getOrCache(requiresServiceLocator, new Pair<Method, Method>(
+ contextMethod, domainMethod), Boolean.class, contextMethod,
+ domainMethod);
+ }
@Override
public Class<? extends BaseProxy> resolveClass(String typeToken) {
@@ -115,12 +139,12 @@
}
@Override
- @SuppressWarnings("unchecked")
public <T> Class<? extends T> resolveClientType(Class<?> domainClass,
Class<T> clientType, boolean required) {
- return getOrCache(resolveClientType, new Pair<Class<?>, Class<?>>(
- domainClass, clientType), Class.class, domainClass, clientType,
- required);
+ Class<?> clazz = getOrCache(resolveClientType,
+ new Pair<Class<?>, Class<?>>(domainClass, clientType), Class.class,
+ domainClass, clientType, required);
+ return clazz == null ? null : clazz.asSubclass(clientType);
}
@Override
@@ -147,6 +171,15 @@
requestContextClass, methodName), Method.class,
requestContextClass,
methodName);
}
+
+ @Override
+ public Class<? extends ServiceLocator> resolveServiceLocator(
+ Method contextMethod, Method domainMethod) {
+ Class<?> clazz = getOrCache(resolveServiceLocator,
+ new Pair<Method, Method>(contextMethod, domainMethod), Class.class,
+ contextMethod, domainMethod);
+ return clazz == null ? null : clazz.asSubclass(ServiceLocator.class);
+ }
@Override
public String resolveTypeToken(Class<? extends BaseProxy> domainClass) {
=======================================
---
/trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayerDecorator.java
Mon Nov 22 11:30:59 2010
+++
/trunk/user/src/com/google/gwt/requestfactory/server/ServiceLayerDecorator.java
Tue Nov 30 12:13:24 2010
@@ -17,6 +17,7 @@
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.Locator;
+import com.google.gwt.requestfactory.shared.ServiceLocator;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -52,6 +53,11 @@
public <T extends Locator<?, ?>> T createLocator(Class<T> clazz) {
return getNext().createLocator(clazz);
}
+
+ @Override
+ public Object createServiceInstance(Method contextMethod, Method
domainMethod) {
+ return getNext().createServiceInstance(contextMethod, domainMethod);
+ }
@Override
public Object getId(Object domainObject) {
@@ -98,6 +104,12 @@
List<Object> domainIds) {
return getNext().loadDomainObjects(classes, domainIds);
}
+
+ @Override
+ public boolean requiresServiceLocator(Method contextMethod,
+ Method domainMethod) {
+ return getNext().requiresServiceLocator(contextMethod, domainMethod);
+ }
@Override
public Class<? extends BaseProxy> resolveClass(String typeToken) {
@@ -131,6 +143,12 @@
return getNext().resolveRequestContextMethod(requestContextClass,
methodName);
}
+
+ @Override
+ public Class<? extends ServiceLocator> resolveServiceLocator(
+ Method contextMethod, Method domainMethod) {
+ return getNext().resolveServiceLocator(contextMethod, domainMethod);
+ }
@Override
public String resolveTypeToken(Class<? extends BaseProxy> proxyType) {
=======================================
---
/trunk/user/src/com/google/gwt/requestfactory/server/SimpleRequestProcessor.java
Mon Nov 22 11:30:59 2010
+++
/trunk/user/src/com/google/gwt/requestfactory/server/SimpleRequestProcessor.java
Tue Nov 30 12:13:24 2010
@@ -27,6 +27,7 @@
import com.google.gwt.requestfactory.shared.BaseProxy;
import com.google.gwt.requestfactory.shared.EntityProxyId;
import com.google.gwt.requestfactory.shared.InstanceRequest;
+import com.google.gwt.requestfactory.shared.Request;
import com.google.gwt.requestfactory.shared.ServerFailure;
import com.google.gwt.requestfactory.shared.WriteOperation;
import com.google.gwt.requestfactory.shared.impl.BaseProxyCategory;
@@ -47,7 +48,6 @@
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
@@ -346,7 +346,7 @@
*/
private List<Object> decodeInvocationArguments(RequestState source,
InvocationMessage invocation, Method contextMethod, Method
domainMethod) {
- boolean isStatic = Modifier.isStatic(domainMethod.getModifiers());
+ boolean isStatic =
Request.class.isAssignableFrom(contextMethod.getReturnType());
int baseLength = contextMethod.getParameterTypes().length;
int length = baseLength + (isStatic ? 0 : 1);
int offset = isStatic ? 0 : 1;
@@ -418,9 +418,16 @@
+ invocation.getOperation(), null);
}
- // Invoke it
+ // Compute the arguments
List<Object> args = decodeInvocationArguments(state, invocation,
contextMethod, domainMethod);
+ // Possibly use a ServiceLocator
+ if (service.requiresServiceLocator(contextMethod, domainMethod)) {
+ Object serviceInstance =
service.createServiceInstance(contextMethod,
+ domainMethod);
+ args.add(0, serviceInstance);
+ }
+ // Invoke it
Object returnValue = service.invoke(domainMethod, args.toArray());
// Convert domain object to client object
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/Locator.java Mon
Nov 22 08:01:19 2010
+++ /trunk/user/src/com/google/gwt/requestfactory/shared/Locator.java Tue
Nov 30 12:13:24 2010
@@ -29,7 +29,7 @@
* @param <T> the type of domain object the Locator will operate on
* @param <I> the type of object the Locator expects to use as an id for
the
* domain object
- * @see LocatorFor
+ * @see ProxyFor#locator()
*/
public abstract class Locator<T, I> {
/**
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/ProxyFor.java Fri
Oct 22 12:06:16 2010
+++ /trunk/user/src/com/google/gwt/requestfactory/shared/ProxyFor.java Tue
Nov 30 12:13:24 2010
@@ -21,13 +21,22 @@
import java.lang.annotation.Target;
/**
- * Annotation on EntityProxy classes specifying the domain (server-side)
object
- * type.
+ * Annotation on EntityProxy and ValueProxy classes specifying the domain
+ * (server-side) object type.
*
* @see ProxyForName
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ProxyFor {
+ /**
+ * The domain type that the proxy is mapped to.
+ */
Class<?> value();
-}
+
+ /**
+ * An optional {...@link Locator} that provides instances of the domain
objects.
+ */
+ @SuppressWarnings("rawtypes")
+ Class<? extends Locator> locator() default Locator.class;
+}
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/ProxyForName.java
Fri Oct 22 12:06:16 2010
+++ /trunk/user/src/com/google/gwt/requestfactory/shared/ProxyForName.java
Tue Nov 30 12:13:24 2010
@@ -28,5 +28,14 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ProxyForName {
+ /**
+ * The name of the domain type that the proxy is mapped to.
+ */
String value();
-}
+
+ /**
+ * An optional name of a {...@link Locator} that provides instances of the
domain
+ * objects.
+ */
+ String locator() default "";
+}
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/Service.java Fri
Oct 22 12:06:16 2010
+++ /trunk/user/src/com/google/gwt/requestfactory/shared/Service.java Tue
Nov 30 12:13:24 2010
@@ -29,5 +29,16 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Service {
+ /**
+ * The domain type that provides the implementations for the methods
defined
+ * in the RequestContext.
+ */
Class<?> value();
-}
+
+ /**
+ * An optional {...@link ServiceLocator} that provides instances of service
+ * objects used when invoking instance methods on the type returned by
+ * {...@link #value()}.
+ */
+ Class<? extends ServiceLocator> locator() default ServiceLocator.class;
+}
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/ServiceName.java
Fri Oct 22 12:06:16 2010
+++ /trunk/user/src/com/google/gwt/requestfactory/shared/ServiceName.java
Tue Nov 30 12:13:24 2010
@@ -28,5 +28,16 @@
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ServiceName {
+ /**
+ * The binary name of the domain type that provides the implementations
for
+ * the methods defined in the RequestContext.
+ */
String value();
-}
+
+ /**
+ * An optional binary name of a {...@link ServiceLocator} that provides
instances
+ * of service objects used when invoking instance methods on the type
returned
+ * by {...@link #value()}.
+ */
+ String locator() default "";
+}
=======================================
---
/trunk/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
Tue Nov 30 10:50:09 2010
+++
/trunk/user/test/com/google/gwt/requestfactory/client/RequestFactoryTest.java
Tue Nov 30 12:13:24 2010
@@ -760,6 +760,17 @@
}
});
}
+
+ public void testInstanceServiceRequest() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ req.instanceServiceRequest().add(5).fire(new Receiver<Integer>() {
+ @Override
+ public void onSuccess(Integer response) {
+ assertEquals(10, (int) response);
+ finishTestAndReset();
+ }
+ });
+ }
/**
* Make sure our stock RF logging service keeps receiving.
@@ -1156,6 +1167,11 @@
}
});
}
+
+ /*
+ * TODO: all these tests should check the final values. It will be easy
when
+ * we have better persistence than the singleton pattern.
+ */
/**
* Ensure that a relationship can be set up between two newly-created
objects.
@@ -1181,11 +1197,6 @@
}
});
}
-
- /*
- * TODO: all these tests should check the final values. It will be easy
when
- * we have better persistence than the singleton pattern.
- */
/*
* Find Entity2 Create Entity, Persist Entity Relate Entity2 to Entity
Persist
@@ -1418,6 +1429,11 @@
}
});
}
+
+ /*
+ * TODO: all these tests should check the final values. It will be easy
when
+ * we have better persistence than the singleton pattern.
+ */
public void testPersistValueList() {
delayTestFinish(DELAY_TEST_FINISH);
@@ -1477,11 +1493,6 @@
}
});
}
-
- /*
- * TODO: all these tests should check the final values. It will be easy
when
- * we have better persistence than the singleton pattern.
- */
/*
* TODO: all these tests should check the final values. It will be easy
when
@@ -2069,28 +2080,6 @@
}
});
}
-
- /**
- * We provide a simple UserInformation class to give GAE developers a
hand,
- * and other developers a hint. Make sure RF doesn't break it (it relies
on
- * server side upcasting, and a somewhat sleazey reflective lookup
mechanism
- * in a static method on UserInformation).
- */
- public void testUserInfo() {
- delayTestFinish(DELAY_TEST_FINISH);
- req.userInformationRequest().getCurrentUserInformation("").fire(
- new Receiver<UserInformationProxy>() {
- @Override
- public void onSuccess(UserInformationProxy response) {
- response = checkSerialization(response);
- assertEquals("Dummy Email", response.getEmail());
- assertEquals("Dummy User", response.getName());
- assertEquals("", response.getLoginUrl());
- assertEquals("", response.getLogoutUrl());
- finishTestAndReset();
- }
- });
- }
/**
* Check if a graph of unpersisted objects can be echoed.
@@ -2231,6 +2220,28 @@
}
});
}
+
+ /**
+ * We provide a simple UserInformation class to give GAE developers a
hand,
+ * and other developers a hint. Make sure RF doesn't break it (it relies
on
+ * server side upcasting, and a somewhat sleazey reflective lookup
mechanism
+ * in a static method on UserInformation).
+ */
+ public void testUserInfo() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ req.userInformationRequest().getCurrentUserInformation("").fire(
+ new Receiver<UserInformationProxy>() {
+ @Override
+ public void onSuccess(UserInformationProxy response) {
+ response = checkSerialization(response);
+ assertEquals("Dummy Email", response.getEmail());
+ assertEquals("Dummy User", response.getName());
+ assertEquals("", response.getLoginUrl());
+ assertEquals("", response.getLogoutUrl());
+ finishTestAndReset();
+ }
+ });
+ }
public void testValueObjectCreateSetRetrieveUpdate() {
delayTestFinish(DELAY_TEST_FINISH);
@@ -2372,6 +2383,48 @@
b.getSimpleValue().get(0).setNumber(55);
checkEqualityAndHashcode(a, b);
}
+
+ /**
+ * Since a ValueProxy cannot be passed into RequestContext edit, a proxy
+ * returned from a service method should be mutable by default.
+ */
+ public void testValueObjectReturnedFromRequestIsImmutable() {
+ delayTestFinish(DELAY_TEST_FINISH);
+ simpleFooRequest().returnValueProxy().fire(
+ new Receiver<SimpleValueProxy>() {
+ @Override
+ public void onSuccess(SimpleValueProxy a) {
+ a = checkSerialization(a);
+ try {
+ a.setNumber(77);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ try {
+ // Ensure Dates comply with ValueProxy mutation behaviors
+ a.getDate().setTime(1);
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ SimpleFooRequest ctx = simpleFooRequest();
+ final SimpleValueProxy toCheck = ctx.edit(a);
+ toCheck.setNumber(77);
+ toCheck.getDate().setTime(1);
+ ctx.returnValueProxy().fire(new Receiver<SimpleValueProxy>() {
+ @Override
+ public void onSuccess(SimpleValueProxy b) {
+ b = checkSerialization(b);
+ b = simpleFooRequest().edit(b);
+ // Now check that same value is equal across contexts
+ b.setNumber(77);
+ b.setDate(new Date(1));
+ checkEqualityAndHashcode(toCheck, b);
+ finishTestAndReset();
+ }
+ });
+ }
+ });
+ }
public void testValueObjectViolationsOnCreate() {
delayTestFinish(DELAY_TEST_FINISH);
@@ -2432,48 +2485,6 @@
}
});
}
-
- /**
- * Since a ValueProxy cannot be passed into RequestContext edit, a proxy
- * returned from a service method should be mutable by default.
- */
- public void testValueObjectReturnedFromRequestIsImmutable() {
- delayTestFinish(DELAY_TEST_FINISH);
- simpleFooRequest().returnValueProxy().fire(
- new Receiver<SimpleValueProxy>() {
- @Override
- public void onSuccess(SimpleValueProxy a) {
- a = checkSerialization(a);
- try {
- a.setNumber(77);
- fail();
- } catch (IllegalStateException expected) {
- }
- try {
- // Ensure Dates comply with ValueProxy mutation behaviors
- a.getDate().setTime(1);
- fail();
- } catch (IllegalStateException expected) {
- }
- SimpleFooRequest ctx = simpleFooRequest();
- final SimpleValueProxy toCheck = ctx.edit(a);
- toCheck.setNumber(77);
- toCheck.getDate().setTime(1);
- ctx.returnValueProxy().fire(new Receiver<SimpleValueProxy>() {
- @Override
- public void onSuccess(SimpleValueProxy b) {
- b = checkSerialization(b);
- b = simpleFooRequest().edit(b);
- // Now check that same value is equal across contexts
- b.setNumber(77);
- b.setDate(new Date(1));
- checkEqualityAndHashcode(toCheck, b);
- finishTestAndReset();
- }
- });
- }
- });
- }
public void testViolationAbsent() {
delayTestFinish(DELAY_TEST_FINISH);
=======================================
---
/trunk/user/test/com/google/gwt/requestfactory/rebind/model/RequestFactoryModelTest.java
Thu Nov 18 13:15:58 2010
+++
/trunk/user/test/com/google/gwt/requestfactory/rebind/model/RequestFactoryModelTest.java
Tue Nov 30 12:13:24 2010
@@ -28,12 +28,14 @@
import com.google.gwt.requestfactory.server.TestContextImpl;
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.InstanceRequest;
+import com.google.gwt.requestfactory.shared.Locator;
import com.google.gwt.requestfactory.shared.ProxyFor;
import com.google.gwt.requestfactory.shared.Receiver;
import com.google.gwt.requestfactory.shared.Request;
import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.RequestFactory;
import com.google.gwt.requestfactory.shared.Service;
+import com.google.gwt.requestfactory.shared.ServiceLocator;
import com.google.gwt.requestfactory.shared.ValueProxy;
import junit.framework.TestCase;
@@ -269,8 +271,10 @@
new EmptyMockJavaResource(Iterable.class),
new EmptyMockJavaResource(EntityProxy.class),
new EmptyMockJavaResource(InstanceRequest.class),
+ new EmptyMockJavaResource(Locator.class),
new EmptyMockJavaResource(RequestFactory.class),
new EmptyMockJavaResource(Receiver.class),
+ new EmptyMockJavaResource(ServiceLocator.class),
new EmptyMockJavaResource(ValueProxy.class),
new RealJavaResource(Request.class),
=======================================
---
/trunk/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
Mon Nov 22 08:01:19 2010
+++
/trunk/user/test/com/google/gwt/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
Tue Nov 30 12:13:24 2010
@@ -19,12 +19,13 @@
import com.google.gwt.requestfactory.shared.EntityProxy;
import com.google.gwt.requestfactory.shared.InstanceRequest;
import com.google.gwt.requestfactory.shared.Locator;
-import com.google.gwt.requestfactory.shared.LocatorFor;
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.RequestFactory;
import com.google.gwt.requestfactory.shared.Service;
+import com.google.gwt.requestfactory.shared.ServiceName;
import com.google.gwt.requestfactory.shared.SimpleRequestFactory;
import com.google.gwt.requestfactory.shared.ValueProxy;
import com.google.gwt.requestfactory.shared.impl.FindRequest;
@@ -180,8 +181,7 @@
}
}
- @ProxyFor(LocatorEntity.class)
- @LocatorFor(LocatorEntityLocator.class)
+ @ProxyFor(value = LocatorEntity.class, locator =
LocatorEntityLocator.class)
interface LocatorEntityProxy extends EntityProxy {
}
@@ -227,6 +227,13 @@
interface ServiceRequestMissingMethod extends RequestContext {
Request<Integer> doesNotExist(int a);
}
+
+ @ProxyFor(Domain.class)
+ @ProxyForName("Domain")
+ @Service(Domain.class)
+ @ServiceName("Domain")
+ interface TooManyAnnotations extends RequestContext {
+ }
static class UnexpectedIdAndVersionDomain {
Random getId() {
@@ -348,6 +355,11 @@
v.validateRequestFactory(SimpleRequestFactory.class.getName());
assertFalse(v.isPoisoned());
}
+
+ public void testTooManyAnnotations() {
+ v.validateRequestContext(TooManyAnnotations.class.getName());
+ assertTrue(v.isPoisoned());
+ }
public void testUnexpectedIdAndVersion() {
v.validateEntityProxy(UnexpectedIdAndVersionProxy.class.getName());
=======================================
--- /trunk/user/test/com/google/gwt/requestfactory/shared/LocatorTest.java
Mon Nov 22 08:01:19 2010
+++ /trunk/user/test/com/google/gwt/requestfactory/shared/LocatorTest.java
Tue Nov 30 12:13:24 2010
@@ -82,8 +82,7 @@
static final Domain INSTANCE = new Domain();
}
- @ProxyFor(Domain.class)
- @LocatorFor(DomainLocator.class)
+ @ProxyFor(value = Domain.class, locator = DomainLocator.class)
interface DomainProxy extends EntityProxy {
EntityProxyId<DomainProxy> stableId();
};
=======================================
---
/trunk/user/test/com/google/gwt/requestfactory/shared/SimpleRequestFactory.java
Tue Nov 30 09:13:06 2010
+++
/trunk/user/test/com/google/gwt/requestfactory/shared/SimpleRequestFactory.java
Tue Nov 30 12:13:24 2010
@@ -20,6 +20,8 @@
* UserInformation and Logging services.
*/
public interface SimpleRequestFactory extends BasicRequestFactory {
+
+ InstanceServiceRequest instanceServiceRequest();
SimpleBarRequest simpleBarRequest();
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors