Author: ningjiang Date: Sat Oct 8 10:00:53 2011 New Revision: 1180345 URL: http://svn.apache.org/viewvc?rev=1180345&view=rev Log: CAMEL-4480 RuntimeCamelException "Ambiguous Parameter Mapping" must not be thrown, if there are parameters of the same type but with different QNames in ServiceInterfaceStrategy
Modified: camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/MethodInfo.java camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/ServiceInterfaceStrategy.java camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCustomerServiceImpl.java camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCxfServerTest.java camel/trunk/components/camel-soap/src/test/resources/org/apache/camel/dataformat/soap/MultiPartCustomerService.wsdl Modified: camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/MethodInfo.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/MethodInfo.java?rev=1180345&r1=1180344&r2=1180345&view=diff ============================================================================== --- camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/MethodInfo.java (original) +++ camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/MethodInfo.java Sat Oct 8 10:00:53 2011 @@ -19,6 +19,8 @@ package org.apache.camel.dataformat.soap import java.util.HashMap; import java.util.Map; +import org.apache.camel.RuntimeCamelException; + /** * Value object to hold information about a method in a JAX-WS service interface. * Method can have many parameters in the signature, but only one response object. @@ -49,6 +51,15 @@ public final class MethodInfo { this.inTypeMap = new HashMap<String, TypeInfo>(); for (int i = 0; i < in.length; i++) { + TypeInfo ti = in[i]; + if (inTypeMap.containsKey(ti.getTypeName()) + && (!(ti.getTypeName().equals("javax.xml.ws.Holder"))) + && (!(inTypeMap.get(ti.getTypeName()).equals(ti.getElName())))) { + throw new RuntimeCamelException("Ambiguous QName mapping. The type [ " + + ti.getTypeName() + + " ] is already mapped to a QName in this method." + + " This is not supported."); + } inTypeMap.put(in[i].getTypeName(), in[i]); } } Modified: camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/ServiceInterfaceStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/ServiceInterfaceStrategy.java?rev=1180345&r1=1180344&r2=1180345&view=diff ============================================================================== --- camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/ServiceInterfaceStrategy.java (original) +++ camel/trunk/components/camel-soap/src/main/java/org/apache/camel/dataformat/soap/name/ServiceInterfaceStrategy.java Sat Oct 8 10:00:53 2011 @@ -34,11 +34,15 @@ import javax.xml.ws.WebFault; import org.apache.camel.RuntimeCamelException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Offers a finder for a webservice interface to determine the QName of a * webservice data element */ public class ServiceInterfaceStrategy implements ElementNameStrategy { + private static final transient Logger LOG = LoggerFactory.getLogger(ServiceInterfaceStrategy.class); private Map<String, MethodInfo> soapActionToMethodInfo = new HashMap<String, MethodInfo>(); private Map<String, QName> inTypeNameToQName = new HashMap<String, QName>(); private Map<String, QName> outTypeNameToQName = new HashMap<String, QName>(); @@ -85,7 +89,6 @@ public class ServiceInterfaceStrategy im } } - @SuppressWarnings("rawtypes") private List<TypeInfo> getInInfo(Method method) { List<TypeInfo> typeInfos = new ArrayList<TypeInfo>(); RequestWrapper requestWrapper = method.getAnnotation(RequestWrapper.class); @@ -160,9 +163,10 @@ public class ServiceInterfaceStrategy im if (inTypeNameToQName.containsKey(ti.getTypeName()) && (!(ti.getTypeName().equals("javax.xml.ws.Holder"))) && (!(inTypeNameToQName.get(ti.getTypeName()).equals(ti.getElName())))) { - throw new RuntimeCamelException("Ambiguous parameter mapping. The type [ " + LOG.warn("Ambiguous QName mapping. The type [ " + ti.getTypeName() + " ] is already mapped to a QName in this context."); + continue; } inTypeNameToQName.put(ti.getTypeName(), ti.getElName()); } Modified: camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCustomerServiceImpl.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCustomerServiceImpl.java?rev=1180345&r1=1180344&r2=1180345&view=diff ============================================================================== --- camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCustomerServiceImpl.java (original) +++ camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCustomerServiceImpl.java Sat Oct 8 10:00:53 2011 @@ -64,7 +64,6 @@ public class MultiPartCustomerServiceImp company.value = returnCompany; lastSavedCustomer = parameters.getCustomer(); - } @Override @@ -84,4 +83,24 @@ public class MultiPartCustomerServiceImp return lastSavedCustomer; } + @Override + public void saveCustomerToo(SaveCustomer parameters, Product product, + Holder<Company> company) { + if (product == null) { + throw new IllegalArgumentException("product may not be null."); + } + + if (company == null) { + throw new IllegalArgumentException("company may not be null."); + } + + Company returnCompany = new Company(); + returnCompany.setName("MultipartSoft"); + returnCompany.setPresident("Dr. Multipart"); + + company.value = returnCompany; + + lastSavedCustomer = parameters.getCustomer(); + } + } Modified: camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCxfServerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCxfServerTest.java?rev=1180345&r1=1180344&r2=1180345&view=diff ============================================================================== --- camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCxfServerTest.java (original) +++ camel/trunk/components/camel-soap/src/test/java/org/apache/camel/dataformat/soap/MultiPartCxfServerTest.java Sat Oct 8 10:00:53 2011 @@ -143,4 +143,51 @@ public class MultiPartCxfServerTest exte assertTrue(((Company)companyHeaderObj).getName().equals("MultipartSoft")); } + /** + * This test validates the end-to-end behavior of the service interface mapping when a parameter type + * is defined with a different QName in two different Web method. It also tests the case where a + * QName and type are directly reused across methods. + */ + @Test + public void testSendRequestWithReusedInAndInOutParts() throws Exception { + + Exchange exchange = producerTemplate.send("direct:start", new Processor() { + + public void process(Exchange exchange) throws Exception { + BeanInvocation beanInvocation = new BeanInvocation(); + + beanInvocation.setMethod(MultiPartCustomerService.class.getMethod("saveCustomerToo", + SaveCustomer.class, Product.class, Holder.class)); + + Customer customer = new Customer(); + customer.setName("TestCustomerToo"); + customer.setRevenue(50000); + SaveCustomer saveCustomer = new SaveCustomer(); + saveCustomer.setCustomer(customer); + + Product product = new Product(); + product.setName("Multiuse Product"); + product.setDescription("Useful for lots of things."); + + Holder<Company> holder = new Holder<Company>(); + + Object[] args = new Object[] {saveCustomer, product, holder}; + beanInvocation.setArgs(args); + exchange.getIn().setBody(beanInvocation); + } + + }); + + if (exchange.getException() != null) { + throw exchange.getException(); + } + + @SuppressWarnings("unchecked") + List<Object> headers = (List<Object>) exchange.getOut().getHeader(SoapJaxbDataFormat.SOAP_UNMARSHALLED_HEADER_LIST); + assertTrue(headers.size() == 1); + Object companyHeaderObj = headers.get(0); + assertTrue(companyHeaderObj instanceof Company); + assertTrue(((Company)companyHeaderObj).getName().equals("MultipartSoft")); + } + } Modified: camel/trunk/components/camel-soap/src/test/resources/org/apache/camel/dataformat/soap/MultiPartCustomerService.wsdl URL: http://svn.apache.org/viewvc/camel/trunk/components/camel-soap/src/test/resources/org/apache/camel/dataformat/soap/MultiPartCustomerService.wsdl?rev=1180345&r1=1180344&r2=1180345&view=diff ============================================================================== --- camel/trunk/components/camel-soap/src/test/resources/org/apache/camel/dataformat/soap/MultiPartCustomerService.wsdl (original) +++ camel/trunk/components/camel-soap/src/test/resources/org/apache/camel/dataformat/soap/MultiPartCustomerService.wsdl Sat Oct 8 10:00:53 2011 @@ -62,6 +62,10 @@ <xs:element name="saveCustomer" type="tns:saveCustomer"> </xs:element> + + <!-- This element reuses the tns:SaveCustomer type, but applies a different element QName (than above) --> + <xs:element name="saveCustomerToo" type="tns:saveCustomer"> + </xs:element> <xs:complexType name="saveCustomer"> <xs:sequence> <xs:element name="customer" type="tns:customer"></xs:element> @@ -116,18 +120,27 @@ <wsdl:part name="parameters" element="typens:getAllCustomersResponse"/> <wsdl:part name="companyType" element="typens:companyType"/> </wsdl:message> - + <!-- multiple in parts and an inout --> <wsdl:message name="saveCustomer"> <wsdl:part name="parameters" element="typens:saveCustomer"/> <wsdl:part name="product" element="typens:product"/> - <wsdl:part name="company" element="typens:company"/> + <wsdl:part name="company" element="typens:company"/> </wsdl:message> <wsdl:message name="saveCustomerResponse"> <wsdl:part name="company" element="typens:company"/> - </wsdl:message> - - + </wsdl:message> + + <wsdl:message name="saveCustomerToo"> + <wsdl:part name="parameters" element="typens:saveCustomerToo"/> + <wsdl:part name="product" element="typens:product"/> + <wsdl:part name="company" element="typens:company"/> + </wsdl:message> + <wsdl:message name="saveCustomerResponseToo"> + <wsdl:part name="company" element="typens:company"/> + </wsdl:message> + + <!-- message with an out part --> <wsdl:portType name="MultiPartCustomerService"> <wsdl:operation name="getCustomersByName"> <wsdl:input name="getCustomersByName" message="tns:getCustomersByName"/> @@ -142,8 +155,12 @@ <wsdl:input message="tns:saveCustomer"/> <wsdl:output message="tns:saveCustomerResponse"/> </wsdl:operation> + <wsdl:operation name="saveCustomerToo"> + <wsdl:input message="tns:saveCustomerToo"/> + <wsdl:output name="saveCustomerResponseToo" message="tns:saveCustomerResponseToo"/> + </wsdl:operation> </wsdl:portType> - + <wsdl:binding name="CustomerServiceMultiPart" type="tns:MultiPartCustomerService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> @@ -172,7 +189,7 @@ <soap:body use="literal" /> </wsdl:output> </wsdl:operation> - + <!-- operation with two header values in request - one is an inout --> <wsdl:operation name="saveCustomer"> <soap:operation soapAction="http://multipart.customerservice.example.com/saveCustomer" /> @@ -185,7 +202,22 @@ <soap:header use="literal" part="company" message="tns:saveCustomer" /> <soap:body use="literal" /> </wsdl:output> - </wsdl:operation> + </wsdl:operation> + + <!-- operation to test reused parameters and a parameters that reuses a type but applies a new namespace --> + <wsdl:operation name="saveCustomerToo"> + <soap:operation soapAction="http://multipart.customerservice.example.com/saveCustomerToo" /> + <wsdl:input> + <soap:header use="literal" part="product" message="tns:saveCustomerToo" /> + <soap:header use="literal" part="company" message="tns:saveCustomerToo" /> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output name="saveCustomerResponseToo"> + <soap:header use="literal" part="company" message="tns:saveCustomerToo" /> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding>