You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by em...@apache.org on 2018/08/28 02:46:36 UTC

[cxf] branch 3.1.x-fixes updated: [CXF-7823]:JAXBEncoderDecoder doesn't respect @XmlType's propOrder in Exception class (#439)

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

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


The following commit(s) were added to refs/heads/3.1.x-fixes by this push:
     new ffafc04  [CXF-7823]:JAXBEncoderDecoder doesn't respect @XmlType's propOrder in Exception class (#439)
ffafc04 is described below

commit ffafc04bb9ff15a988b6d0b8dc0943f4c694d3b7
Author: Petr Jurak <pj...@redhat.com>
AuthorDate: Tue Aug 28 02:46:32 2018 +0000

    [CXF-7823]:JAXBEncoderDecoder doesn't respect @XmlType's propOrder in Exception class (#439)
---
 .../org/apache/cxf/jaxb/JAXBEncoderDecoder.java    | 40 ++++++++++++-
 systests/databinding/pom.xml                       |  6 ++
 .../apache/cxf/systest/jaxb/TestServiceTest.java   | 36 ++++++++++-
 .../apache/cxf/systest/jaxb/service/ErrorData.java | 62 +++++++++++++++++++
 .../jaxb/service/PropertyOrderException.java       | 70 ++++++++++++++++++++++
 .../cxf/systest/jaxb/service/TestService.java      |  3 +
 .../cxf/systest/jaxb/service/TestServiceImpl.java  | 17 +++++-
 7 files changed, 229 insertions(+), 5 deletions(-)

diff --git a/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java
index 05ca83c..0b6136c 100644
--- a/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java
+++ b/rt/databinding/jaxb/src/main/java/org/apache/cxf/jaxb/JAXBEncoderDecoder.java
@@ -56,6 +56,7 @@ import javax.xml.bind.annotation.XmlAccessOrder;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorOrder;
 import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.adapters.HexBinaryAdapter;
 import javax.xml.bind.attachment.AttachmentMarshaller;
 import javax.xml.bind.attachment.AttachmentUnmarshaller;
@@ -428,7 +429,28 @@ public final class JAXBEncoderDecoder {
                     }
                 });
             }
