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

dkulp pushed a commit to branch 3.5.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 23662383f32d75defca89ece23d13afafd268b8d
Author: Andriy Redko <drr...@gmail.com>
AuthorDate: Wed Nov 23 19:41:46 2022 -0500

    CXF-8796: IllegalArgumentException: argument type mismatch with code first 
RPC when parameter omitted
    
    (cherry picked from commit ac2f96db79ae7fb931295d721753cfd9df007d88)
    (cherry picked from commit f95cfdfdf4fd6ecee8132c8dc7f8d8a0f4e1badb)
---
 .../apache/cxf/message/MessageContentsList.java    |  47 +++----
 .../org/apache/cxf/jaxws/body/RPCGreeterImpl.java  |  36 ++++++
 .../apache/cxf/jaxws/body/RpcBodyServerTest.java   | 137 +++++++++++++++++++++
 .../soapbody_rpc_provider/sayHello1Msg.xml         |  33 +++++
 .../soapbody_rpc_provider/sayHelloMsg.xml          |  33 +++++
 .../src/main/resources/wsdl/soapbody_rpc.wsdl      |  80 ++++++++++++
 6 files changed, 335 insertions(+), 31 deletions(-)

diff --git a/core/src/main/java/org/apache/cxf/message/MessageContentsList.java 
b/core/src/main/java/org/apache/cxf/message/MessageContentsList.java
index 31ff1bfe36..4b5cfa46fa 100644
--- a/core/src/main/java/org/apache/cxf/message/MessageContentsList.java
+++ b/core/src/main/java/org/apache/cxf/message/MessageContentsList.java
@@ -21,7 +21,9 @@ package org.apache.cxf.message;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.cxf.helpers.CastUtils;
 import org.apache.cxf.service.model.MessagePartInfo;
