jnan77 / jsonrpc4j

Automatically exported from code.google.com/p/jsonrpc4j
0 stars 0 forks source link

Add support for jaxws annotations #37

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
jsonrpc4j introduces it's own JsonRpcParam annotation, but this annotation 
exactly duplicates the WebParam annotation already included in the JDK (Java 
6+).  Even if JsonRpcParam support is retained, the freedom to use WebParam 
would be nice.  We have a web service that is exposed over SOAP and via 
jsonrpc4j, so it would be nice if we didn't have to decorate every parameter 
with two annotations (esp. because they serve the same purpose).

Original issue reported on code.google.com by brett.wo...@gmail.com on 26 Sep 2012 at 12:29

GoogleCodeExporter commented 8 years ago
Here is a patch to add support for the WebParam annotation.  This patch also 
slightly alters the code for handling legacy JsonRpcParamName annotations by 
using an anonymous JsonRpcParam class rather than a Proxy instance.  I feel it 
is cleaner while providing higher performance (less overhead).

NOTE: the line offsets in this patch are based on the changes in the patch 
included in Issue#38.

Index: src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java
===================================================================
--- src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java   (revision 238634)
+++ src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java   (working copy)
@@ -4,7 +4,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.lang.reflect.InvocationHandler;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
@@ -20,6 +20,7 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;

