将MOXy的元数据与实现java.util.Map的类一起使用时的NPE

情况

我正在使用EclipseLink的MOXy,我正在尝试将外部OX映射XML与实现Map接口的类一起使用。 但是,每次我尝试创建一个JAXBContext时,我都会得到以下NPE:

Caused by: javax.xml.bind.JAXBException - with linked exception: [java.lang.NullPointerException] at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:832) at org.eclipse.persistence.jaxb.JAXBContext.(JAXBContext.java:143) at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:142) at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:129) at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:93) at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:83) at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:210) at javax.xml.bind.ContextFinder.find(ContextFinder.java:336) at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574) at com.example.MOXyOXTest(MOXyOXTest.java:59) Caused by: java.lang.NullPointerException at org.eclipse.persistence.jaxb.compiler.XMLProcessor.processXML(XMLProcessor.java:202) at org.eclipse.persistence.jaxb.compiler.Generator.(Generator.java:145) at org.eclipse.persistence.jaxb.JAXBContext$TypeMappingInfoInput.createContextState(JAXBContext.java:829) 

细节

如果要映射的类实现java.util.Map接口,则只会出现此问题。 如果我映射的类没有实现该接口,那么一切正常。 这是我试图映射的类的简化示例:

 package com.example; import java.util.Map; // This class just wraps a java.util.HashMap import com.xetus.lib.type.DelegatedMap; public class SampleClassA extends DelegatedMap{ public SampleClassA(){ super(); } public SampleClassA(Map m){ super(m); } public void setSomeProperty(String value){ put("somevalue", value); } public String getSomeProperty(){ return (String) get("somevalue"); } } 

以下是我想要使用的MOXy OX元数据的简化示例:

              

这是我如何创建我的JAXBContext

 Map props = new HashMap(1); List bindings = new ArrayList(1); bindings.add(new StreamSource(MOXyOXTest.class.getResourceAsStream("test-mappings.xml"))); props.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, bindings); cntxt = JAXBContext.newInstance(new Class[] { SampleClassA.class }, props); 

我正在使用EclipseLink版本2.3.2,以防这很重要。 我也试过版本2.2.1,结果相同。

我的问题

这是我第一次尝试在实现java.util.Map接口的类上使用JAXB,我很好奇我是否遗漏了一些基本的东西。 我不希望OX映射使用Map的名称/值对,而是将自定义的getter和setter添加到类中。

这样的配置应该有效吗?

额外细节

  1. 示例代码中使用的DelegatedMap不扩展 java.util.HashMap,它只包装一个实例并实现Map接口。 此外,该类使用@XmlAccessorType(XmlAccessType.NONE)进行注释。
  2. 无论实现我用于SampleClassA的Map接口的哪个抽象类,我都会得到相同的错误。 如果SampleClassA扩展了一个没有实现映射的类,那么一切都行为正常。
  3. 我正在使用的代码库需要许多类来实现Map接口。

注意:我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员。

这是一个非常有趣的用例。 JAXB(JSR-222)具有地图和域对象的表示,因此有必要考虑混合对象应该如何表现。 我添加了以下增强请求以引入对它的支持:


UPDATE

我们刚刚完成了这项增强function。 您可以在2012年4月19日从以下位置使用EclipseLink 2.4.0每夜下载开始尝试:

该修复涉及利用super-type属性来指定超类型以覆盖真正的超类型。 以前只有我们的动态JAXB支持才能利用super-type属性。

bindings.xml

            

DelegatedMap

下面是您问题中描述的DelegatatedMap类的实现。

 package forum10075634; import java.util.*; public class DelegatedMap implements Map { private Map map; public DelegatedMap() { map = new HashMap(); } public DelegatedMap(Map map) { this.map = map; } public void clear() { map.clear(); } public boolean containsKey(Object key) { return map.containsKey(key); } public boolean containsValue(Object value) { return map.containsValue(value); } public Set> entrySet() { return map.entrySet(); } public V get(Object key) { return map.get(key); } public boolean isEmpty() { return map.isEmpty(); } public Set keySet() { return map.keySet(); } public V put(K key, V value) { return map.put(key, value); } public void putAll(Map m) { map.putAll(m); } public V remove(Object key) { return map.remove(key); } public int size() { return map.size(); } public Collection values() { return map.values(); } } 

SampleClassA

 package forum10075634; import java.util.Map; public class SampleClassA extends DelegatedMap { public SampleClassA() { super(); } public SampleClassA(Map m) { super(m); } public void setSomeProperty(String value) { put("somevalue", value); } public String getSomeProperty() { return (String) get("somevalue"); } } 

jaxb.properties

要将MOXy指定为JAXB提供程序,您需要在与域类相同的包中添加名为jaxb.properties的文件,并使用以下条目:

 javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

演示

 package forum10075634; import java.io.StringReader; 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 properties = new HashMap(1); properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum10075634/bindings.xml"); JAXBContext jc = JAXBContext.newInstance(new Class[] {SampleClassA.class}, properties); StringReader xml = new StringReader(""); Unmarshaller unmarshaller = jc.createUnmarshaller(); SampleClassA sampleClassA = (SampleClassA) unmarshaller.unmarshal(xml); System.out.println(sampleClassA.getSomeProperty()); System.out.println(sampleClassA.get("somevalue")); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(sampleClassA, System.out); } } 

产量

 Foo Foo