-
+            XmlType xmlType = cls.getAnnotation(XmlType.class);
+            if (xmlType != null && xmlType.propOrder().length > 1 && !xmlType.propOrder()[0].isEmpty()) {
+                final List<String> orderList = Arrays.asList(xmlType.propOrder());
+                Collections.sort(combinedMembers, new Comparator<Member>() {
+                    public int compare(Member m1, Member m2) {
+                        String m1Name = getName(m1);
+                        String m2Name = getName(m2);
+                        int m1Index = orderList.indexOf(m1Name);
+                        int m2Index = orderList.indexOf(m2Name);
+                        if (m1Index != -1 && m2Index != -1) {
+                            return m1Index - m2Index;
+                        }
+                        if (m1Index == -1 && m2Index != -1) {
+                            return 1;
+                        }
+                        if (m1Index != -1 && m2Index == -1) {
+                            return -1;
+                        }
+                        return 0;
+                    }
+                });
+            }
             for (Member member : combinedMembers) {
                 if (member instanceof Field) {
                     Field f = (Field)member;
@@ -463,8 +485,20 @@ public final class JAXBEncoderDecoder {
             StaxUtils.close(writer);
         }
     }
-    
-    private static void writeArrayObject(Marshaller marshaller, 
+
+    private static String getName(Member m1) {
+        String m1Name = null;
+        if (m1 instanceof Field) {
+            m1Name = ((Field)m1).getName();
+        } else {
+            int idx = m1.getName().startsWith("get") ? 3 : 2;
+            String name = m1.getName().substring(idx);
+            m1Name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
+        }
+        return m1Name;
+    }
+
+    private static void writeArrayObject(Marshaller marshaller,
                                          Object source,
                                          QName mname,
                                          Object mObj) throws Fault, JAXBException {
diff --git a/systests/databinding/pom.xml b/systests/databinding/pom.xml
index 361c2e0..823734f 100644
--- a/systests/databinding/pom.xml
+++ b/systests/databinding/pom.xml
@@ -185,6 +185,12 @@
             <version>${project.version}</version>
         </dependency>
         <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-features-logging</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>${cxf.servlet-api.group}</groupId>
             <artifactId>${cxf.servlet-api.artifact}</artifactId>
         </dependency>
diff --git a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/TestServiceTest.java b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/TestServiceTest.java
index 8f780b6..97e0230 100644
--- a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/TestServiceTest.java
+++ b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/TestServiceTest.java
@@ -28,9 +28,13 @@ import org.w3c.dom.Document;
 
 import org.apache.cxf.Bus;
 import org.apache.cxf.endpoint.Server;
+import org.apache.cxf.ext.logging.LoggingOutInterceptor;
+import org.apache.cxf.ext.logging.event.LogEvent;
+import org.apache.cxf.ext.logging.event.LogEventSender;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.systest.jaxb.model.ExtendedWidget;
 import org.apache.cxf.systest.jaxb.model.Widget;
+import org.apache.cxf.systest.jaxb.service.PropertyOrderException;
 import org.apache.cxf.systest.jaxb.service.TestService;
 import org.apache.cxf.test.TestUtilities;
 import org.apache.cxf.testutil.common.TestUtil;
@@ -44,7 +48,7 @@ import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
 @ContextConfiguration(locations = { "classpath:extrajaxbclass.xml" })
 public class TestServiceTest extends AbstractJUnit4SpringContextTests {
     static final String PORT = TestUtil.getPortNumber(TestServiceTest.class);
-
+    private static TestLoggingEventSender fault = new TestLoggingEventSender();
     private TestUtilities testUtilities;
 
     public TestServiceTest() {
@@ -73,7 +77,37 @@ public class TestServiceTest extends AbstractJUnit4SpringContextTests {
         Assert.assertEquals(expected, widgetFromService);
     }
 
+    @Test
+    public void testExceptionPropertyOrder() throws Throwable {
+        ((Bus)applicationContext.getBean("cxf")).getOutFaultInterceptors().add(new LoggingOutInterceptor(fault));
+        TestService testClient = getTestClient();
+        ((BindingProvider)testClient).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
+                                                              "http://localhost:" + PORT
+                                                                  + "/service/TestEndpoint");
+        try {
+            testClient.echo("Exception");
+        } catch (PropertyOrderException e) {
+            Assert.assertTrue("Expect <message> element is before <data> element :" + fault.getMessage(),
+                              fault.getMessage().indexOf("</message><data") > -1);
+        }
+    }
+
     
+    static class TestLoggingEventSender implements LogEventSender {
+        private String logMessage;
+
+        public String getMessage() {
+            return logMessage;
+        }
+        public void clearMessage() {
+            logMessage = null;
+        }
+        @Override
+        public void send(LogEvent event) {
+            logMessage = event.getPayload();
+        }
+    }
+
     @Test
     public void testSchema() throws Exception {
         URL url = new URL("http://localhost:" + PORT + "/service/TestService?wsdl");
diff --git a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/ErrorData.java b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/ErrorData.java
new file mode 100644
index 0000000..5fe127f
--- /dev/null
+++ b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/ErrorData.java
@@ -0,0 +1,62 @@
+/**
+ * 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.systest.jaxb.service;
+
+import javax.xml.bind.annotation.XmlType;
+
+@XmlType(name = "ErrorData")
+public class ErrorData implements java.io.Serializable {
+    private static final long serialVersionUID = 1L;
+    private long code;
+    private String title;
+    private String description;
+
+    public ErrorData() {
+    }
+
+    public ErrorData(long code, String title, String description, String stack) {
+        this.code = code;
+        this.title = title;
+        this.description = description;
+    }
+
+    public long getCode() {
+        return code;
+    }
+
+    public void setCode(long code) {
+        this.code = code;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+}
diff --git a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/PropertyOrderException.java b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/PropertyOrderException.java
new file mode 100644
index 0000000..61ee4ce
--- /dev/null
+++ b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/PropertyOrderException.java
@@ -0,0 +1,70 @@
+/**
+ * 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.systest.jaxb.service;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+@XmlRootElement(name = "fault")
+@XmlType(name = "", propOrder = {
+    "message", "data"
+}, namespace = "")
+public class PropertyOrderException extends Exception implements java.io.Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @XmlElement(name = "message", required = true, nillable = true)
+    private String message;
+
+    @XmlElement(name = "data", required = true, nillable = true)
+    private ErrorData data;
+
+    public PropertyOrderException() {
+        this.data = new ErrorData();
+        this.message = null;
+    }
+
+    public PropertyOrderException(ErrorData data) {
+        this.data = data;
+        this.message = null;
+    }
+
+    public PropertyOrderException(String message) {
+        this.data = null;
+        this.message = message;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    public ErrorData getData() {
+        return data;
+    }
+
+    public void setData(ErrorData data) {
+        this.data = data;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+}
diff --git a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/TestService.java b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/TestService.java
index d104f63..7ac2d02 100644
--- a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/TestService.java
+++ b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/TestService.java
@@ -34,5 +34,8 @@ public interface TestService {
     
     @WebMethod
     void testExceptionMarshalling() throws TestServiceException;
+    
+    @WebMethod
+    String echo(String test) throws PropertyOrderException;
 
 }
diff --git a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/TestServiceImpl.java b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/TestServiceImpl.java
index 6ac4216..99823b0 100644
--- a/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/TestServiceImpl.java
+++ b/systests/databinding/src/test/java/org/apache/cxf/systest/jaxb/service/TestServiceImpl.java
@@ -19,6 +19,7 @@
 
 package org.apache.cxf.systest.jaxb.service;
 
+import javax.jws.WebMethod;
 import javax.jws.WebService;
 
 import org.apache.cxf.systest.jaxb.model.ExtendedWidget;
@@ -35,6 +36,20 @@ public class TestServiceImpl implements TestService {
         throw new TestServiceException("Your hovercraft is full of eels.");
     }
 
-    
+    @WebMethod
+    public String echo(String test) throws PropertyOrderException {
+        if ("Exception".equalsIgnoreCase(test)) {
+            PropertyOrderException exception = new PropertyOrderException();
+            ErrorData ed = new ErrorData();
+            ed.setCode(500);
+            ed.setDescription("Error happened");
+            ed.setTitle("Error title");
+            exception.setData(ed);
+            exception.setMessage("Exception message");
+            throw exception;
+
+        }
+        return test;
+    }
 
 }