@@ -38,6 +40,7 @@ public class MessageContentsList extends ArrayList<Object> {
      */
     public static final Object REMOVED_MARKER = new Object();
     private static final long serialVersionUID = -5780720048950696258L;
+    private final Set<Integer> removed = new HashSet<>();
 
     public MessageContentsList() {
         super(6);
@@ -65,25 +68,32 @@ public class MessageContentsList extends ArrayList<Object> {
     @Override
     public Object set(int idx, Object value) {
         ensureSize(idx);
-        return super.set(idx, value);
+
+        if (value != REMOVED_MARKER) {
+            removed.remove(idx);
+            return super.set(idx, value);
+        } else {
+            removed.add(idx);
+            return super.set(idx, null);
+        }
     }
 
     private void ensureSize(int idx) {
         while (idx >= size()) {
-            add(REMOVED_MARKER);
+            removed.add(size());
+            add(null);
         }
     }
 
     public Object put(MessagePartInfo key, Object value) {
-        ensureSize(key.getIndex());
-        return super.set(key.getIndex(), value);
+        return set(key.getIndex(), value);
     }
 
     public boolean hasValue(MessagePartInfo key) {
         if (key.getIndex() >= size()) {
             return false;
         }
-        return super.get(key.getIndex()) != REMOVED_MARKER;
+        return !removed.contains(key.getIndex());
     }
 
     /**
@@ -92,8 +102,7 @@ public class MessageContentsList extends ArrayList<Object> {
      * is mapped, or {@code null} if mapped element is marked as removed.
      */
     public Object get(MessagePartInfo key) {
-        Object o = super.get(key.getIndex());
-        return o == REMOVED_MARKER ? null : o;
+        return super.get(key.getIndex());
     }
 
     /**
@@ -104,28 +113,4 @@ public class MessageContentsList extends ArrayList<Object> 
{
     public void remove(MessagePartInfo key) {
         put(key, REMOVED_MARKER);
     }
-
-    /**
-     * Allocates a new array containing the elements of the underlying list.
-     *
-     * @return an array containing all the elements of this list which are not
-     * marked as removed and {@code null} instead of those elements which are
-     * marked as removed, producing the same sequence of the elements as when
-     * sequentially iterating through underlying list using {@code get(int)}.
-     *                                                                         
     
-     * @see {@link #get(MessagePartInfo)}
-     */
-    @Override
-    public Object[] toArray() {
-        final int size = size();
-        Object[] array = new Object[size];
-        for (int idx = 0; idx < size; ++idx) {
-            Object o = super.get(idx);
-            if (o != REMOVED_MARKER) {
-                array[idx] = o;
-            }
-        }
-        return array;
-    }
-
 }
diff --git 
a/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/body/RPCGreeterImpl.java 
b/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/body/RPCGreeterImpl.java
new file mode 100644
index 0000000000..9122f834de
--- /dev/null
+++ 
b/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/body/RPCGreeterImpl.java
@@ -0,0 +1,36 @@
+/**
+ * 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.jaxws.body;
+
+import org.apache.body_test.rpc.RPCGreeter;
+
+public class RPCGreeterImpl implements RPCGreeter {
+
+    @Override
+    public String sayHello(String in1, String in2, java.lang.String[] in3) {
+        return "Yes!";
+    }
+
+    @Override
+    public String sayHello1(String in1, int in2, String[] in3) {
+        return "Yes!";
+    }
+
+}
diff --git 
a/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/body/RpcBodyServerTest.java
 
b/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/body/RpcBodyServerTest.java
new file mode 100644
index 0000000000..c20b465e83
--- /dev/null
+++ 
b/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/body/RpcBodyServerTest.java
@@ -0,0 +1,137 @@
+/**
+ * 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.jaxws.body;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.xml.namespace.QName;
+
+import jakarta.xml.soap.MessageFactory;
+import jakarta.xml.soap.SOAPMessage;
+import jakarta.xml.ws.Dispatch;
+import jakarta.xml.ws.Endpoint;
+import jakarta.xml.ws.Service;
+import jakarta.xml.ws.soap.SOAPFaultException;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.jaxws.AbstractJaxWsTest;
+import org.apache.header_test.rpc.SOAPRPCHeaderService;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class RpcBodyServerTest extends AbstractJaxWsTest {
+
+    @Before
+    public void setUp() throws Exception {
+        BusFactory.setDefaultBus(getBus());
+
+        String address = 
"http://localhost:9105/SoapBodyRPCContext/SoapBodyRPCPort";;
+        Endpoint.publish(address, new RPCGreeterImpl());
+    }
+
+    @Test
+    public void testRPCInBodyObject() throws Exception {
+        URL wsdl = getClass().getResource("/wsdl/soapbody_rpc.wsdl");
+        assertNotNull(wsdl);
+
+        SOAPRPCHeaderService service = new SOAPRPCHeaderService(
+                                                                wsdl,
+                                                                new QName(
+                                                                          
"http://apache.org/body_test/rpc";,
+                                                                          
"SOAPRPCBodyService"));
+        assertNotNull(service);
+        Dispatch<SOAPMessage> dispatch = service
+            .createDispatch(new QName("http://apache.org/body_test/rpc";, 
"SoapRPCBodyPort"),
+                    jakarta.xml.soap.SOAPMessage.class, Service.Mode.MESSAGE);
+
+        MessageFactory factory = MessageFactory.newInstance();
+        InputStream is = getClass().getClassLoader()
+            .getResourceAsStream("./soapbody_rpc_provider/sayHelloMsg.xml");
+        SOAPMessage inMessage = factory.createMessage(null, is);
+        SOAPMessage response = dispatch.invoke(inMessage);
+        is.close();
+
+        try (ByteArrayOutputStream bout = new ByteArrayOutputStream()) {
+            response.writeTo(bout);
+            assertTrue(new String(bout.toByteArray()).contains("Yes!"));
+        }
+    }
+
+    /**
+     * When arguments are of primitive type, the invocation fails (since 
'null' 
+     * placeholders could not be converted to primitive ones).
+     */
+    @Test(expected = SOAPFaultException.class)
+    public void testRPCInBodyPrimitive() throws Exception {
+        URL wsdl = getClass().getResource("/wsdl/soapbody_rpc.wsdl");
+        assertNotNull(wsdl);
+
+        SOAPRPCHeaderService service = new SOAPRPCHeaderService(
+                                                                wsdl,
+                                                                new QName(
+                                                                          
"http://apache.org/body_test/rpc";,
+                                                                          
"SOAPRPCBodyService"));
+        assertNotNull(service);
+        Dispatch<SOAPMessage> dispatch = service
+            .createDispatch(new QName("http://apache.org/body_test/rpc";, 
"SoapRPCBodyPort"),
+                    jakarta.xml.soap.SOAPMessage.class, Service.Mode.MESSAGE);
+
+        MessageFactory factory = MessageFactory.newInstance();
+        InputStream is = getClass().getClassLoader()
+            .getResourceAsStream("./soapbody_rpc_provider/sayHello1Msg.xml");
+        SOAPMessage inMessage = factory.createMessage(null, is);
+        dispatch.invoke(inMessage);
+        is.close();
+    }
+
+    @Test
+    public void testRPCInBodyNoArguments() throws Exception {
+        URL wsdl = getClass().getResource("/wsdl/soapbody_rpc.wsdl");
+        assertNotNull(wsdl);
+
+        SOAPRPCHeaderService service = new SOAPRPCHeaderService(
+                                                                wsdl,
+                                                                new QName(
+                                                                          
"http://apache.org/body_test/rpc";,
+                                                                          
"SOAPRPCBodyService"));
+        assertNotNull(service);
+        Dispatch<SOAPMessage> dispatch = service
+            .createDispatch(new QName("http://apache.org/body_test/rpc";, 
"SoapRPCBodyPort"),
+                    jakarta.xml.soap.SOAPMessage.class, Service.Mode.MESSAGE);
+
+        MessageFactory factory = MessageFactory.newInstance();
+        InputStream is = getClass().getClassLoader()
+            .getResourceAsStream("./soapbody_rpc_provider/sayHello2Msg.xml");
+        SOAPMessage inMessage = factory.createMessage(null, is);
+        SOAPMessage response = dispatch.invoke(inMessage);
+        is.close();
+
+        try (ByteArrayOutputStream bout = new ByteArrayOutputStream()) {
+            response.writeTo(bout);
+            assertTrue(new String(bout.toByteArray()).contains("Yes!"));
+        }
+    }
+}
diff --git 
a/rt/frontend/jaxws/src/test/resources/soapbody_rpc_provider/sayHello1Msg.xml 
b/rt/frontend/jaxws/src/test/resources/soapbody_rpc_provider/sayHello1Msg.xml
new file mode 100644
index 0000000000..3ae6ccc5d9
--- /dev/null
+++ 
b/rt/frontend/jaxws/src/test/resources/soapbody_rpc_provider/sayHello1Msg.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:ns1="http://apache.org/body_test/rpc";
+    xmlns:SOAP-ENC = "http://schemas.xmlsoap.org/soap/encoding/";
+    xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance";>
+   <soapenv:Header/>
+   <soapenv:Body>
+      <ns1:sayHello1>
+         <ns1:in1>1</ns1:in1>
+         <ns1:in3>
+             222
+             333
+         </ns1:in3>
+      </ns1:sayHello1>
+   </soapenv:Body>
+</soapenv:Envelope>
diff --git 
a/rt/frontend/jaxws/src/test/resources/soapbody_rpc_provider/sayHelloMsg.xml 
b/rt/frontend/jaxws/src/test/resources/soapbody_rpc_provider/sayHelloMsg.xml
new file mode 100644
index 0000000000..c4280a4f02
--- /dev/null
+++ b/rt/frontend/jaxws/src/test/resources/soapbody_rpc_provider/sayHelloMsg.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:ns1="http://apache.org/body_test/rpc";
+    xmlns:SOAP-ENC = "http://schemas.xmlsoap.org/soap/encoding/";
+    xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance";>
+   <soapenv:Header/>
+   <soapenv:Body>
+      <ns1:sayHello>
+         <ns1:in1>1</ns1:in1>
+         <ns1:in3>
+             222
+             333
+         </ns1:in3>
+      </ns1:sayHello>
+   </soapenv:Body>
+</soapenv:Envelope>
diff --git a/testutils/src/main/resources/wsdl/soapbody_rpc.wsdl 
b/testutils/src/main/resources/wsdl/soapbody_rpc.wsdl
new file mode 100644
index 0000000000..a611cfe1fd
--- /dev/null
+++ b/testutils/src/main/resources/wsdl/soapbody_rpc.wsdl
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<wsdl:definitions xmlns="http://schemas.xmlsoap.org/wsdl/"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"; 
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"; 
xmlns:xformat="http://cxf.apache.org/bindings/xformat"; 
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"; 
xmlns:x1="http://apache.org/body_test/rpc/types"; 
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"; 
xmlns:tns="http://apache.org/body_test/rpc"; 
targetNamespace="http://apache.org/bo [...]
+    <wsdl:types>
+        <schema xmlns="http://www.w3.org/2001/XMLSchema"; 
xmlns:x1="http://apache.org/body_test/rpc/types"; 
targetNamespace="http://apache.org/body_test/rpc/types"; 
elementFormDefault="qualified">
+            <simpleType name="array">
+                <list itemType="string"/>
+            </simpleType>
+        </schema>
+    </wsdl:types>
+    <wsdl:message name="sayHelloRequest">
+        <wsdl:part name="in1" type="xsd:string"/>
+        <wsdl:part name="in2" type="xsd:string"/>
+        <wsdl:part name="in3" type="x1:array"/>
+    </wsdl:message>
+    <wsdl:message name="sayHelloResponse">
+        <wsdl:part name="out" type="xsd:string"/>
+    </wsdl:message>
+    <wsdl:message name="sayHelloRequest1">
+        <wsdl:part name="in1" type="xsd:string"/>
+        <wsdl:part name="in2" type="xsd:int"/>
+        <wsdl:part name="in3" type="x1:array"/>
+    </wsdl:message>
+    <wsdl:message name="sayHelloResponse1">
+        <wsdl:part name="out" type="xsd:string"/>
+    </wsdl:message>
+    <wsdl:portType name="RPCGreeter">
+        <wsdl:operation name="sayHello">
+            <wsdl:input name="sayHelloRequest" message="tns:sayHelloRequest"/>
+            <wsdl:output name="sayHelloResponse" 
message="tns:sayHelloResponse"/>
+        </wsdl:operation>
+        <wsdl:operation name="sayHello1">
+            <wsdl:input name="sayHelloRequest1" 
message="tns:sayHelloRequest1"/>
+            <wsdl:output name="sayHelloResponse1" 
message="tns:sayHelloResponse1"/>
+        </wsdl:operation>
+    </wsdl:portType>
+    <wsdl:binding name="Greeter_SOAPBinding" type="tns:RPCGreeter">
+        <soap:binding style="rpc" 
transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="sayHello">
+            <soap:operation style="rpc" soapAction="sayHello"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+        <wsdl:operation name="sayHello1">
+            <soap:operation style="rpc" soapAction="sayHello"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:service name="SOAPRPCBodyService">
+        <wsdl:port name="SoapRPCBodyPort" binding="tns:Greeter_SOAPBinding">
+            <soap:address 
location="http://localhost:9105/SoapBodyRPCContext/SoapBodyRPCPort"/>
+        </wsdl:port>
+    </wsdl:service>
+</wsdl:definitions>

Reply via email to