+import javax.jws.WebParam;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.servlet.http.HttpServletRequest;
@@ -681,17 +687,35 @@
                for (List<JsonRpcParamName> annots : depMethodAnnotations) {
                    if (annots.size()>0) {
                        final JsonRpcParamName annotation = annots.get(0);
-                       annotations.add((JsonRpcParam)Proxy.newProxyInstance(
-                           getClass().getClassLoader(), new Class[] {JsonRpcParam.class},
-                               new InvocationHandler() {
-                                   public Object invoke(Object proxy, Method method, Object[] args)
-                                       throws Throwable {
-                                       if (method.getName().equals("value")) {
-                                           return annotation.value();
-                                       }
-                                       throw new Exception("Unknown method: "+method.getName());
-                                   }
-                           }));
+                       annotations.add(new JsonRpcParam() {
+                           public Class<? extends Annotation> annotationType() {
+                               return JsonRpcParam.class;
+                           }
+                           public String value() {
+                               return annotation.value();
+                           }
+                       });
+                   } else {
+                       annots.add(null);
+                   }
+               }
+           }
+
+           List<List<WebParam>> jaxwsAnnotations = ReflectionUtil
+                   .getParameterAnnotations(method, WebParam.class);
+           if (!jaxwsAnnotations.isEmpty())
+           {
+               for (List<WebParam> annots : jaxwsAnnotations) {
+                   if (annots.size()>0) {
+                       final WebParam annotation = annots.get(0);
+                       annotations.add(new JsonRpcParam() {
+                           public Class<? extends Annotation> annotationType() {
+                               return JsonRpcParam.class;
+                           }
+                           public String value() {
+                               return annotation.name();
+                           }
+                       });
                    } else {
                        annots.add(null);
                    }

Original comment by brett.wo...@gmail.com on 26 Sep 2012 at 3:39

GoogleCodeExporter commented 8 years ago
thanks, i plan on resolving this any many other issues in the next day or two.

Original comment by brian.di...@gmail.com on 3 Oct 2012 at 11:22

GoogleCodeExporter commented 8 years ago
I'm not sure that I'm ready to break support for jdk 1.5 just yet.  Can you 
think of any compelling reasons that we should?  Also, if you could implement 
this in a way that wouldn't cause problems in jdk1.5 then there wouldn't be any 
issues.

Original comment by brian.di...@gmail.com on 5 Oct 2012 at 11:53

GoogleCodeExporter commented 8 years ago

Original comment by brian.di...@gmail.com on 6 Oct 2012 at 12:11

GoogleCodeExporter commented 8 years ago
Here's a new patch that uses reflection rather than a hard dependency on 
javax.jws.WebParam.  It should compile and run under jdk 1.5.

I noticed you use Eclipse, you can just highlight this patch and copy it to the 
clipboard.  Then select your top-level project and paste (Ctrl-V or whatever), 
Eclipse will prompt you to apply the patch.  If you have Quick Diff enabled 
under Preferences->General->Editors->Text Editors, and check the 'Show 
differences in overview ruler' box and change the drop-down for the reference 
source to 'SVN Working Copy Base', you'll get little highlight markers in the 
editor showing each changed line.  Hovering over the marker shows the original 
line of code.  Very handy for reviewing patches like this.

NOTE: the line offsets in this patch are based on the changes in the patch 
included in  Issue#38 .

Index: src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java
===================================================================
--- src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java   (revision 238659)
+++ src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java   (working copy)
@@ -1,10 +1,14 @@
 package com.googlecode.jsonrpc4j;

+import static com.googlecode.jsonrpc4j.ReflectionUtil.findMethods;
+import static com.googlecode.jsonrpc4j.ReflectionUtil.getParameterAnnotations;
+import static com.googlecode.jsonrpc4j.ReflectionUtil.getParameterTypes;
+
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.lang.reflect.InvocationHandler;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
@@ -48,6 +52,9 @@
    public static final ErrorResolver DEFAULT_ERRROR_RESOLVER
        = new MultipleErrorResolver(AnnotationsErrorResolver.INSTANCE, DefaultErrorResolver.INSTANCE);

+   private static Class<?> WEBPARAM_ANNOTATION_CLASS;
+   private static Method WEBPARAM_NAME_METHOD;
+
    private boolean backwardsComaptible     = true;
    private boolean rethrowExceptions       = false;
    private boolean allowExtraParams        = false;
@@ -57,6 +64,16 @@
    private Object handler;
    private Class<?> remoteInterface;

+   static {
+       ClassLoader classLoader = JsonRpcServer.class.getClassLoader();
+       try {
+           WEBPARAM_ANNOTATION_CLASS = classLoader.loadClass("javax.jws.WebParam");
+           WEBPARAM_NAME_METHOD  = WEBPARAM_ANNOTATION_CLASS.getMethod("name");
+       } catch (Exception e) {
+           // Must be Java 1.5
+       }
+   }
+
    /**
     * Creates the server with the given {@link ObjectMapper} delegating
     * all calls to the given {@code handler} {@link Object} but only
@@ -331,7 +348,7 @@

        // find methods
        Set<Method> methods = new HashSet<Method>();
-       methods.addAll(ReflectionUtil.findMethods(getHandlerInterfaces(), 
methodName));
+       methods.addAll(findMethods(getHandlerInterfaces(), methodName));
        if (methods.isEmpty()) {
            writeAndFlushValue(ops, createErrorResponse(
                jsonRpc, id, -32601, "Method not found", null));
@@ -613,7 +630,7 @@
            // matching parameter types
            int mostMatches = -1;
            for (Method method : matchedMethods) {
-               List<Class<?>> parameterTypes = ReflectionUtil.getParameterTypes(method);
+               List<Class<?>> parameterTypes = getParameterTypes(method);
                int numMatches = 0;
                for (int i=0; i<parameterTypes.size() && i<numParams; i++) {
                    if (isMatchingType(paramNodes.get(i), parameterTypes.get(i))) {
@@ -668,7 +685,7 @@
        for (Method method : methods) {

            // get parameter types
-           List<Class<?>> parameterTypes = ReflectionUtil.getParameterTypes(method);
+           List<Class<?>> parameterTypes = getParameterTypes(method);

            // bail early if possible
            if (!allowExtraParams && paramNames.size()>parameterTypes.size()) {
@@ -681,39 +698,54 @@
            List<JsonRpcParam> annotations = new ArrayList<JsonRpcParam>();

            // try the deprecated parameter first
-           List<List<JsonRpcParamName>> depMethodAnnotations = ReflectionUtil
-               .getParameterAnnotations(method, JsonRpcParamName.class);
-           if (!depMethodAnnotations.isEmpty()) {
-               for (List<JsonRpcParamName> annots : depMethodAnnotations) {
-                   if (annots.size()>0) {
-                       final JsonRpcParamName annotation = annots.get(0);
-                       annotations.add((JsonRpcParam)Proxy.newProxyInstance(
-                           getClass().getClassLoader(), new Class[] {JsonRpcParam.class},
-                               new InvocationHandler() {
-                                   public Object invoke(Object proxy, Method method, Object[] args)
-                                       throws Throwable {
-                                       if (method.getName().equals("value")) {
-                                           return annotation.value();
-                                       }
-                                       throw new Exception("Unknown method: "+method.getName());
-                                   }
-                           }));
-                   } else {
-                       annots.add(null);
-                   }
+           List<List<JsonRpcParamName>> depMethodAnnotations = 
getParameterAnnotations(method, JsonRpcParamName.class);
+           for (List<JsonRpcParamName> annots : depMethodAnnotations) {
+               if (annots.size()>0) {
+                   final JsonRpcParamName annotation = annots.get(0);
+                   annotations.add(new JsonRpcParam() {
+                       public Class<? extends Annotation> annotationType() {
+                           return JsonRpcParam.class;
+                       }
+                       public String value() {
+                           return annotation.value();
+                       }
+                   });
+               } else {
+                   annots.add(null);
+               }
+           }
+
+           @SuppressWarnings("unchecked")
+           List<List<Annotation>> jaxwsAnnotations = WEBPARAM_ANNOTATION_CLASS != null
+               ? getParameterAnnotations(method, (Class<Annotation>) 
WEBPARAM_ANNOTATION_CLASS)
+               : new ArrayList<List<Annotation>>();
+           for (List<Annotation> annots : jaxwsAnnotations) {
+               if (annots.size()>0) {
+                   final Annotation annotation = annots.get(0);
+                   annotations.add(new JsonRpcParam() {
+                       public Class<? extends Annotation> annotationType() {
+                           return JsonRpcParam.class;
+                       }
+                       public String value() {
+                           try {
+                               return (String) WEBPARAM_NAME_METHOD.invoke(annotation);
+                           } catch (Exception e) {
+                               throw new RuntimeException(e);
+                           }
+                       }
+                   });
+               } else {
+                   annots.add(null);
                }
            }

            // now try the non-deprecated parameters
-           List<List<JsonRpcParam>> methodAnnotations = ReflectionUtil
-               .getParameterAnnotations(method, JsonRpcParam.class);
-           if (!methodAnnotations.isEmpty()) {
-               for (List<JsonRpcParam> annots : methodAnnotations) {
-                   if (annots.size()>0) {
-                       annotations.add(annots.get(0));
-                   } else {
-                       annots.add(null);
-                   }
+           List<List<JsonRpcParam>> methodAnnotations = 
getParameterAnnotations(method, JsonRpcParam.class);
+           for (List<JsonRpcParam> annots : methodAnnotations) {
+               if (annots.size()>0) {
+                   annotations.add(annots.get(0));
+               } else {
+                   annots.add(null);
                }
            }

Original comment by brett.wo...@gmail.com on 23 Oct 2012 at 3:24

GoogleCodeExporter commented 8 years ago
Thanks, will be included in next release.

Original comment by brian.di...@gmail.com on 28 Nov 2012 at 8:02