无法使用 Dozzer Mapper 将自定义对象复制到 Apache-CXF 生成的对象

Unable to copy custom Object to Apache-CXF generated Object using Dozzer Mapper

我正在使用 Apache CXF (org.apache.cxf) maven 插件来自动生成 Java 文件 (wsdl2java) 并希望将业务逻辑生成的响应对象复制到Apache CXF 使用 Dozer 映射器自动生成的文件。但是 Dozer 映射器无法将列表对象从源复制到目标,因为列表的 setter 方法不是使用 CXF 插件生成的。

XSD 文件:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://com/test/ram/webservices/customer" targetNamespace="http://com/test/ram/webservices/customer" elementFormDefault="qualified">
    <xs:element name="customerRequest" type="tns:customerRequestType" />
    <xs:complexType name="customerRequestType">
            <xs:sequence>
                <xs:element name="CustomerID"                   type="xs:string"          minOccurs="1" />
            </xs:sequence>
    </xs:complexType>
    <xs:element name="customerResponse" type="tns:customerResponseType" />
    <xs:complexType name="customerResponseType">
        <xs:sequence>
            <xs:element name="TemplateList"                                       minOccurs="1"  maxOccurs="1">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="Template"          type="xs:string"     minOccurs="0" maxOccurs="unbounded" >
                            <xs:annotation>
                                <xs:documentation>
                                        TemplateList.
                                </xs:documentation>
                            </xs:annotation>
                        </xs:element>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>   
</xs:schema>

pom.xml

org.apache.cxf plugin to generate wsdl2java

自定义客户class:

public class customerResponse {   
    private customerResponse.TemplateList templateList;

    public customerResponse .TemplateList getTemplateList() {
        return templateList;
    }

    public void setTemplateList(customerResponse .TemplateList value) {
        this.templateList = value;
    }

    public static class TemplateList {
        private List<String> template;

        public List<String> getTemplate() {
            if (template == null) {
                template = new ArrayList<String>();
            }
            return this.template;
        }

        public void setTemplate(List<String> tmp) {
            template=tmp
        }
    }
}

CXF 插件自动生成的 CustomerResponse 对象

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "customerResponse", propOrder = {
    "templateList"
})
public class customerResponse {
    @XmlElement(name = "TemplateList", required = true)
    protected customerResponse.TemplateList templateList;

    public customerResponse .TemplateList getTemplateList() {
        return templateList;
    }

    public void setTemplateList(customerResponse .TemplateList value) {
        this.templateList = value;
    }


    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "template"
    })
    public static class TemplateList {

        @XmlElement(name = "Template")
        protected List<String> template;

        public List<String> getTemplate() {
            if (template == null) {
                template = new ArrayList<String>();
            }
            return this.template;
        }

    }
}

Dozer 映射程序无法复制模板列表。

customerResponse response = dozerMapper.map(customerResponse, customerResponse.class);

那么,在自动生成的 java class 中没有 setter 方法的情况下,有没有办法使用 Dozer 映射器复制列表对象?

您可以使用生成 setter 方法的 JAXB2 Setters 插件。

插件由 -Xsetters 命令行选项激活。 您还可以使用 -Xsetters-mode=accessor-Xsetters-mode=direct 选项来配置生成模式。

参考下面的maven示例来配置这个插件

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version><!-- Current version --></version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <args>
            <arg>-XtoString</arg>
            <arg>-Xequals</arg>
            <arg>-XhashCode</arg>
            <arg>-Xcopyable</arg>
            <arg>-Xmergeable</arg>
        </args>
        <plugins>
            <plugin>
                <groupId>org.jvnet.jaxb2_commons</groupId>
                <artifactId>jaxb2-basics</artifactId>
                <version><!-- Current version --></version>
            </plugin>
        </plugins>
    </configuration>
</plugin>

还要在 pom.xml 中添加以下依赖项,因为生成的代码依赖于它。

<dependency>
        <groupId>org.jvnet.jaxb2_commons</groupId>
        <artifactId>jaxb2-basics-runtime</artifactId>
        <version><!-- Current version --></version>
</dependency>

参考这个 link for more help. Also, there is a user guide 可能会有帮助。

