MOXy:JAXBElement的高效深度拷贝

MOXy:JAXBElement的高效深度拷贝,jaxb,eclipselink,moxy,docx4j,Jaxb,Eclipselink,Moxy,Docx4j,docx4j v3.3.0使用以下代码克隆JAXB对象: public static <T> T deepCopy(T value, JAXBContext jc) { if (value==null) { throw new IllegalArgumentException("Can't clone a null argument"); } try { @SuppressWarnings("unchecked")

docx4j v3.3.0使用以下代码克隆JAXB对象:

    public static <T> T deepCopy(T value, JAXBContext jc) {

    if (value==null) {
        throw new IllegalArgumentException("Can't clone a null argument");
    }

    try {
        @SuppressWarnings("unchecked")
        Class<T> clazz = (Class<T>) value.getClass();
        JAXBElement<T> contentObject = new JAXBElement<T>(new QName(clazz.getSimpleName()), clazz, value);
        JAXBSource source = new JAXBSource(jc, contentObject);
        JAXBElement<T> elem = jc.createUnmarshaller().unmarshal(source, clazz);

        T res;
        if (value instanceof JAXBElement<?>) {
            @SuppressWarnings("unchecked")
            T resT = (T) elem;
            res = resT;
        } else {
            @SuppressWarnings("unchecked")
            T resT = (T) elem.getValue();
            res = resT;
        }

        return res;
    } catch (JAXBException ex) {
        throw new IllegalArgumentException(ex);
    }
}
我们可以通过以下方式解决此问题:

        JAXBElement<T> elem; 

        if (Context.getJaxbImplementation().equals(JAXBImplementation.ECLIPSELINK_MOXy)
                && value instanceof JAXBElement<?>) {

            elem = (JAXBElement<T>) value;
            Class<?> valueClass = elem.getDeclaredType();

            Marshaller mar = jc.createMarshaller();
            ByteArrayOutputStream bout = new ByteArrayOutputStream(256);
            mar.marshal(elem, bout);

            Unmarshaller unmar = jc.createUnmarshaller();
            elem = (JAXBElement<T>)unmar.unmarshal(new StreamSource(new ByteArrayInputStream(
                    bout.toByteArray())), valueClass);

        }
JAXBElement元素;
if(Context.getJaxbImplementation().equals(JAXBImplementation.ECLIPSELINK_MOXy)
&&JAXBELENT的值实例){
elem=(JAXBElement)值;
Class valueClass=elem.getDeclaredType();
Marshaller mar=jc.createMarshaller();
ByteArrayOutputStream bout=新的ByteArrayOutputStream(256);
三月元帅(埃伦,布特);
Unmarshaller unmar=jc.createUnmarshaller();
elem=(JAXBElement)unmar.unmarshal(新的StreamSource(新的ByteArrayInputStream(
toByteArray()),valueClass);
}

但是有更好的方法吗?

免责声明:我是这篇文章的作者,其中包括我认为非常适合这项任务的
可复制插件

您可能对可复制插件感兴趣,它生成无反射的策略复制方法

在Maven中激活(另请参见):


可能看起来有点奇怪/麻烦,但它考虑了相当多的JAXB特性。

免责声明:我是这篇文章的作者,其中包括
可复制插件,我认为它非常适合这项任务

您可能对可复制插件感兴趣,它生成无反射的策略复制方法

在Maven中激活(另请参见):


可能看起来有点奇怪/麻烦,但它考虑了相当多的JAXB特性。

结果表明,在复制JAXBElement时引入的docx4j代码存在问题,无论是使用MOXy还是Sun/Oracle引用实现


修复了它

发现在中引入的docx4j代码在复制JAXBElement时出现问题,无论是使用MOXy还是Sun/Oracle参考实现


修复它

谢谢您的帮助。iirc,我在过去尝试同时使用多个扩展时遇到了麻烦。docx4j为此使用父指针插件。iirc,我在过去尝试同时使用多个扩展时遇到了麻烦。docx4j使用父指针插件
    [Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.XMLMarshalException
    Exception Description: A descriptor for class javax.xml.bind.JAXBElement was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.]
        at org.eclipse.persistence.jaxb.JAXBUnmarshaller.handleXMLMarshalException(JAXBUnmarshaller.java:980)
        at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:303)
        at org.docx4j.XmlUtils.deepCopy(XmlUtils.java:974)
        ... 25 more
    Caused by: Exception [EclipseLink-25007] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.XMLMarshalException
    Exception Description: A descriptor for class javax.xml.bind.JAXBElement was not found in the project.  For JAXB, if the JAXBContext was bootstrapped using TypeMappingInfo[] you must call a marshal method that accepts TypeMappingInfo as an input parameter.
        at org.eclipse.persistence.exceptions.XMLMarshalException.descriptorNotFoundInProject(XMLMarshalException.java:140)
        at org.eclipse.persistence.internal.oxm.Context$ContextState.getSession(Context.java:145)
        at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:795)
        at org.eclipse.persistence.oxm.XMLContext$XMLContextState.getSession(XMLContext.java:1)
        at org.eclipse.persistence.internal.oxm.Context.getSession(Context.java:466)
        at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:364)
        at org.eclipse.persistence.oxm.XMLContext.getSession(XMLContext.java:1)
        at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:466)
        at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:695)
        at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:655)
        at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:301)
        ... 26 more
        JAXBElement<T> elem; 

        if (Context.getJaxbImplementation().equals(JAXBImplementation.ECLIPSELINK_MOXy)
                && value instanceof JAXBElement<?>) {

            elem = (JAXBElement<T>) value;
            Class<?> valueClass = elem.getDeclaredType();

            Marshaller mar = jc.createMarshaller();
            ByteArrayOutputStream bout = new ByteArrayOutputStream(256);
            mar.marshal(elem, bout);

            Unmarshaller unmar = jc.createUnmarshaller();
            elem = (JAXBElement<T>)unmar.unmarshal(new StreamSource(new ByteArrayInputStream(
                    bout.toByteArray())), valueClass);

        }
        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <configuration>
                <extension>true</extension>
                <args>
                    <arg>-Xcopyable</arg>
                </args>
                <plugins>
                    <plugin>
                        <groupId>org.jvnet.jaxb2_commons</groupId>
                        <artifactId>jaxb2-basics</artifactId>
                    </plugin>
                </plugins>
            </configuration>
        </plugin>
public Object clone() {
    return copyTo(createNewInstance());
}

public Object copyTo(Object target) {
    final CopyStrategy2 strategy = JAXBCopyStrategy.INSTANCE;
    return copyTo(null, target, strategy);
}

public Object copyTo(ObjectLocator locator, Object target, CopyStrategy2 strategy) {
    final Object draftCopy = ((target == null)?createNewInstance():target);
    if (draftCopy instanceof IssueJIIB35) {
        final IssueJIIB35 copy = ((IssueJIIB35) draftCopy);
        {
            Boolean nameShouldBeCopiedAndSet = strategy.shouldBeCopiedAndSet(locator, this.isSetName());
            if (nameShouldBeCopiedAndSet == Boolean.TRUE) {
                String sourceName;
                sourceName = this.getName();
                String copyName = ((String) strategy.copy(LocatorUtils.property(locator, "name", sourceName), sourceName, this.isSetName()));
                copy.setName(copyName);
            } else {
                if (nameShouldBeCopiedAndSet == Boolean.FALSE) {
                    copy.name = null;
                }
            }
        }
        // ...
    }
    return draftCopy;
}

public Object createNewInstance() {
    return new IssueJIIB35();
}