java - 如何在 JAXB(Eclipse MOXy) 中标记第 3 方不可变对象(immutable对象)

标签 java jaxb eclipselink moxy

我有三个第 3 方不可变对象(immutable对象)(Foo、Bar、BarFactory)和 binding.xml。 我想在 binding.xml 中标记第 3 方不可变对象(immutable对象), 但是 JAXB 需要零参数构造函数。 在 JAXB 和 MOXy 中编码这些类是不可能的吗?

Foo, Bar, BarFactory, demo codes binding.xml and are below.

package example.bindingfile;

public class Foo{
    public static Foo getInstance(int value1, float value2){
        return new Foo(value1, value2);
    }
    private final int value1;
    private final float value2;
    private Foo(int value1, float value2){
        this.value1 = value1;
        this.value2 = value2;
    }
    public int getValue1(){
        return value1;
    }
    public float getValue2(){
        return value2;
    }
}

package example.bindingfile;
public class Bar{
    private final int value;
    Bar(int value){
        this.value = value;
    }
    public int getValue(){
        return value;
    }
}

package example.bindingfile;
public class BarFactory{
    private BarFactory(){}
    public static Bar getInstance(int value){
        return new Bar(value);
    }
}

binding.xml,自定义的ClassExtractor和demo类如下。

--- 绑定(bind).xml

<?xml version="1.0"?>
    <xml-bindings
    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence/oxm http://www.eclipse.org/eclipselink/xsds/eclipselink_oxm_2_3.xsd"
    version="2.3"
    package-name="example.bindingfile">
    <xml-schema
        namespace="http://www.example.com/bindingfile"
        element-form-default="QUALIFIED"/>
    <java-types>
        <!--
        <java-type name="Foo" xml-accessor-type="FIELD">
            <xml-root-element/>
            <xml-type prop-order="value1 value2"/>
            <java-attributes>
                <xml-element java-attribute="value1" name="val1"/>
                <xml-element java-attribute="value2" name="val2"/>
            </java-attributes>
        </java-type>
        -->
        <java-type name="Bar" xml-accessor-type="PROPERTY">
            <xml-root-element/>
            <!--<xml-java-type-adapter value="example.bindingfile.BarAdapter"/>-->
            <xml-type prop-order="value"/>
            <xml-class-extractor class="example.bindingfile.BarExtractor"/>
            <java-attributes>
                <xml-element java-attribute="value" name="Value"/>
            </java-attributes>
        </java-type>
    </java-types>
</xml-bindings>
package example.bindingfile;

import org.eclipse.persistence.descriptors.ClassExtractor;
import org.eclipse.persistence.descriptors.MethodClassExtractor;
import org.eclipse.persistence.sessions.Record;
import org.eclipse.persistence.sessions.Session;

public class BarExtractor extends MethodClassExtractor{
    public BarExtractor(){}
    @Override public Class extractClassFromRow(Record databaseRow, Session session){
        return BarFactory.class;
    }
    @Override public String getClassExtractionMethodName(){
        return "getInstance";
    }
}
package example.bindingfile;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;

public class Demo{
    public static void main(String[] args) throws Exception{
        Map<String, Object> properties = new HashMap<String, Object>(1);
        List<Object> bindingFileList = new ArrayList<Object>(1);
        bindingFileList.add("example/bindingfile/binding.xml");
        properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, bindingFileList);
        JAXBContext jc = JAXBContext.newInstance(new Class[]{Bar.class}, properties);
    //JAXBContext jc = JAXBContext.newInstance(Bar.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(BarFactory.getInstance(1), System.out);
    }
}

和 example.bindingfile.Demo 抛出异常。

Exception in thread "main" javax.xml.bind.JAXBException: 
Exception Description: The class example.bindingfile.Bar requires a zero argument constructor or a specified factory method.  Note that non-static inner classes do not have zero argument constructors and are not supported.
 - with linked exception:
[Exception [EclipseLink-50001] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.JAXBException
Exception Description: The class example.bindingfile.Bar requires a zero argument constructor or a specified factory method.  Note that non-static inner classes do not have zero argument constructors and are not supported.]
    at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:926)
    at org.eclipse.persistence.jaxb.JAXBContext.<init>(JAXBContext.java:163)
    at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:171)
    at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:158)
    at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:118)
    at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:108)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:248)
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:235)
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:385)
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:637)
    at example.bindingfile.Demo.main(Demo.java:16)
Caused by: Exception [EclipseLink-50001] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.JAXBException
Exception Description: The class example.bindingfile.Bar requires a zero argument constructor or a specified factory method.  Note that non-static inner classes do not have zero argument constructors and are not supported.
    at org.eclipse.persistence.exceptions.JAXBException.factoryMethodOrConstructorRequired(JAXBException.java:142)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.finalizeProperties(AnnotationsProcessor.java:826)
    at org.eclipse.persistence.jaxb.compiler.XMLProcessor.processXML(XMLProcessor.java:412)
    at org.eclipse.persistence.jaxb.compiler.Generator.<init>(Generator.java:145)
    at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:922)
    ... 14 more

最佳答案

目前您可以在 EclipseLink MOXy 中支持不可变对象(immutable对象)(以及所有其他使用 XmlAdapterJAXB (JSR-222) 实现。其中 XmlAdapter 用于在不可变对象(immutable对象)和它的可变版本之间进行转换。

以下增强请求已开放,以在 MOXy 中原生支持多参数构造函数。您可以对此增强功能投上您的一票,以帮助提高它的优先级。

关于java - 如何在 JAXB(Eclipse MOXy) 中标记第 3 方不可变对象(immutable对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14495920/

相关文章:

java - 用 Java 构建 GUI

java - 如何知道使用了什么 JAXB 实现?

java - 我想使用 Java 将子元素插入 xml 树中的子元素

java - JAXB xs :maxLength and minOccurs ="0" didn't show in generated class by xsd

java - 具有 JPA 事务的 JAX-WS Web 服务

Java/JAXB : Unmarshall Xml to specific subclass based on an attribute

java - 从 Spring 框架迁移到 Play 框架 (Scala)

java - apache ant 可变文件类型属性

java - Spring/RMI 服务器错误

hibernate - 使用 JPA 进行哈希分区/分片的库