This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch 3.2
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.2 by this push:
     new c5a03c9458 Rest bugfix & optimization (#11617)
c5a03c9458 is described below

commit c5a03c94581e6a68443146ead2b632c34c2f6138
Author: Mengyang Tang <[email protected]>
AuthorDate: Thu Feb 23 09:40:25 2023 +0800

    Rest bugfix & optimization (#11617)
    
    * Modifier optimize
    
    * rawtypes problem optimize
    
    * Remove commented redundant code
    
    * Constants optimize
    
    * Fix consistency bug
    
    * Support exception mapper extension
    
    * resolve conflict
---
 .../rpc/protocol/rest/BaseRestProtocolServer.java  | 12 ++++----
 .../apache/dubbo/rpc/protocol/rest/Constants.java  | 14 ++++++++-
 .../rpc/protocol/rest/DubboHttpProtocolServer.java |  9 +++---
 .../rpc/protocol/rest/DubboResourceFactory.java    | 22 ++------------
 .../rpc/protocol/rest/NettyRestProtocolServer.java |  3 +-
 .../rpc/protocol/rest/ReferenceCountedClient.java  |  2 +-
 .../dubbo/rpc/protocol/rest/RestProtocol.java      | 35 +++++++++++++---------
 .../rpc/protocol/rest/RestProtocolServer.java      |  4 +--
 .../dubbo/rpc/protocol/rest/RestServerFactory.java |  5 ++--
 .../dubbo/rpc/protocol/rest/RpcContextFilter.java  |  9 +++---
 .../rpc/protocol/rest/RpcExceptionMapper.java      | 11 +++----
 .../rpc/protocol/rest/JaxrsRestProtocolTest.java   | 31 +++++++++++++++++--
 .../rpc/protocol/rest/RpcExceptionMapperTest.java  |  4 +--
 13 files changed, 94 insertions(+), 67 deletions(-)

diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestProtocolServer.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestProtocolServer.java
index 95bdccb707..baa0fff9cc 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestProtocolServer.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/BaseRestProtocolServer.java
@@ -25,22 +25,22 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import static 
org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
+import static 
org.apache.dubbo.rpc.protocol.rest.Constants.EXCEPTION_MAPPER_KEY;
 import static org.apache.dubbo.rpc.protocol.rest.Constants.EXTENSION_KEY;
 
 public abstract class BaseRestProtocolServer implements RestProtocolServer {
 
     private String address;
 
-    private Map<String, Object> attributes = new ConcurrentHashMap<>();
+    private final Map<String, Object> attributes = new ConcurrentHashMap<>();
 
     @Override
     public void start(URL url) {
         getDeployment().getMediaTypeMappings().put("json", "application/json");
         getDeployment().getMediaTypeMappings().put("xml", "text/xml");
-//        server.getDeployment().getMediaTypeMappings().put("xml", 
"application/xml");
         
getDeployment().getProviderClasses().add(RpcContextFilter.class.getName());
-        // TODO users can override this mapper, but we just rely on the 
current priority strategy of resteasy
-        
getDeployment().getProviderClasses().add(RpcExceptionMapper.class.getName());
+
+        loadProviders(url.getParameter(EXCEPTION_MAPPER_KEY, 
RpcExceptionMapper.class.getName()));
 
         loadProviders(url.getParameter(EXTENSION_KEY, ""));
 
@@ -48,7 +48,7 @@ public abstract class BaseRestProtocolServer implements 
RestProtocolServer {
     }
 
     @Override
-    public void deploy(Class resourceDef, Object resourceInstance, String 
contextPath) {
+    public void deploy(Class<?> resourceDef, Object resourceInstance, String 
contextPath) {
         if (StringUtils.isEmpty(contextPath)) {
             getDeployment().getRegistry().addResourceFactory(new 
DubboResourceFactory(resourceInstance, resourceDef));
         } else {
@@ -57,7 +57,7 @@ public abstract class BaseRestProtocolServer implements 
RestProtocolServer {
     }
 
     @Override
-    public void undeploy(Class resourceDef) {
+    public void undeploy(Class<?> resourceDef) {
         getDeployment().getRegistry().removeRegistrations(resourceDef);
     }
 
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/Constants.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/Constants.java
index 90747c9a3a..8966315425 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/Constants.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/Constants.java
@@ -18,7 +18,7 @@
 package org.apache.dubbo.rpc.protocol.rest;
 
 /**
- *
+ * Constants definition.
  */
 public interface Constants {
     String KEEP_ALIVE_KEY = "keepalive";
@@ -26,4 +26,16 @@ public interface Constants {
     boolean DEFAULT_KEEP_ALIVE = true;
 
     String EXTENSION_KEY = "extension";
+
+    // http server
+    String SERVLET = "servlet";
+
+    String JETTY = "jetty";
+
+    String TOMCAT = "tomcat";
+
+    String NETTY = "netty";
+
+    // exception mapper
+    String EXCEPTION_MAPPER_KEY = "exception.mapper";
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboHttpProtocolServer.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboHttpProtocolServer.java
index 71db6b963a..475238d548 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboHttpProtocolServer.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboHttpProtocolServer.java
@@ -40,9 +40,8 @@ public class DubboHttpProtocolServer extends 
BaseRestProtocolServer {
 
     private final HttpServletDispatcher dispatcher = new 
HttpServletDispatcher();
     private final ResteasyDeployment deployment = new ResteasyDeployment();
-    private HttpBinder httpBinder;
+    private final HttpBinder httpBinder;
     private HttpServer httpServer;
-//    private boolean isExternalServer;
 
     public DubboHttpProtocolServer(HttpBinder httpBinder) {
         this.httpBinder = httpBinder;
@@ -114,15 +113,15 @@ public class DubboHttpProtocolServer extends 
BaseRestProtocolServer {
         }
 
         @Override
-        public Enumeration getInitParameterNames() {
-            return new Enumeration() {
+        public Enumeration<String> getInitParameterNames() {
+            return new Enumeration<String>() {
                 @Override
                 public boolean hasMoreElements() {
                     return false;
                 }
 
                 @Override
-                public Object nextElement() {
+                public String nextElement() {
                     return null;
                 }
             };
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboResourceFactory.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboResourceFactory.java
index 191102e2cd..ac8695ccc4 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboResourceFactory.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/DubboResourceFactory.java
@@ -23,24 +23,17 @@ import org.jboss.resteasy.spi.ResteasyProviderFactory;
 
 /**
  * We don't support propertyInjector here since the resource impl should be 
singleton in dubbo
- *
  */
 public class DubboResourceFactory implements ResourceFactory {
 
-    private Object resourceInstance;
-    private Class scannableClass;
-//    private PropertyInjector propertyInjector;
-//    private String context = null;
+    private final Object resourceInstance;
+    private final Class<?> scannableClass;
 
-    public DubboResourceFactory(Object resourceInstance, Class scannableClass) 
{
+    public DubboResourceFactory(Object resourceInstance, Class<?> 
scannableClass) {
         this.resourceInstance = resourceInstance;
         this.scannableClass = scannableClass;
     }
 
-//    public PropertyInjector getPropertyInjector() {
-//        return propertyInjector;
-//    }
-
     @Override
     public Object createResource(HttpRequest request, HttpResponse response,
                                  ResteasyProviderFactory factory) {
@@ -54,7 +47,6 @@ public class DubboResourceFactory implements ResourceFactory {
 
     @Override
     public void registered(ResteasyProviderFactory factory) {
-//        this.propertyInjector = 
factory.getInjectorFactory().createPropertyInjector(getScannableClass(), 
factory);
     }
 
     @Override
@@ -65,12 +57,4 @@ public class DubboResourceFactory implements ResourceFactory 
{
     @Override
     public void unregistered() {
     }
-
-//    public void setContext(String context) {
-//        this.context = context;
-//    }
-//
-//    public String getContext() {
-//        return context;
-//    }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyRestProtocolServer.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyRestProtocolServer.java
index b066c79f43..fbb9be782e 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyRestProtocolServer.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/NettyRestProtocolServer.java
@@ -46,13 +46,14 @@ public class NettyRestProtocolServer extends 
BaseRestProtocolServer {
     private final NettyJaxrsServer server = new NettyJaxrsServer();
 
     @Override
+    @SuppressWarnings("rawtypes")
     protected void doStart(URL url) {
         String bindIp = url.getParameter(BIND_IP_KEY, url.getHost());
         if (!url.isAnyHost() && NetUtils.isValidLocalHost(bindIp)) {
             server.setHostname(bindIp);
         }
         server.setPort(url.getParameter(BIND_PORT_KEY, url.getPort()));
-        Map<ChannelOption, Object> channelOption = new HashMap<ChannelOption, 
Object>();
+        Map<ChannelOption, Object> channelOption = new HashMap<>();
         channelOption.put(ChannelOption.SO_KEEPALIVE, 
url.getParameter(KEEP_ALIVE_KEY, DEFAULT_KEEP_ALIVE));
         server.setChildChannelOptions(channelOption);
         server.setExecutorThreadCount(url.getParameter(THREADS_KEY, 
DEFAULT_THREADS));
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/ReferenceCountedClient.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/ReferenceCountedClient.java
index fc8d4664c8..22de2147c2 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/ReferenceCountedClient.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/ReferenceCountedClient.java
@@ -26,7 +26,7 @@ import static 
org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERR
 public class ReferenceCountedClient<T extends RestClient> extends 
ReferenceCountedResource {
     private static final ErrorTypeAwareLogger logger = 
LoggerFactory.getErrorTypeAwareLogger(ReferenceCountedClient.class);
 
-    private T client;
+    private final T client;
 
     public ReferenceCountedClient(T client) {
         this.client = client;
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
index 90e254be71..4cd8376263 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
@@ -65,12 +65,12 @@ import static 
org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERR
 import static 
org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_ERROR_CLOSE_SERVER;
 import static org.apache.dubbo.remoting.Constants.SERVER_KEY;
 import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
+import static 
org.apache.dubbo.rpc.protocol.rest.constans.RestConstant.PATH_SEPARATOR;
 
 public class RestProtocol extends AbstractProxyProtocol {
 
     private static final int DEFAULT_PORT = 80;
-    private static final String DEFAULT_SERVER = "jetty";
-    private static final String DEFAULT_CLIENT = 
org.apache.dubbo.remoting.Constants.OK_HTTP;
+    private static final String DEFAULT_SERVER = Constants.JETTY;
 
     private final RestServerFactory serverFactory = new RestServerFactory();
 
@@ -95,7 +95,7 @@ public class RestProtocol extends AbstractProxyProtocol {
     @Override
     protected <T> Runnable doExport(T impl, Class<T> type, URL url) throws 
RpcException {
         String addr = getAddr(url);
-        Class implClass = url.getServiceModel().getProxyObject().getClass();
+        Class<?> implClass = url.getServiceModel().getProxyObject().getClass();
         RestProtocolServer server = (RestProtocolServer) 
ConcurrentHashMapUtils.computeIfAbsent(serverMap, addr, restServer -> {
             RestProtocolServer s = 
serverFactory.createServer(url.getParameter(SERVER_KEY, DEFAULT_SERVER));
             s.setAddress(url.getAddress());
@@ -104,7 +104,7 @@ public class RestProtocol extends AbstractProxyProtocol {
         });
 
         String contextPath = getContextPath(url);
-        if ("servlet".equalsIgnoreCase(url.getParameter(SERVER_KEY, 
DEFAULT_SERVER))) {
+        if (Constants.SERVLET.equalsIgnoreCase(url.getParameter(SERVER_KEY, 
DEFAULT_SERVER))) {
             ServletContext servletContext = 
ServletManager.getInstance().getServletContext(ServletManager.EXTERNAL_SERVER_PORT);
             if (servletContext == null) {
                 throw new RpcException("No servlet context found. Since you 
are using server='servlet', " +
@@ -118,13 +118,13 @@ public class RestProtocol extends AbstractProxyProtocol {
                         "make sure that the 'contextpath' property starts with 
the path of external webapp");
                 }
                 contextPath = contextPath.substring(webappPath.length());
-                if (contextPath.startsWith("/")) {
+                if (contextPath.startsWith(PATH_SEPARATOR)) {
                     contextPath = contextPath.substring(1);
                 }
             }
         }
 
-        final Class resourceDef = GetRestful.getRootResourceClass(implClass) 
!= null ? implClass : type;
+        final Class<?> resourceDef = 
GetRestful.getRootResourceClass(implClass) != null ? implClass : type;
 
         server.deploy(resourceDef, impl, contextPath);
 
@@ -136,15 +136,22 @@ public class RestProtocol extends AbstractProxyProtocol {
         };
     }
 
-
     @Override
     protected <T> Invoker<T> protocolBindingRefer(final Class<T> type, final 
URL url) throws RpcException {
 
-        ReferenceCountedClient<? extends RestClient> refClient =
-            clients.computeIfAbsent(url.getAddress(), key -> 
createReferenceCountedClient(url));
-
+        ReferenceCountedClient<? extends RestClient> refClient = 
clients.get(url.getAddress());
+        if (refClient == null || refClient.isDestroyed()) {
+            synchronized (clients) {
+                refClient = clients.get(url.getAddress());
+                if (refClient == null || refClient.isDestroyed()) {
+                    refClient = 
ConcurrentHashMapUtils.computeIfAbsent(clients, url.getAddress(), _key -> 
createReferenceCountedClient(url));
+                }
+            }
+        }
         refClient.retain();
 
+        final ReferenceCountedClient<? extends RestClient> glueRefClient = 
refClient;
+
         // resolve metadata
         Map<String, Map<ParameterTypesComparator, RestMethodMetadata>> 
metadataMap = MetadataResolver.resolveConsumerServiceMetadata(type, url);
 
@@ -168,7 +175,7 @@ public class RestProtocol extends AbstractProxyProtocol {
                         intercept.intercept(httpConnectionCreateContext);
                     }
 
-                    CompletableFuture<RestResult> future = 
refClient.getClient().send(requestTemplate);
+                    CompletableFuture<RestResult> future = 
glueRefClient.getClient().send(requestTemplate);
                     CompletableFuture<AppResponse> responseFuture = new 
CompletableFuture<>();
                     AsyncRpcResult asyncRpcResult = new 
AsyncRpcResult(responseFuture, invocation);
                     future.whenComplete((r, t) -> {
@@ -260,7 +267,7 @@ public class RestProtocol extends AbstractProxyProtocol {
         if (logger.isInfoEnabled()) {
             logger.info("Closing rest clients");
         }
-        for (ReferenceCountedClient client : clients.values()) {
+        for (ReferenceCountedClient<?> client : clients.values()) {
             try {
                 // destroy directly regardless of the current reference count.
                 client.destroy();
@@ -287,7 +294,7 @@ public class RestProtocol extends AbstractProxyProtocol {
             if (contextPath.endsWith(url.getParameter(INTERFACE_KEY))) {
                 contextPath = contextPath.substring(0, 
contextPath.lastIndexOf(url.getParameter(INTERFACE_KEY)));
             }
-            return contextPath.endsWith("/") ? contextPath.substring(0, 
contextPath.length() - 1) : contextPath;
+            return contextPath.endsWith(PATH_SEPARATOR) ? 
contextPath.substring(0, contextPath.length() - 1) : contextPath;
         } else {
             return "";
         }
@@ -296,7 +303,7 @@ public class RestProtocol extends AbstractProxyProtocol {
     @Override
     protected void destroyInternal(URL url) {
         try {
-            ReferenceCountedClient referenceCountedClient = 
clients.get(url.getAddress());
+            ReferenceCountedClient<?> referenceCountedClient = 
clients.get(url.getAddress());
             if (referenceCountedClient != null && 
referenceCountedClient.release()) {
                 clients.remove(url.getAddress());
             }
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolServer.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolServer.java
index fe16f4687f..ee03685662 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolServer.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolServer.java
@@ -26,8 +26,8 @@ public interface RestProtocolServer extends ProtocolServer {
     /**
      * @param resourceDef it could be either resource interface or resource 
impl
      */
-    void deploy(Class resourceDef, Object resourceInstance, String 
contextPath);
+    void deploy(Class<?> resourceDef, Object resourceInstance, String 
contextPath);
 
-    void undeploy(Class resourceDef);
+    void undeploy(Class<?> resourceDef);
 
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServerFactory.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServerFactory.java
index 265987241e..01c0df5aed 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServerFactory.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestServerFactory.java
@@ -28,10 +28,9 @@ public class RestServerFactory {
     private static final HttpBinder httpBinder = 
FrameworkModel.defaultModel().getAdaptiveExtension(HttpBinder.class);
 
     public RestProtocolServer createServer(String name) {
-        // TODO move names to Constants
-        if ("servlet".equalsIgnoreCase(name) || "jetty".equalsIgnoreCase(name) 
|| "tomcat".equalsIgnoreCase(name)) {
+        if (Constants.SERVLET.equalsIgnoreCase(name) || 
Constants.JETTY.equalsIgnoreCase(name) || 
Constants.TOMCAT.equalsIgnoreCase(name)) {
             return new DubboHttpProtocolServer(httpBinder);
-        } else if ("netty".equalsIgnoreCase(name)) {
+        } else if (Constants.NETTY.equalsIgnoreCase(name)) {
             return new NettyRestProtocolServer();
         } else {
             throw new IllegalArgumentException("Unrecognized server name: " + 
name);
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcContextFilter.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcContextFilter.java
index 70edad5bcc..3572ea67e3 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcContextFilter.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcContextFilter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.rpc.protocol.rest;
 
+import org.apache.dubbo.common.constants.CommonConstants;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.rpc.Invocation;
@@ -40,7 +41,7 @@ public class RpcContextFilter implements 
ContainerRequestFilter, ClientRequestFi
 
     private static final String DUBBO_ATTACHMENT_HEADER = "Dubbo-Attachments";
 
-    // currently we use a single header to hold the attachments so that the 
total attachment size limit is about 8k
+    // currently, we use a single header to hold the attachments so that the 
total attachment size limit is about 8k
     private static final int MAX_HEADER_SIZE = 8 * 1024;
 
     @Override
@@ -57,7 +58,7 @@ public class RpcContextFilter implements 
ContainerRequestFilter, ClientRequestFi
 
         String headers = 
requestContext.getHeaderString(DUBBO_ATTACHMENT_HEADER);
         if (headers != null) {
-            for (String header : headers.split(",")) {
+            for (String header : 
headers.split(CommonConstants.COMMA_SEPARATOR)) {
                 int index = header.indexOf("=");
                 if (index > 0) {
                     String key = header.substring(0, index);
@@ -101,14 +102,14 @@ public class RpcContextFilter implements 
ContainerRequestFilter, ClientRequestFi
 
     private boolean illegalHttpHeaderKey(String key) {
         if (StringUtils.isNotEmpty(key)) {
-            return key.contains(",") || key.contains("=");
+            return key.contains(CommonConstants.COMMA_SEPARATOR) || 
key.contains("=");
         }
         return false;
     }
 
     private boolean illegalHttpHeaderValue(String value) {
         if (StringUtils.isNotEmpty(value)) {
-            return value.contains(",");
+            return value.contains(CommonConstants.COMMA_SEPARATOR);
         }
         return false;
     }
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapper.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapper.java
index e0fb782607..de6d2e45a6 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapper.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapper.java
@@ -28,24 +28,21 @@ public class RpcExceptionMapper implements 
ExceptionMapper<RpcException> {
 
     @Override
     public Response toResponse(RpcException e) {
-        // TODO do more sophisticated exception handling and output
         if (e.getCause() instanceof ConstraintViolationException) {
             return 
handleConstraintViolationException((ConstraintViolationException) e.getCause());
         }
         // we may want to avoid exposing the dubbo exception details to 
certain clients
-        // TODO for now just do plain text output
         return 
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("Internal server 
error: " + e.getMessage()).type(ContentType.TEXT_PLAIN_UTF_8).build();
     }
 
     protected Response 
handleConstraintViolationException(ConstraintViolationException cve) {
         ViolationReport report = new ViolationReport();
-        for (ConstraintViolation cv : cve.getConstraintViolations()) {
+        for (ConstraintViolation<?> cv : cve.getConstraintViolations()) {
             report.addConstraintViolation(new RestConstraintViolation(
-                    cv.getPropertyPath().toString(),
-                    cv.getMessage(),
-                    cv.getInvalidValue() == null ? "null" : 
cv.getInvalidValue().toString()));
+                cv.getPropertyPath().toString(),
+                cv.getMessage(),
+                cv.getInvalidValue() == null ? "null" : 
cv.getInvalidValue().toString()));
         }
-        // TODO for now just do xml output
         return 
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(report).type(ContentType.TEXT_XML_UTF_8).build();
     }
 }
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java
index 3c4510056b..cff2d73222 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/JaxrsRestProtocolTest.java
@@ -35,15 +35,19 @@ import org.apache.dubbo.rpc.model.ServiceDescriptor;
 
 import org.apache.dubbo.rpc.protocol.rest.rest.AnotherUserRestService;
 import org.apache.dubbo.rpc.protocol.rest.rest.AnotherUserRestServiceImpl;
+
 import org.hamcrest.CoreMatchers;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
 import java.util.Arrays;
 import java.util.Map;
 
 import static org.apache.dubbo.remoting.Constants.SERVER_KEY;
+import static 
org.apache.dubbo.rpc.protocol.rest.Constants.EXCEPTION_MAPPER_KEY;
 import static org.apache.dubbo.rpc.protocol.rest.Constants.EXTENSION_KEY;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
@@ -51,8 +55,8 @@ import static org.hamcrest.CoreMatchers.nullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 
 class JaxrsRestProtocolTest {
-    private Protocol protocol = 
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("rest");
-    private ProxyFactory proxy = 
ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+    private final Protocol protocol = 
ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("rest");
+    private final ProxyFactory proxy = 
ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
     private final int availablePort = NetUtils.getAvailablePort();
     private final URL exportUrl = URL.valueOf("rest://127.0.0.1:" + 
availablePort + 
"/rest?interface=org.apache.dubbo.rpc.protocol.rest.DemoService");
     private final ModuleServiceRepository repository = 
ApplicationModel.defaultModel().getDefaultModule().getServiceRepository();
@@ -282,6 +286,29 @@ class JaxrsRestProtocolTest {
         assertThat(protocol.getDefaultPort(), is(80));
     }
 
+    @Test
+    void testExceptionMapper() {
+        DemoService server = new DemoServiceImpl();
+
+        URL url = this.registerProvider(exportUrl, server, DemoService.class);
+
+        URL exceptionUrl = url.addParameter(EXCEPTION_MAPPER_KEY, 
TestExceptionMapper.class.getName());
+
+        protocol.export(proxy.getInvoker(server, DemoService.class, 
exceptionUrl));
+
+        DemoService referDemoService = 
this.proxy.getProxy(protocol.refer(DemoService.class, exceptionUrl));
+
+        Assertions.assertEquals("test-exception", referDemoService.error());
+    }
+
+    public static class TestExceptionMapper implements 
ExceptionMapper<RuntimeException> {
+
+        @Override
+        public Response toResponse(RuntimeException e) {
+            return Response.ok("test-exception").build();
+        }
+    }
+
     private URL registerProvider(URL url, Object impl, Class<?> 
interfaceClass) {
         ServiceDescriptor serviceDescriptor = 
repository.registerService(interfaceClass);
         ProviderModel providerModel = new ProviderModel(
diff --git 
a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapperTest.java
 
b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapperTest.java
index 5d4410ed7e..b8a983c055 100644
--- 
a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapperTest.java
+++ 
b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RpcExceptionMapperTest.java
@@ -46,8 +46,8 @@ class RpcExceptionMapperTest {
     @Test
     void testConstraintViolationException() {
         ConstraintViolationException violationException = 
mock(ConstraintViolationException.class);
-        ConstraintViolation violation = mock(ConstraintViolation.class, 
Answers.RETURNS_DEEP_STUBS);
-        
given(violationException.getConstraintViolations()).willReturn(Sets.<ConstraintViolation<?>>newSet(violation));
+        ConstraintViolation<?> violation = mock(ConstraintViolation.class, 
Answers.RETURNS_DEEP_STUBS);
+        
given(violationException.getConstraintViolations()).willReturn(Sets.newSet(violation));
         RpcException rpcException = new RpcException("violation", 
violationException);
 
         Response response = exceptionMapper.toResponse(rpcException);

Reply via email to