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

reta pushed a commit to branch CXF-8174
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 893f86f79688cd9587fffeed493c33cdd3325d5a
Author: reta <[email protected]>
AuthorDate: Wed Dec 18 21:35:41 2019 -0500

    CXF-8174: Incorrect service method resolution
---
 .../org/apache/cxf/jaxrs/utils/JAXRSUtils.java     | 17 ++++--
 .../test/java/org/apache/cxf/jaxrs/BaseApi.java    | 39 ++++++++++++++
 .../java/org/apache/cxf/jaxrs/BaseRequest.java     | 32 +++++++++++
 .../java/org/apache/cxf/jaxrs/BaseResponse.java    | 32 +++++++++++
 .../java/org/apache/cxf/jaxrs/CustomerService.java | 35 ++++++++++++
 .../apache/cxf/jaxrs/CustomerServiceRequest.java   | 35 ++++++++++++
 .../apache/cxf/jaxrs/CustomerServiceResource.java  | 29 ++++++++++
 .../apache/cxf/jaxrs/CustomerServiceResponse.java  | 23 ++++++++
 .../java/org/apache/cxf/jaxrs/CustomizedApi.java   | 38 +++++++++++++
 .../java/org/apache/cxf/jaxrs/GenericService.java  | 24 +++++++++
 .../cxf/jaxrs/SelectMethodCandidatesTest.java      | 63 ++++++++++++++++++++++
 11 files changed, 364 insertions(+), 3 deletions(-)

