当前位置: 首页 > 面试题库 >

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

石思淼
2023-03-14
问题内容

情况

我正在使用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
Mappings与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)具有地图和域对象的表示形式,因此有必要考虑一下混合对象的行为。我添加了以下增强请求以引入对此的支持:

  • http://bugs.eclipse.org/37640

更新

我们刚刚完成了此增强功能。您可以使用EclipseLink 2.4.0每晚下载,从2012年4月19日开始在以下位置进行尝试:

  • http://www.eclipse.org/eclipselink/downloads/nightly.php

该修复程序涉及利用该super-type属性指定超级类型以覆盖实际超级类型。该super- type属性以前仅由我们的动态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"/>


 类似资料:
  • 有什么方法可以说服MOXy使用私有的XMLAdapter,还是我只能使用公有的?当然,我已经通读了文档,并尝试在谷歌上寻找解决方案,但没有任何东西跳出来。

  • 我有一个使用Amplify(使用AppSync API和Cognito)制作的工作应用程序。我想制作另一个不同的应用程序,但与我的第一个项目共享一些数据(相同的产品,但不同的目标、用法和安全规则)。 有没有一种干净的方法可以在新项目中使用Amplify,告诉GraphQLAPI从我的第一个Amplify项目中获取DynamoDB中的一些数据? 这些数据会经常变化,而且会很重——所以我不太喜欢任何同

  • 我有一个带有Spring(5.7.2)Web/Security的REST API项目。 我只有一个表,它包含一个id和一个名称。 当我删除光盘时,我的DiscsService会 当我需要插入或更新时,我会: 我了解到,当您希望在同一事务中使用值(提交之前)时,将使用,并且将同步并清空SQL缓存。 在我的例子中,我看到我在数据库中插入/更新或删除了值。 我应该使用flush()(我认为不应该),但可

  • 问题内容: 默认情况下,Hibernate 5不支持PostgreSQL 数据类型。 有什么方法可以实现对Hibernate + Spring JPA的支持? 如果有办法,与Hibernate一起使用的利弊是什么? 问题答案: 感谢Vlad Mihalcea我们有这样的机会!) 他创建了hibernate类型的 lib: 这为Hibernate添加了对’json’,’jsonb’和其他类型的支持:

  • 问题内容: 我正在尝试将React-redux与Typescript一起使用,当我尝试使用connect()和mapStateToProps注入道具时遇到类型错误。 我的组件如下所示: 商店看起来像这样 最后,我将类型定义为: 当我尝试编译代码时,出现以下错误: 有趣的是,即使代码抛出类型错误,它仍然可以正常工作。同样,将组件的prop接口更改为any也可以解决该问题。似乎类型系统无法理解这两个映

  • 我想知道如何使用 Spark SQL 来处理存储在关系数据库中的结构化大数据?我的表格包含超过 40 亿条线(GPS 坐标)。在使用合并操作时,Spark尝试处理内存中的整个表,这是不可能的。我知道 Spark 是“内存中”处理,但就我而言,内存无法容纳整个表。那么,当表很大时,是否可以在关系数据库中使用 spark?