【问题标题】:NPE when using MOXy's meta data with a class that implements java.util.Map将 MOXy 的元数据与实现 java.util.Map 的类一起使用时的 NPE
【发布时间】:2012-04-09 15:33:59
【问题描述】:

情况

我正在使用 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.<init>(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<clinit>(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.<init>(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<String, Object>{

    public SampleClassA(){
        super();
    }

    public SampleClassA(Map<String, Object> m){
        super(m);
    }

    public void setSomeProperty(String value){
        put("somevalue", value);
    }

    public String getSomeProperty(){
        return (String) get("somevalue");
    }
}

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

<?xml version="1.0"?>
<xml-bindings
  xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
  package-name="com.example"
  xml-mapping-metadata-complete="true"> 
  <java-types>
  <java-type name="SampleClassA" xml-accessor-type="NONE">
   <xml-root-element name="SAMPLE" />
    <java-attributes>
     <xml-attribute type="java.lang.String" name="SomeProperty" required="true">
     <xml-access-methods get-method="getSomeProperty" set-method="setSomeProperty"/>
    </xml-attribute>
   </java-attributes>
  </java-type>
 </java-types>
</xml-bindings>

这是我创建 JAXBContext 的方式

Map<String, Object> props = new HashMap<String, Object>(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 接口。

【问题讨论】:

    标签: java map jaxb moxy


    【解决方案1】:

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

    这是一个非常有趣的用例。 JAXB (JSR-222) 具有映射和域对象的表示,因此考虑混合对象的行为方式很有趣。我添加了以下增强请求以引入对它的支持:


    更新

    我们刚刚完成了这项增强功能的实施。您可以使用 2012 年 4 月 19 日开始的 EclipseLink 2.4.0 夜间下载来试用它,地址如下:

    修复涉及利用super-type 属性来指定超类型以覆盖真正的超类型。 super-type 属性以前仅由我们的 dynamic JAXB 支持人员使用。

    bindings.xml

    <?xml version="1.0"?>
    <xml-bindings 
        xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
        package-name="forum10075634">
        <java-types>
            <java-type name="SampleClassA" super-type="java.lang.Object" xml-accessor-type="NONE">
                <xml-root-element name="SAMPLE" />
                <java-attributes>
                    <xml-attribute java-attribute="someProperty" name="SomeProperty" required="true"/>
                </java-attributes>
            </java-type>
        </java-types>
    </xml-bindings>
    

    委托地图

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

    package forum10075634;
    
    import java.util.*;
    
    public class DelegatedMap<K,V> implements Map<K,V> {
    
        private Map<K,V> map;
    
        public DelegatedMap() {
            map = new HashMap<K,V>();
        }
    
        public DelegatedMap(Map<K,V> 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<java.util.Map.Entry<K, V>> entrySet() {
            return map.entrySet();
        }
    
        public V get(Object key) {
            return map.get(key);
        }
    
        public boolean isEmpty() {
            return map.isEmpty();
        }
    
        public Set<K> keySet() {
            return map.keySet();
        }
    
        public V put(K key, V value) {
            return map.put(key, value);
        }
    
        public void putAll(Map<? extends K, ? extends V> m) {
            map.putAll(m);
        }
    
        public V remove(Object key) {
            return map.remove(key);
        }
    
        public int size() {
            return map.size();
        }
    
        public Collection<V> values() {
            return map.values();
        }
    
    }
    

    SampleClassA

    package forum10075634;
    
    import java.util.Map;
    
    public class SampleClassA extends DelegatedMap<String, Object> {
    
        public SampleClassA() {
            super();
        }
    
        public SampleClassA(Map<String, Object> 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<String, Object> properties = new HashMap<String, Object>(1);
            properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum10075634/bindings.xml");
            JAXBContext jc = JAXBContext.newInstance(new Class[] {SampleClassA.class}, properties);
    
            StringReader xml = new StringReader("<SAMPLE SomeProperty='Foo'/>");
            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
    <?xml version="1.0" encoding="UTF-8"?>
    <SAMPLE SomeProperty="Foo"/>
    

    【讨论】:

    • 感谢您对此进行调查。我现在正在尝试你的建议,我会告诉你进展如何。
    • @Terence - 我给出的建议不起作用,我只是展示了计划修复的配置。
    • 啊,好的。这解释了我遇到的 NPE。我应该更仔细地阅读您的帖子!
    • @Terence - 我们增加了对这个用例的支持。我已经用详细信息和完整示例更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-17
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多