diff --git 
a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java 
b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
index c6a5209..d1f4daa 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
@@ -719,9 +719,20 @@ public final class JAXRSUtils {
         int size1 = paraList1.length;
         int size2 = paraList2.length;
         for (int i = 0; i < size1 && i < size2; i++) {
-            int result = 
paraList1[i].getName().compareTo(paraList2[i].getName());
-            if (result != 0) {
-                return result;
+            if (!paraList1[i].equals(paraList2[i])) {
+                // Handling the case when bridge / synthetic methods may be 
taken 
+                // into account (f.e. when service implements generic 
interfaces or
+                // extends the generic classes.
+                if (paraList1[i].isAssignableFrom(paraList2[i])) {
+                    return 1;
+                } else if (paraList2[i].isAssignableFrom(paraList1[i])) {
+                    return -1;
+                } else {
+                    int result = 
paraList1[i].getName().compareTo(paraList2[i].getName());
+                    if (result != 0) {
+                        return result;
+                    }
+                }
             }
         }
         return size1 == size2 ? 0 : size1 < size2 ? -1 : 1;
diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseApi.java 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseApi.java
new file mode 100644
index 0000000..63f3d7d
--- /dev/null
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseApi.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+@Path("/api")
+public class BaseApi {
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    public Response getApi(@Context HttpHeaders headers, @Context UriInfo 
uriInfo, @PathParam("type") String type) {
+        return Response.ok().build();
+    }
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseRequest.java 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseRequest.java
new file mode 100644
index 0000000..dc0334f
--- /dev/null
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseRequest.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+public class BaseRequest {
+    private int requestId;
+
+    public int getRequestId() {
+        return requestId;
+    }
+
+    public void setRequestId(int requestId) {
+        this.requestId = requestId;
+    }
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseResponse.java 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseResponse.java
new file mode 100644
index 0000000..fbe3a49
--- /dev/null
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/BaseResponse.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+public class BaseResponse {
+    private int responseId;
+
+    public int getResponseId() {
+        return responseId;
+    }
+
+    public void setResponseId(int responseId) {
+        this.responseId = responseId;
+    }
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerService.java 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerService.java
new file mode 100644
index 0000000..17e21d0
--- /dev/null
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerService.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+@Consumes(MediaType.TEXT_XML)
+@Produces(MediaType.TEXT_XML)
+public interface CustomerService extends 
GenericService<CustomerServiceRequest, CustomerServiceResponse> {
+    @Override
+    @POST
+    @Path("process")
+    CustomerServiceResponse process(CustomerServiceRequest request);
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceRequest.java
 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceRequest.java
new file mode 100644
index 0000000..40acb14
--- /dev/null
+++ 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceRequest.java
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "CustomerRequest")
+public class CustomerServiceRequest extends BaseRequest {
+    private int customerId;
+
+    public int getCustomerId() {
+        return customerId;
+    }
+
+    public void setCustomerId(int customerId) {
+        this.customerId = customerId;
+    }
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceResource.java
 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceResource.java
new file mode 100644
index 0000000..9be79b7
--- /dev/null
+++ 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceResource.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+public class CustomerServiceResource implements CustomerService {
+    @Override
+    public CustomerServiceResponse process(CustomerServiceRequest request) {
+        CustomerServiceResponse customerServiceResponse = new 
CustomerServiceResponse();
+        customerServiceResponse.setResponseId(request.getRequestId());
+        return customerServiceResponse;
+    }
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceResponse.java
 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceResponse.java
new file mode 100644
index 0000000..1988a41
--- /dev/null
+++ 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomerServiceResponse.java
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+public class CustomerServiceResponse extends BaseResponse {
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomizedApi.java 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomizedApi.java
new file mode 100644
index 0000000..de9c3f8
--- /dev/null
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/CustomizedApi.java
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+import javax.servlet.ServletConfig;
+import javax.ws.rs.GET;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+public class CustomizedApi extends BaseApi {
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON })
+    public Response getApi(@Context ServletConfig config, @Context HttpHeaders 
headers, @Context UriInfo uriInfo,
+            @PathParam("type") String type) {
+        return getApi(headers, uriInfo, type);
+    }
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/GenericService.java 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/GenericService.java
new file mode 100644
index 0000000..4943cef
--- /dev/null
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/GenericService.java
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.cxf.jaxrs;
+
+public interface GenericService<REQ extends BaseRequest, RES extends 
BaseResponse> {
+    RES process(REQ request);
+}
diff --git 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java
 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java
index 946ec80..0a5ea80 100644
--- 
a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java
+++ 
b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/SelectMethodCandidatesTest.java
@@ -21,19 +21,23 @@ package org.apache.cxf.jaxrs;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
+import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
+import javax.servlet.ServletConfig;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
 
 import org.apache.cxf.endpoint.Endpoint;
 import org.apache.cxf.jaxrs.fortest.BookEntity;
@@ -158,6 +162,65 @@ public class SelectMethodCandidatesTest {
         assertNotNull(book);
         assertEquals("The Book", book.getName());
     }
+    
+    @Test
+    public void testFindFromAbstractGenericImpl6() throws Exception {
+        JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean();
+        sf.setResourceClasses(CustomerServiceResource.class);
+
+        sf.create();
+        List<ClassResourceInfo> resources = 
((JAXRSServiceImpl)sf.getService()).getClassResourceInfos();
+        Message m = createMessage();
+        m.put(Message.CONTENT_TYPE, "text/xml");
+
+        MetadataMap<String, String> values = new MetadataMap<>();
+        OperationResourceInfo ori = findTargetResourceClass(resources, m,
+                                                            "/process",
+                                                            "POST",
+                                                            values, "text/xml",
+                                                            
sortMediaTypes("*/*"));
+        assertNotNull(ori);
+        assertEquals("resourceMethod needs to be selected", "process",
+                     ori.getMethodToInvoke().getName());
+
+        String value = 
"<CustomerRequest><customerId>1</customerId><requestId>100</requestId></CustomerRequest>";
+        m.setContent(InputStream.class, new 
ByteArrayInputStream(value.getBytes()));
+        List<Object> params = JAXRSUtils.processParameters(ori, values, m);
+        assertEquals(1, params.size());
+        CustomerServiceRequest request = (CustomerServiceRequest)params.get(0);
+        assertNotNull(request);
+        assertEquals(1, request.getCustomerId());
+        assertEquals(100, request.getRequestId());
+        
+        final Method notSynthetic = 
CustomerServiceResource.class.getMethod("process", 
+            new Class[]{CustomerServiceRequest.class});
+        assertEquals(notSynthetic, ori.getMethodToInvoke());
+    }
+
+    @Test
+    public void testFindOverridesDifferentArguments() throws Exception {
+        JAXRSServiceFactoryBean sf = new JAXRSServiceFactoryBean();
+        sf.setResourceClasses(CustomizedApi.class);
+
+        sf.create();
+        List<ClassResourceInfo> resources = 
((JAXRSServiceImpl)sf.getService()).getClassResourceInfos();
+        Message m = createMessage();
+        m.put(Message.CONTENT_TYPE, "application/json");
+
+        MetadataMap<String, String> values = new MetadataMap<>();
+        OperationResourceInfo ori = findTargetResourceClass(resources, m,
+                                                            "/api",
+                                                            "GET",
+                                                            values, 
"application/json",
+                                                            
sortMediaTypes("*/*"));
+        assertNotNull(ori);
+        assertEquals("resourceMethod needs to be selected", "getApi",
+                     ori.getMethodToInvoke().getName());
+        
+        final Method expected = CustomizedApi.class.getMethod("getApi", 
+            new Class[]{ServletConfig.class, HttpHeaders.class, UriInfo.class, 
String.class});
+        assertEquals(expected, ori.getMethodToInvoke());
+    }
 
     @Test
     public void testFindFromAbstractGenericClass3() throws Exception {

Reply via email to