From 6150c58b191f8b416b20d491ea6deec5483e7467 Mon Sep 17 00:00:00 2001 From: Andreeva Kseniya Date: Tue, 5 Jun 2018 19:37:36 +0500 Subject: [PATCH 01/14] Fixed bug ignoring the date value of @JsonRpcError Error: If you use @JsonRpcError, the value of the field "date" is ignored. Cause: In the resolveError function, the value of the field date is not checked, the default value is immediately used. --- .../googlecode/jsonrpc4j/AnnotationsErrorResolver.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/googlecode/jsonrpc4j/AnnotationsErrorResolver.java b/src/main/java/com/googlecode/jsonrpc4j/AnnotationsErrorResolver.java index 918c14a4..c30f7bd4 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/AnnotationsErrorResolver.java +++ b/src/main/java/com/googlecode/jsonrpc4j/AnnotationsErrorResolver.java @@ -22,7 +22,8 @@ public JsonError resolveError(Throwable thrownException, Method method, List 0; } + + private boolean hasErrorData(JsonRpcError em) { + // noinspection ConstantConditions + return em.data() != null && em.data().trim().length() > 0; + } private boolean hasAnnotations(JsonRpcErrors errors) { return errors != null; From 9f1052744b3524a5dafca5e372058211ba21557d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Fri, 8 Jun 2018 19:24:56 +0200 Subject: [PATCH 02/14] Fix sending JsonMappingException and JsonParseException as response for reading errors in method arguments. Now a PARSE_ERROR response error is send instead as in case of call body malformation. --- src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java index a6e360c5..39cb4aff 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java @@ -370,7 +370,10 @@ private JsonError handleObject(final ObjectNode node, final OutputStream output) writeAndFlushValue(output, response); } return JsonError.OK; + } catch (JsonParseException | JsonMappingException e) { + throw e; // rethrow this, it will be handled as PARSE_ERROR later } catch (Throwable e) { + System.out.println("Co to je?????????????,"); handler.error = e; return handleError(output, id, jsonRpc, methodArgs, e); } From 58dd833562450c7abe174bdc7f0502257c889a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Fri, 8 Jun 2018 19:31:00 +0200 Subject: [PATCH 03/14] Remove debug print. --- src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java index 39cb4aff..78f503fd 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcBasicServer.java @@ -373,7 +373,6 @@ private JsonError handleObject(final ObjectNode node, final OutputStream output) } catch (JsonParseException | JsonMappingException e) { throw e; // rethrow this, it will be handled as PARSE_ERROR later } catch (Throwable e) { - System.out.println("Co to je?????????????,"); handler.error = e; return handleError(output, id, jsonRpc, methodArgs, e); } From 1b3a4bc72456fba12c881bedede6e5e5d2a625d5 Mon Sep 17 00:00:00 2001 From: Calvin Ken <2993614148@qq.com> Date: Sun, 24 Jun 2018 23:40:52 +0800 Subject: [PATCH 04/14] Modify JsonRpcServer constructor access to public The JsonRpcServer constructor (private JsonRpcServer(Object handler, Class remoteInterface)) should be public. For example: new JsonRpcServer(new HelloWorldServiceImpl(), HelloWorldService.class); --- src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java index 4fb92342..7439dd44 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java @@ -77,7 +77,7 @@ public JsonRpcServer(ObjectMapper mapper, Object handler) { * @param handler the {@code handler} * @param remoteInterface the interface */ - private JsonRpcServer(Object handler, Class remoteInterface) { + public JsonRpcServer(Object handler, Class remoteInterface) { super(new ObjectMapper(), handler, remoteInterface); this.gzipResponses = false; } From 57a79485a5d34a5d3544d7dcb77951e362a4d458 Mon Sep 17 00:00:00 2001 From: Oleg Oleynik Date: Thu, 19 Jul 2018 17:54:23 +0400 Subject: [PATCH 05/14] @klya version of #1 PR --- .../jsonrpc4j/JsonRpcHttpClient.java | 42 +++++++++---------- .../jsonrpc4j/integration/HttpClientTest.java | 24 ++++++++++- .../jsonrpc4j/util/BaseRestTest.java | 5 +++ 3 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcHttpClient.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcHttpClient.java index 722b9c3f..f804e855 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcHttpClient.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcHttpClient.java @@ -6,16 +6,12 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; +import java.io.*; import java.lang.reflect.Type; import java.net.HttpURLConnection; import java.net.Proxy; import java.net.URL; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -23,9 +19,8 @@ import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.ACCEPT_ENCODING; -import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.CONTENT_ENCODING; -import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.JSONRPC_CONTENT_TYPE; +import static com.googlecode.jsonrpc4j.JsonRpcBasicServer.*; +import static java.nio.charset.StandardCharsets.UTF_8; /** * A JSON-RPC client that uses the HTTP protocol. @@ -155,10 +150,14 @@ public Object invoke(String methodName, Object argument, Type returnType, Map= 0; ch = reader.read()) { - buffer.append((char) ch); - } - } - return buffer.toString(); - } catch (IOException e) { - return e.getMessage(); + private static byte[] readErrorStream(InputStream errorStream, int maxLength) throws IOException { + int b; + int pos = 0; + byte[] buffer = new byte[maxLength]; + while (pos < buffer.length && (b = errorStream.read(buffer, pos, buffer.length - pos)) != -1) { + pos += b; + } + if (pos == 0) { + throw new IOException("Empty error stream"); } + return pos < buffer.length? Arrays.copyOf(buffer, pos): buffer; } private void setupSsl(HttpURLConnection connection) { diff --git a/src/test/java/com/googlecode/jsonrpc4j/integration/HttpClientTest.java b/src/test/java/com/googlecode/jsonrpc4j/integration/HttpClientTest.java index 51448d02..2b098156 100644 --- a/src/test/java/com/googlecode/jsonrpc4j/integration/HttpClientTest.java +++ b/src/test/java/com/googlecode/jsonrpc4j/integration/HttpClientTest.java @@ -1,5 +1,6 @@ package com.googlecode.jsonrpc4j.integration; +import com.googlecode.jsonrpc4j.JsonRpcClientException; import com.googlecode.jsonrpc4j.ProxyUtil; import com.googlecode.jsonrpc4j.util.BaseRestTest; import com.googlecode.jsonrpc4j.util.FakeServiceInterface; @@ -9,6 +10,9 @@ import java.net.MalformedURLException; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; + /** * HttpClientTest */ @@ -36,7 +40,25 @@ public void testRequestAndResponse() throws MalformedURLException { int i = service.returnPrimitiveInt(2); Assert.assertEquals(2, i); } - + + @Test + public void testCustomException() throws Exception { + expectedEx.expectMessage(equalTo("Custom exception")); + expectedEx.expect(JsonRpcClientException.class); + + service = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), FakeServiceInterface.class, getHttpClient(false, false)); + service.throwSomeException("Custom exception"); + } + + @Test + public void testHttpError() throws Exception { + expectedEx.expectMessage(containsString("405 HTTP method POST is not supported by this URL")); + expectedEx.expect(Exception.class); + + service = ProxyUtil.createClientProxy(this.getClass().getClassLoader(), FakeServiceInterface.class, getHttpClient("error", false, false)); + service.doSomething(); + } + @Override protected Class service() { return FakeServiceInterfaceImpl.class; diff --git a/src/test/java/com/googlecode/jsonrpc4j/util/BaseRestTest.java b/src/test/java/com/googlecode/jsonrpc4j/util/BaseRestTest.java index fc7eb271..333b6365 100644 --- a/src/test/java/com/googlecode/jsonrpc4j/util/BaseRestTest.java +++ b/src/test/java/com/googlecode/jsonrpc4j/util/BaseRestTest.java @@ -51,6 +51,11 @@ protected JsonRpcHttpClient getHttpClient(boolean gzipRequests, boolean acceptGz Map header = new HashMap<>(); return new JsonRpcHttpClient(new ObjectMapper(), new URL(jettyServer.getCustomServerUrlString(JettyServer.SERVLET)), header, gzipRequests, acceptGzipResponses); } + + protected JsonRpcHttpClient getHttpClient(final String servlet, boolean gzipRequests, boolean acceptGzipResponses) throws MalformedURLException { + Map header = new HashMap<>(); + return new JsonRpcHttpClient(new ObjectMapper(), new URL(jettyServer.getCustomServerUrlString(servlet)), header, gzipRequests, acceptGzipResponses); + } @After public void teardown() throws Exception { From 14c52ca5cc73671145e53db421b658e61d4fa6b3 Mon Sep 17 00:00:00 2001 From: hiwayama Date: Tue, 23 Oct 2018 11:54:20 +0900 Subject: [PATCH 06/14] gzip response for JsonRpcMultiServer --- .../jsonrpc4j/JsonRpcMultiServer.java | 30 +++++++++------- .../googlecode/jsonrpc4j/JsonRpcServer.java | 36 +++++++++---------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcMultiServer.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcMultiServer.java index 1651286e..58589dd8 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcMultiServer.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcMultiServer.java @@ -38,29 +38,35 @@ */ @SuppressWarnings({"WeakerAccess", "unused"}) public class JsonRpcMultiServer extends JsonRpcServer { - + public static final char DEFAULT_SEPARATOR = '.'; private static final Logger logger = LoggerFactory.getLogger(JsonRpcMultiServer.class); - + private final Map handlerMap; private final Map> interfaceMap; private char separator = DEFAULT_SEPARATOR; - + public JsonRpcMultiServer() { this(new ObjectMapper()); logger.debug("created empty multi server"); } - + public JsonRpcMultiServer(ObjectMapper mapper) { super(mapper, null); this.handlerMap = new HashMap<>(); this.interfaceMap = new HashMap<>(); } - + + public JsonRpcMultiServer(ObjectMapper mapper, boolean gzipResponses) { + super(mapper, null, null, gzipResponses); + this.handlerMap = new HashMap<>(); + this.interfaceMap = new HashMap<>(); + } + public JsonRpcMultiServer addService(String name, Object handler) { return addService(name, handler, null); } - + public JsonRpcMultiServer addService(String name, Object handler, Class remoteInterface) { logger.debug("add service interface {} with handler {}", remoteInterface, handler); handlerMap.put(name, handler); @@ -69,15 +75,15 @@ public JsonRpcMultiServer addService(String name, Object handler, Class remot } return this; } - + public char getSeparator() { return this.separator; } - + public void setSeparator(char separator) { this.separator = separator; } - + /** * Returns the handler's class or interfaces. The serviceName is used * to look up a registered handler. @@ -96,7 +102,7 @@ protected Class[] getHandlerInterfaces(String serviceName) { return new Class[]{getHandler(serviceName).getClass()}; } } - + /** * Get the service name from the methodNode. JSON-RPC methods with the form * Service.method will result in "Service" being returned in this case. @@ -114,7 +120,7 @@ protected String getServiceName(final String methodName) { } return methodName; } - + /** * Get the method name from the methodNode, stripping off the service name. * @@ -131,7 +137,7 @@ protected String getMethodName(final String methodName) { } return methodName; } - + /** * Get the handler (object) that should be invoked to execute the specified * RPC method based on the specified service name. diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java index 4fb92342..9b1c954b 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcServer.java @@ -23,11 +23,11 @@ @SuppressWarnings("unused") public class JsonRpcServer extends JsonRpcBasicServer { private static final Logger logger = LoggerFactory.getLogger(JsonRpcServer.class); - + private static final String GZIP = "gzip"; - private final boolean gzipResponses; + protected final boolean gzipResponses; private String contentType = JSONRPC_CONTENT_TYPE; - + /** * Creates the server with the given {@link ObjectMapper} delegating * all calls to the given {@code handler} {@link Object} but only @@ -42,7 +42,7 @@ public JsonRpcServer(ObjectMapper mapper, Object handler, Class remoteInterfa super(mapper, handler, remoteInterface); this.gzipResponses = gzipResponses; } - + /** * Creates the server with the given {@link ObjectMapper} delegating * all calls to the given {@code handler} {@link Object} but only @@ -56,7 +56,7 @@ public JsonRpcServer(ObjectMapper mapper, Object handler, Class remoteInterfa super(mapper, handler, remoteInterface); this.gzipResponses = false; } - + /** * Creates the server with the given {@link ObjectMapper} delegating * all calls to the given {@code handler}. @@ -68,7 +68,7 @@ public JsonRpcServer(ObjectMapper mapper, Object handler) { super(mapper, handler, null); this.gzipResponses = false; } - + /** * Creates the server with a default {@link ObjectMapper} delegating * all calls to the given {@code handler} {@link Object} but only @@ -81,7 +81,7 @@ private JsonRpcServer(Object handler, Class remoteInterface) { super(new ObjectMapper(), handler, remoteInterface); this.gzipResponses = false; } - + /** * Creates the server with a default {@link ObjectMapper} delegating * all calls to the given {@code handler}. @@ -92,7 +92,7 @@ public JsonRpcServer(Object handler) { super(new ObjectMapper(), handler, null); this.gzipResponses = false; } - + /** * Handles a portlet request. * @@ -109,7 +109,7 @@ public void handle(ResourceRequest request, ResourceResponse response) throws IO // fix to not flush within handleRequest() but outside so http status code can be set output.flush(); } - + private InputStream getRequestStream(ResourceRequest request) throws IOException { if (request.getMethod().equals("POST")) { return request.getPortletInputStream(); @@ -119,11 +119,11 @@ private InputStream getRequestStream(ResourceRequest request) throws IOException throw new IOException("Invalid request method, only POST and GET is supported"); } } - + private static InputStream createInputStream(ResourceRequest request) throws IOException { return createInputStream(request.getParameter(METHOD), request.getParameter(ID), request.getParameter(PARAMS)); } - + /** * Handles a servlet request. * @@ -158,7 +158,7 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr byteOutput.writeTo(output); output.flush(); } - + private InputStream getRequestStream(HttpServletRequest request) throws IOException { InputStream input; if (request.getMethod().equals("POST")) { @@ -170,7 +170,7 @@ private InputStream getRequestStream(HttpServletRequest request) throws IOExcept } return input; } - + private int handleRequest0(InputStream input, OutputStream output, String contentEncoding, HttpServletResponse response, ByteArrayOutputStream byteOutput) throws IOException { int result; @@ -187,7 +187,7 @@ private int handleRequest0(InputStream input, OutputStream output, String conten return result; } - + private static InputStream createInputStream(InputStream inputStream, String contentEncoding) throws IOException { InputStream input; if (contentEncoding != null && GZIP.equalsIgnoreCase(contentEncoding)) { @@ -195,10 +195,10 @@ private static InputStream createInputStream(InputStream inputStream, String con } else { input = inputStream; } - + return input; } - + private static InputStream createInputStream(HttpServletRequest request) throws IOException { String method = request.getParameter(METHOD); String id = request.getParameter(ID); @@ -209,9 +209,9 @@ private static InputStream createInputStream(HttpServletRequest request) throws return createInputStream(method, id, params); } } - + public void setContentType(String contentType) { this.contentType = contentType; } - + } From d4384150f007d3c14959c38ca34fc072eee882fb Mon Sep 17 00:00:00 2001 From: Douglas-Lee Date: Tue, 16 Jul 2019 14:46:41 +0800 Subject: [PATCH 07/14] @JsonRpcService support placeholder --- .../spring/AutoJsonRpcClientProxyCreator.java | 258 +++++++++--------- 1 file changed, 134 insertions(+), 124 deletions(-) diff --git a/src/main/java/com/googlecode/jsonrpc4j/spring/AutoJsonRpcClientProxyCreator.java b/src/main/java/com/googlecode/jsonrpc4j/spring/AutoJsonRpcClientProxyCreator.java index c04bb77a..e02c5431 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/spring/AutoJsonRpcClientProxyCreator.java +++ b/src/main/java/com/googlecode/jsonrpc4j/spring/AutoJsonRpcClientProxyCreator.java @@ -1,124 +1,134 @@ -package com.googlecode.jsonrpc4j.spring; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.googlecode.jsonrpc4j.JsonRpcService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.DefaultListableBeanFactory; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.core.io.Resource; -import org.springframework.core.type.AnnotationMetadata; -import org.springframework.core.type.ClassMetadata; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; - -import static java.lang.String.format; -import static org.springframework.util.ClassUtils.convertClassNameToResourcePath; -import static org.springframework.util.ResourceUtils.CLASSPATH_URL_PREFIX; - -/** - * Auto-creates proxies for service interfaces annotated with {@link JsonRpcService}. - */ -@SuppressWarnings("unused") -public class AutoJsonRpcClientProxyCreator implements BeanFactoryPostProcessor, ApplicationContextAware { - - private static final Logger logger = LoggerFactory.getLogger(AutoJsonRpcClientProxyCreator.class); - private ApplicationContext applicationContext; - private String scanPackage; - private URL baseUrl; - private ObjectMapper objectMapper; - private String contentType; - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { - SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(applicationContext); - DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory; - String resolvedPath = resolvePackageToScan(); - logger.debug("Scanning '{}' for JSON-RPC service interfaces.", resolvedPath); - try { - for (Resource resource : applicationContext.getResources(resolvedPath)) { - if (resource.isReadable()) { - MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource); - ClassMetadata classMetadata = metadataReader.getClassMetadata(); - AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); - String jsonRpcPathAnnotation = JsonRpcService.class.getName(); - if (annotationMetadata.isAnnotated(jsonRpcPathAnnotation)) { - String className = classMetadata.getClassName(); - String path = (String) annotationMetadata.getAnnotationAttributes(jsonRpcPathAnnotation).get("value"); - logger.debug("Found JSON-RPC service to proxy [{}] on path '{}'.", className, path); - registerJsonProxyBean(defaultListableBeanFactory, className, path); - } - } - } - } catch (IOException e) { - throw new IllegalStateException(format("Cannot scan package '%s' for classes.", resolvedPath), e); - } - } - - /** - * Converts the scanPackage to something that the resource loader can handleRequest. - */ - private String resolvePackageToScan() { - return CLASSPATH_URL_PREFIX + convertClassNameToResourcePath(scanPackage) + "/**/*.class"; - } - - /** - * Registers a new proxy bean with the bean factory. - */ - private void registerJsonProxyBean(DefaultListableBeanFactory defaultListableBeanFactory, String className, String path) { - BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder - .rootBeanDefinition(JsonProxyFactoryBean.class) - .addPropertyValue("serviceUrl", appendBasePath(path)) - .addPropertyValue("serviceInterface", className); - - if (objectMapper != null) { - beanDefinitionBuilder.addPropertyValue("objectMapper", objectMapper); - } - - if (contentType != null) { - beanDefinitionBuilder.addPropertyValue("contentType", contentType); - } - - defaultListableBeanFactory.registerBeanDefinition(className + "-clientProxy", beanDefinitionBuilder.getBeanDefinition()); - } - - /** - * Appends the base path to the path found in the interface. - */ - private String appendBasePath(String path) { - try { - return new URL(baseUrl, path).toString(); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(format("Cannot combine URLs '%s' and '%s' to valid URL.", baseUrl, path), e); - } - } - - @Override - public void setApplicationContext(ApplicationContext applicationContext) { - this.applicationContext = applicationContext; - } - - public void setBaseUrl(URL baseUrl) { - this.baseUrl = baseUrl; - } - - public void setScanPackage(String scanPackage) { - this.scanPackage = scanPackage; - } - - public void setObjectMapper(ObjectMapper objectMapper) { - this.objectMapper = objectMapper; - } - - public void setContentType(String contextType) { - this.contentType = contextType; - } -} +package com.googlecode.jsonrpc4j.spring; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.googlecode.jsonrpc4j.JsonRpcService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; +import org.springframework.core.io.Resource; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.ClassMetadata; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.SimpleMetadataReaderFactory; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; + +import static java.lang.String.format; +import static org.springframework.util.ClassUtils.convertClassNameToResourcePath; +import static org.springframework.util.ResourceUtils.CLASSPATH_URL_PREFIX; + +/** + * Auto-creates proxies for service interfaces annotated with {@link JsonRpcService}. + */ +@SuppressWarnings("unused") +public class AutoJsonRpcClientProxyCreator implements BeanFactoryPostProcessor, ApplicationContextAware, EnvironmentAware { + + private static final Logger logger = LoggerFactory.getLogger(AutoJsonRpcClientProxyCreator.class); + private ApplicationContext applicationContext; + private Environment environment; + private String scanPackage; + private URL baseUrl; + private ObjectMapper objectMapper; + private String contentType; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { + SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory(applicationContext); + DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory; + String resolvedPath = resolvePackageToScan(); + logger.debug("Scanning '{}' for JSON-RPC service interfaces.", resolvedPath); + try { + for (Resource resource : applicationContext.getResources(resolvedPath)) { + if (resource.isReadable()) { + MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource); + ClassMetadata classMetadata = metadataReader.getClassMetadata(); + AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); + String jsonRpcPathAnnotation = JsonRpcService.class.getName(); + if (annotationMetadata.isAnnotated(jsonRpcPathAnnotation)) { + String className = classMetadata.getClassName(); + String path = (String) annotationMetadata.getAnnotationAttributes(jsonRpcPathAnnotation).get("value"); + path = this.environment.resolvePlaceholders(path); + logger.debug("Found JSON-RPC service to proxy [{}] on path '{}'.", className, path); + registerJsonProxyBean(defaultListableBeanFactory, className, path); + } + } + } + } catch (IOException e) { + throw new IllegalStateException(format("Cannot scan package '%s' for classes.", resolvedPath), e); + } + } + + /** + * Converts the scanPackage to something that the resource loader can handleRequest. + */ + private String resolvePackageToScan() { + return CLASSPATH_URL_PREFIX + convertClassNameToResourcePath(scanPackage) + "/**/*.class"; + } + + /** + * Registers a new proxy bean with the bean factory. + */ + private void registerJsonProxyBean(DefaultListableBeanFactory defaultListableBeanFactory, String className, String path) { + BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder + .rootBeanDefinition(JsonProxyFactoryBean.class) + .addPropertyValue("serviceUrl", appendBasePath(path)) + .addPropertyValue("serviceInterface", className); + + if (objectMapper != null) { + beanDefinitionBuilder.addPropertyValue("objectMapper", objectMapper); + } + + if (contentType != null) { + beanDefinitionBuilder.addPropertyValue("contentType", contentType); + } + + defaultListableBeanFactory.registerBeanDefinition(className + "-clientProxy", beanDefinitionBuilder.getBeanDefinition()); + } + + /** + * Appends the base path to the path found in the interface. + */ + private String appendBasePath(String path) { + try { + return new URL(baseUrl, path).toString(); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(format("Cannot combine URLs '%s' and '%s' to valid URL.", baseUrl, path), e); + } + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + this.applicationContext = applicationContext; + } + + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + public void setBaseUrl(URL baseUrl) { + this.baseUrl = baseUrl; + } + + public void setScanPackage(String scanPackage) { + this.scanPackage = scanPackage; + } + + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + public void setContentType(String contextType) { + this.contentType = contextType; + } +} From 33fae5c9523da1904f74c24cfe7ba244a9bca588 Mon Sep 17 00:00:00 2001 From: Douglas-Lee Date: Wed, 17 Jul 2019 17:15:05 +0800 Subject: [PATCH 08/14] fix AutoJsonRpcClientProxyCreator can't not override the json-rpc method --- src/main/java/com/googlecode/jsonrpc4j/ProxyUtil.java | 2 +- .../com/googlecode/jsonrpc4j/spring/JsonProxyFactoryBean.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/googlecode/jsonrpc4j/ProxyUtil.java b/src/main/java/com/googlecode/jsonrpc4j/ProxyUtil.java index 5c6d6047..95b4af24 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/ProxyUtil.java +++ b/src/main/java/com/googlecode/jsonrpc4j/ProxyUtil.java @@ -163,7 +163,7 @@ private static boolean isDeclaringClassAnObject(Method method) { return method.getDeclaringClass() == Object.class; } - private static String getMethodName(Method method) { + public static String getMethodName(Method method) { final JsonRpcMethod jsonRpcMethod = ReflectionUtil.getAnnotation(method, JsonRpcMethod.class); if (jsonRpcMethod == null) { return method.getName(); diff --git a/src/main/java/com/googlecode/jsonrpc4j/spring/JsonProxyFactoryBean.java b/src/main/java/com/googlecode/jsonrpc4j/spring/JsonProxyFactoryBean.java index 76f52eee..654b9262 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/spring/JsonProxyFactoryBean.java +++ b/src/main/java/com/googlecode/jsonrpc4j/spring/JsonProxyFactoryBean.java @@ -4,6 +4,7 @@ import com.googlecode.jsonrpc4j.JsonRpcClient.RequestListener; import com.googlecode.jsonrpc4j.ExceptionResolver; import com.googlecode.jsonrpc4j.JsonRpcHttpClient; +import com.googlecode.jsonrpc4j.ProxyUtil; import com.googlecode.jsonrpc4j.ReflectionUtil; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; @@ -104,7 +105,7 @@ public Object invoke(MethodInvocation invocation) Type retType = (invocation.getMethod().getGenericReturnType() != null) ? invocation.getMethod().getGenericReturnType() : invocation.getMethod().getReturnType(); Object arguments = ReflectionUtil.parseArguments(invocation.getMethod(), invocation.getArguments()); - return jsonRpcHttpClient.invoke(invocation.getMethod().getName(), arguments, retType, extraHttpHeaders); + return jsonRpcHttpClient.invoke(ProxyUtil.getMethodName(method), arguments, retType, extraHttpHeaders); } /** From df5aa24da932a8da152bc9900911d110600b8123 Mon Sep 17 00:00:00 2001 From: anysoft Date: Fri, 15 Nov 2019 15:58:37 +0800 Subject: [PATCH 09/14] fix #251 fix the issue https://github.com/briandilley/jsonrpc4j/issues/251 add params node into request when args is null or empty . --- src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java index 57a91721..a99f76e9 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java @@ -343,6 +343,7 @@ private ObjectNode internalCreateRequest(String methodName, Object arguments, St addParameters(arguments, request); addAdditionalHeaders(request); notifyBeforeRequestListener(request); + addNoneArguments(request); return request; } @@ -423,6 +424,13 @@ private boolean isCollectionArguments(Object arguments) { return arguments != null && Collection.class.isInstance(arguments); } + private void addNoneArguments(ObjectNode request){ + if (!request.has(PARAMS)){ + //for none params add an empty array + request.set(PARAMS,mapper.valueToTree(new String[0])); + } + } + private void addCollectionArguments(Object arguments, ObjectNode request) { Collection args = Collection.class.cast(arguments); if (!args.isEmpty()) { From 73e9d71e082279f104655816b2813ac637109aba Mon Sep 17 00:00:00 2001 From: anysoft Date: Fri, 15 Nov 2019 17:18:25 +0800 Subject: [PATCH 10/14] response error node except int 0 some server response has error node. when success the error node is int value 0; --- src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java index a99f76e9..73cac55e 100644 --- a/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java +++ b/src/main/java/com/googlecode/jsonrpc4j/JsonRpcClient.java @@ -325,7 +325,7 @@ private boolean isIdValueNotCorrect(String id, ObjectNode jsonObject) { } protected boolean hasError(ObjectNode jsonObject) { - return jsonObject.has(ERROR) && jsonObject.get(ERROR) != null && !jsonObject.get(ERROR).isNull(); + return jsonObject.has(ERROR) && jsonObject.get(ERROR) != null && !jsonObject.get(ERROR).isNull() && !(jsonObject.get(ERROR).isInt() && jsonObject.intValue()==0) ; } /** From 9d911563bc90b5a6182d92425296ed2b9efbfe8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Mon, 24 Feb 2020 15:08:05 +0100 Subject: [PATCH 11/14] Dependencies upgrade to newest. --- build.gradle | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 58d966a7..355e23a8 100644 --- a/build.gradle +++ b/build.gradle @@ -39,11 +39,11 @@ repositories { dependencies { ext { - jacksonVersion = '2.8.5' - springVersion = '4.3.5.RELEASE' - springBotVersion = '1.4.3.RELEASE' - jettyVersion = '9.4.0.RC3' - slf4jVersion = '1.7.22' + jacksonVersion = '2.10.2' + springVersion = '4.3.26.RELEASE' + springBotVersion = '1.4.7.RELEASE' + jettyVersion = '9.4.26.v20200117' + slf4jVersion = '1.7.30' } compile 'net.iharder:base64:2.3.9' From fba90729cc11df44c05cdc900077b0f6f274c10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Mon, 24 Feb 2020 18:32:25 +0100 Subject: [PATCH 12/14] Revert upgrade of jetty due to failing tests. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 355e23a8..a892f124 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ dependencies { jacksonVersion = '2.10.2' springVersion = '4.3.26.RELEASE' springBotVersion = '1.4.7.RELEASE' - jettyVersion = '9.4.26.v20200117' + jettyVersion = '9.4.0.RC3' slf4jVersion = '1.7.30' } From a8672218ea78bb68c0ad54c5418322d263134348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Mon, 24 Feb 2020 18:32:49 +0100 Subject: [PATCH 13/14] Local maven repository support. --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index a892f124..9f5f83dd 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,10 @@ compileTestJava { options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" } +apply plugin: "maven" + repositories { + mavenLocal() mavenCentral() } From 5904d11fbea6cbcc5a77a08822519ea1668b919d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Fibich?= Date: Mon, 24 Feb 2020 18:33:02 +0100 Subject: [PATCH 14/14] Release 1.5.3-2 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9f5f83dd..94ce2fd0 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ plugins { } description = 'This project aims to provide the facility to easily implement JSON-RPC for the java programming language.' -version = '1.5.3' +version = '1.5.3-2' group = 'com.github.briandilley.jsonrpc4j' sourceCompatibility = 1.7