我从参考文献 Link 得到了解决方案,现在我可以看到生成的 java class 有 setter 列表方法。

 https://gist.github.com/meiwin/2779731
 https://github.com/highsource/hyperjaxb3-support/issues/4

pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>moc.scodma.tsacmoc.mra</groupId>
        <artifactId>mra</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <artifactId>mra-messaging-schema</artifactId>


    <properties>
        <src.generated.dir>src/main/java</src.generated.dir>
        <artifact.cxf.version>3.1.6</artifact.cxf.version>
        <xerces.version>2.11.0</xerces.version>
        <inbound.wsdl>src/main/resources/wsdl/inbound/tsacmocService.wsdl</inbound.wsdl>
        <inbound.wsdl.location>classpath:resources/wsdl/inbound/tsacmocService.wsdl</inbound.wsdl.location>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.cxf.xjc-utils</groupId>
            <artifactId>cxf-xjc-runtime</artifactId>
            <version>3.0.5</version>
        </dependency>
    </dependencies>

    <build>

        <plugins>
            <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>${artifact.cxf.version}</version>
                <executions>
                    <execution>
                        <id>generate-sources</id>
                        <phase>generate-sources</phase>
                        <configuration>
                            <sourceRoot>${src.generated.dir}</sourceRoot>
                            <defaultOptions>
                                <noAddressBinding>true</noAddressBinding>
                                <faultSerialVersionUID>3105839350746982386</faultSerialVersionUID>
                            </defaultOptions>
                            <wsdlOptions>
                                <wsdlOption>
                                    <wsdl>${inbound.wsdl}</wsdl>
                                    <wsdlLocation>${inbound.wsdl.location}</wsdlLocation>
                                    <serviceName>mraService</serviceName>
                                    <extraargs>
                                        <extraarg>-xjc-Xts</extraarg>
                                        <extraarg>-xjc-Xcollection-setter-injector</extraarg>
                                        <extraarg>-client</extraarg>
                                        <extraarg>-verbose</extraarg>
                                        <extraarg>-p</extraarg>
                                        <extraarg>http://tsacmoc.ent.moc/mra/=moc.ent.tsacmoc.mra</extraarg>
                                        <extraarg>-p</extraarg>
                                        <extraarg>http://tsacmoc.ent.moc/mocmonheader/=moc.ent.tsacmoc.mocmonheader</extraarg>
                                    </extraargs>
                                </wsdlOption>
                            </wsdlOptions>
                        </configuration>
                        <goals>
                            <goal>wsdl2java</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>xerces</groupId>
                        <artifactId>xercesImpl</artifactId>
                        <version>${xerces.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.apache.cxf.xjcplugins</groupId>
                        <artifactId>cxf-xjc-ts</artifactId>
                        <version>3.0.5</version>
                    </dependency>
                    <dependency>
                            <groupId>net.java.dev.vcc.thirdparty</groupId>
                            <artifactId>collection-setter-injector</artifactId>
                            <version>0.5.0-1</version>
                    </dependency>
                    <dependency>
                        <groupId>moc.sun.xml.bind</groupId>
                        <artifactId>jaxb-xjc</artifactId>
                        <version>2.1.8</version>
                    </dependency>
                    <dependency>
                        <groupId>moc.sun.xml.bind</groupId>
                        <artifactId>jaxb-impl</artifactId>
                        <version>2.1.8</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
</project>

java :

@XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "template"
    })
    public static class TemplateList {

        @XmlElement(name = "Template")
        protected List<String> template;

        /**
         * Gets the value of the template property.
         * 
         * <p>
         * This accessor method returns a reference to the live list,
         * not a snapshot. Therefore any modification you make to the
         * returned list will be present inside the JAXB object.
         * This is why there is not a <CODE>set</CODE> method for the template property.
         * 
         * <p>
         * For example, to add a new item, do as follows:
         * <pre>
         *    getTemplate().add(newItem);
         * </pre>
         * 
         * 
         * <p>
         * Objects of the following type(s) are allowed in the list
         * {@link String }
         * 
         * 
         */
        public List<String> getTemplate() {
            if (template == null) {
                template = new ArrayList<String>();
            }
            return this.template;
        }

        /**
         * Sets the value of the template property.
         * 
         * @param template
         *     allowed object is
         *     {@link String }
         *     
         */
        public void setTemplate(List<String> template) {
            this.template = template;
        }

    }