我有三个第 3 方不可变对象(Foo、Bar、BarFactory)和 binding.xml。我想在 binding.xml 中标记第 3 方不可变对象,但 JAXB 需要零参数构造函数。在 JAXB 和 MOXy 中编组这些类是不可能的吗?
Foo、Bar、BarFactory、演示代码 binding.xml 如下。
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 和演示类如下。
--- 绑定.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