You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2014/01/02 17:15:25 UTC

[3/3] git commit: TAP5-2029: Copy annotations from service implementation to proxy

TAP5-2029: Copy annotations from service implementation to proxy


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/28df9e51
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/28df9e51
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/28df9e51

Branch: refs/heads/master
Commit: 28df9e51cbdef90f5768595cfd2992f877c244cf
Parents: 4a818e3
Author: Thiago H. de Paula Figueiredo <th...@apache.org>
Authored: Thu Jan 2 14:14:49 2014 -0200
Committer: Thiago H. de Paula Figueiredo <th...@apache.org>
Committed: Thu Jan 2 14:14:49 2014 -0200

----------------------------------------------------------------------
 .../MethodInvocationGetAnnotationSpec.groovy    | 85 ++++++++++++++++++++
 .../tapestry5/ioc/internal/AdviceModule.java    | 41 ++++++++++
 .../ioc/internal/AnnotatedServiceInterface.java | 30 +++++++
 .../internal/AnnotatedServiceInterfaceImpl.java | 23 ++++++
 .../tapestry5/ioc/internal/DecoratorModule.java | 53 ++++++++++++
 .../internal/NonAnnotatedServiceInterface.java  | 24 ++++++
 .../NonAnnotatedServiceInterfaceImpl.java       | 28 +++++++
 .../tapestry5/ioc/internal/TestAdvice.java      | 55 +++++++++++++
 8 files changed, 339 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/28df9e51/tapestry-ioc/src/test/groovy/ioc/specs/MethodInvocationGetAnnotationSpec.groovy
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/MethodInvocationGetAnnotationSpec.groovy b/tapestry-ioc/src/test/groovy/ioc/specs/MethodInvocationGetAnnotationSpec.groovy
new file mode 100644
index 0000000..b4e4c0e
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/MethodInvocationGetAnnotationSpec.groovy
@@ -0,0 +1,85 @@
+package ioc.specs
+
+import org.apache.tapestry5.beaneditor.ReorderProperties
+import org.apache.tapestry5.ioc.annotations.Advise
+import org.apache.tapestry5.ioc.internal.AdviceModule
+import org.apache.tapestry5.ioc.internal.AnnotatedServiceInterface
+import org.apache.tapestry5.ioc.internal.DecoratorModule
+import org.apache.tapestry5.ioc.internal.NonAnnotatedServiceInterface
+import org.apache.tapestry5.ioc.internal.TestAdvice
+
+/**
+ * Tests whether MethodAdvice.getAnnotation() is actually returning annotations from
+ * the service implementation methods and not from the service interface ones.
+ * The tests also verify whether the proxy annotations have the service implementation annotations
+ * and whether the service implementation annotations were copied the generated proxy class. 
+ * @see TestAdvice
+ */
+class MethodInvocationGetAnnotationSpec extends AbstractRegistrySpecification {
+
+  def "MethodAdvice.getAnnotation() and getMethod() in service decoration"() {
+    when:
+
+    buildRegistry DecoratorModule
+    
+	def nonAnnotatedService = registry.getService NonAnnotatedServiceInterface.class
+	def nonAnnotatedResult = nonAnnotatedService.execute(0);
+    def nonAnnotatedMethod = nonAnnotatedService.getClass().getMethod("execute", int.class);
+
+    def annotatedService = registry.getService AnnotatedServiceInterface.class
+    def annotatedResult = annotatedService.execute(0);
+    def annotatedMethod = annotatedService.getClass().getMethod("execute", int.class);
+
+    then:
+    nonAnnotatedMethod != null
+    nonAnnotatedMethod.getAnnotation(Advise.class) != null
+    nonAnnotatedMethod.getAnnotation(Advise.class).id().equals("id")
+    nonAnnotatedMethod.getAnnotation(Advise.class).serviceInterface() == NonAnnotatedServiceInterface.class
+    nonAnnotatedService.getClass().getAnnotation(ReorderProperties.class) != null
+    nonAnnotatedService.getClass().getAnnotation(ReorderProperties.class).value().equals("reorder") 
+	nonAnnotatedResult == TestAdvice.ANNOTATION_FOUND
+    
+    annotatedMethod != null
+    annotatedMethod.getAnnotation(Advise.class) != null
+    annotatedMethod.getAnnotation(Advise.class).id().equals("id")
+    annotatedMethod.getAnnotation(Advise.class).serviceInterface() == NonAnnotatedServiceInterface.class
+    annotatedService.getClass().getAnnotation(ReorderProperties.class) != null
+    annotatedService.getClass().getAnnotation(ReorderProperties.class).value().equals("reorder")
+    annotatedResult == TestAdvice.ANNOTATION_FOUND
+
+  }
+  
+  def "MethodAdvice.getAnnotation() and getMethod() in service advice"() {
+      
+    when:
+  
+    buildRegistry AdviceModule
+    
+    def nonAnnotatedService = registry.getService NonAnnotatedServiceInterface.class
+    def nonAnnotatedResult = nonAnnotatedService.execute(0);
+    def nonAnnotatedMethod = nonAnnotatedService.getClass().getMethod("execute", int.class);
+
+    def annotatedService = registry.getService AnnotatedServiceInterface
+    def annotatedResult = annotatedService.execute(0);
+    def annotatedMethod = annotatedService.getClass().getMethod("execute", int.class);
+    
+    then:
+    nonAnnotatedMethod != null
+    nonAnnotatedMethod.getAnnotation(Advise.class) != null
+    nonAnnotatedMethod.getAnnotation(Advise.class).id().equals("id")
+    nonAnnotatedMethod.getAnnotation(Advise.class).serviceInterface() == NonAnnotatedServiceInterface.class
+    nonAnnotatedService.getClass().getAnnotation(ReorderProperties.class) != null
+    nonAnnotatedService.getClass().getAnnotation(ReorderProperties.class).value().equals("reorder")
+    nonAnnotatedResult == TestAdvice.ANNOTATION_FOUND
+    
+    annotatedMethod != null
+    annotatedMethod.getAnnotation(Advise.class) != null
+    annotatedMethod.getAnnotation(Advise.class).id().equals("id")
+    annotatedMethod.getAnnotation(Advise.class).serviceInterface() == NonAnnotatedServiceInterface.class
+    annotatedService.getClass().getAnnotation(ReorderProperties.class) != null
+    annotatedService.getClass().getAnnotation(ReorderProperties.class).value().equals("reorder")
+    annotatedResult == TestAdvice.ANNOTATION_FOUND
+
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/28df9e51/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
new file mode 100644
index 0000000..466b528
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AdviceModule.java
@@ -0,0 +1,41 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.ioc.internal;
+
+import org.apache.tapestry5.ioc.MethodAdviceReceiver;
+import org.apache.tapestry5.ioc.ServiceBinder;
+import org.apache.tapestry5.ioc.annotations.Advise;
+
+public class AdviceModule
+{
+
+    public static void bind(ServiceBinder binder)
+    {
+        binder.bind(NonAnnotatedServiceInterface.class, NonAnnotatedServiceInterfaceImpl.class);
+        binder.bind(AnnotatedServiceInterface.class, AnnotatedServiceInterfaceImpl.class);
+    }
+
+    @Advise(serviceInterface = NonAnnotatedServiceInterface.class)
+    public static void adviseNonAnnotatedServiceInterface(MethodAdviceReceiver methodAdviceReceiver)
+    {
+        methodAdviceReceiver.adviseAllMethods(new TestAdvice());
+    }
+
+    @Advise(serviceInterface = AnnotatedServiceInterface.class)
+    public static void adviseAnnotatedServiceInterface(MethodAdviceReceiver methodAdviceReceiver)
+    {
+        methodAdviceReceiver.adviseAllMethods(new TestAdvice());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/28df9e51/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AnnotatedServiceInterface.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AnnotatedServiceInterface.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AnnotatedServiceInterface.java
new file mode 100644
index 0000000..e2575fe
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AnnotatedServiceInterface.java
@@ -0,0 +1,30 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.ioc.internal;
+
+import org.apache.tapestry5.beaneditor.ReorderProperties;
+import org.apache.tapestry5.ioc.annotations.Advise;
+import org.apache.tapestry5.ioc.annotations.IntermediateType;
+
+/**
+ * Service definition with annotations so we can test copying the service interface
+ * annotations, both in class and methods, to the service proxy.
+ */
+@ReorderProperties("reorder") // no meaning, just for testing whether the proxy will have it
+public interface AnnotatedServiceInterface {
+
+    @Advise(id = "id", serviceInterface = NonAnnotatedServiceInterface.class)
+	public String execute(@IntermediateType(String.class) int i); 
+	
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/28df9e51/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AnnotatedServiceInterfaceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AnnotatedServiceInterfaceImpl.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AnnotatedServiceInterfaceImpl.java
new file mode 100644
index 0000000..36db723
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/AnnotatedServiceInterfaceImpl.java
@@ -0,0 +1,23 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.ioc.internal;
+
+
+public class AnnotatedServiceInterfaceImpl implements AnnotatedServiceInterface {
+
+	public String execute(int i) {
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/28df9e51/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DecoratorModule.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DecoratorModule.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DecoratorModule.java
new file mode 100644
index 0000000..ebe972a
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/DecoratorModule.java
@@ -0,0 +1,53 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.ioc.internal;
+
+import org.apache.tapestry5.ioc.ServiceBinder;
+import org.apache.tapestry5.ioc.annotations.Decorate;
+import org.apache.tapestry5.ioc.services.AspectDecorator;
+import org.apache.tapestry5.ioc.services.AspectInterceptorBuilder;
+
+/**
+ * @author Thiago H. de Paula Figueiredo (http://machina.com.br/thiago)
+ */
+public class DecoratorModule
+{
+
+    public static void bind(ServiceBinder binder)
+    {
+        binder.bind(NonAnnotatedServiceInterface.class, NonAnnotatedServiceInterfaceImpl.class);
+        binder.bind(AnnotatedServiceInterface.class, AnnotatedServiceInterfaceImpl.class);
+    }
+
+    @Decorate(serviceInterface = AnnotatedServiceInterface.class)
+    public static AnnotatedServiceInterface decorateAnnotated(AnnotatedServiceInterface delegate,
+            AspectDecorator aspectDecorator)
+    {
+        final AspectInterceptorBuilder<AnnotatedServiceInterface> builder = aspectDecorator
+                .createBuilder(AnnotatedServiceInterface.class, delegate, "!");
+        builder.adviseAllMethods(new TestAdvice());
+        return builder.build();
+    }
+
+    @Decorate(serviceInterface = NonAnnotatedServiceInterface.class)
+    public static NonAnnotatedServiceInterface decorateNonAnnotated(
+            NonAnnotatedServiceInterface delegate, AspectDecorator aspectDecorator)
+    {
+        final AspectInterceptorBuilder<NonAnnotatedServiceInterface> builder = aspectDecorator
+                .createBuilder(NonAnnotatedServiceInterface.class, delegate, "!");
+        builder.adviseAllMethods(new TestAdvice());
+        return builder.build();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/28df9e51/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NonAnnotatedServiceInterface.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NonAnnotatedServiceInterface.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NonAnnotatedServiceInterface.java
new file mode 100644
index 0000000..4270d1e
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NonAnnotatedServiceInterface.java
@@ -0,0 +1,24 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.ioc.internal;
+
+/**
+ * Service definition without any annotations so we can test copying the service implementation
+ * annotations, both in class and methods, to the service proxy.
+ */
+public interface NonAnnotatedServiceInterface {
+
+	public String execute(int i);
+	
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/28df9e51/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NonAnnotatedServiceInterfaceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NonAnnotatedServiceInterfaceImpl.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NonAnnotatedServiceInterfaceImpl.java
new file mode 100644
index 0000000..efa408d
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/NonAnnotatedServiceInterfaceImpl.java
@@ -0,0 +1,28 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.ioc.internal;
+
+import org.apache.tapestry5.beaneditor.ReorderProperties;
+import org.apache.tapestry5.ioc.annotations.Advise;
+import org.apache.tapestry5.ioc.annotations.IntermediateType;
+
+@ReorderProperties("reorder") // no meaning, just for testing whether the proxy will have it
+public class NonAnnotatedServiceInterfaceImpl implements NonAnnotatedServiceInterface {
+
+	@Advise(id = "id", serviceInterface = NonAnnotatedServiceInterface.class)
+	public String execute(@IntermediateType(String.class) int i) { // annotation just for checking too
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/28df9e51/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/TestAdvice.java
----------------------------------------------------------------------
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/TestAdvice.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/TestAdvice.java
new file mode 100644
index 0000000..f7ca811
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/TestAdvice.java
@@ -0,0 +1,55 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.ioc.internal;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import org.apache.tapestry5.ioc.annotations.Advise;
+import org.apache.tapestry5.ioc.annotations.IntermediateType;
+import org.apache.tapestry5.plastic.MethodAdvice;
+import org.apache.tapestry5.plastic.MethodInvocation;
+
+final public class TestAdvice implements MethodAdvice {
+
+	public static final String ANNOTATION_FOUND = "Annotation found!";
+
+	public void advise(MethodInvocation invocation) {
+
+		final Method method = invocation.getMethod();
+        boolean annotationFoundInMethod = checkAnnotation(method.getAnnotation(Advise.class));
+		boolean annotationFoundThroughAnnotationProvider = checkAnnotation(invocation.getAnnotation(Advise.class));
+		IntermediateType parameterAnnotation = null;
+		final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
+		if (parameterAnnotations.length > 0 && parameterAnnotations[0].length > 0) {
+		    parameterAnnotation = (IntermediateType) parameterAnnotations[0][0];
+		}
+        boolean annotationParameter = parameterAnnotation != null && parameterAnnotation.value() == String.class;
+		
+		if (annotationFoundInMethod && annotationFoundThroughAnnotationProvider && annotationParameter) 
+		{
+			invocation.setReturnValue(ANNOTATION_FOUND);
+		}
+		else {
+			invocation.proceed();
+		}
+		
+	}
+
+    private boolean checkAnnotation(Advise annotation)
+    {
+        return annotation != null && "id".equals(annotation.id()) && NonAnnotatedServiceInterface.class.equals(annotation.serviceInterface());
+    }
+	
+}
\ No newline at end of file