通过从JDK 1.7升级到JDK 1.8 u05集合来破解JAXB配置 [英] JAXB Configuration was broken by upgrading from JDK 1.7 to JDK 1.8 u05 for collections

查看:245
本文介绍了通过从JDK 1.7升级到JDK 1.8 u05集合来破解JAXB配置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码用于在JDK 1.7使用的JAXB实现下工作,但是现在在JDK 1.8下它已经坏了。在下面的代码中,您将找到似乎使其在1.8中工作的关键更改。 1.8下的修复并不是一个真正的修复,因为暴露内部集合以供外界直接修改是不好的做法。我想通过我的类来控制对内部列表的访问,我不想通过创建可观察的集合并听取它们来使事情变得复杂。这是不可接受的。

The code below used to work under the JAXB implementation used by JDK 1.7, but now under JDK 1.8 it's broken. In the code below you will find the key change that seems to make it work in 1.8. The "fix" under 1.8 is not really a fix because it's bad practice to expose internal collections for direct modification by the outside world. I want to control access to the internal list through my class and I don't want to complicate things by making observable collections and listening to them. This is not acceptable.

有没有办法让我的原始代码在JD 1.8的JAXB下工作?

Is there any way to get my original code to work under the JAXB of JD 1.8?

 @XmlElementWrapper(name = "Wrap")
   @XmlElement(name = "Item", required = true)
   public synchronized void setList(List<CustomObject> values) {
     list.clear();
     list.addAll(values);
   }

public synchronized List<CustomObject> getList() {
//      return new ArrayList(list); // this was the original code that worked under 1.7
      return list; //this is the only thing that works under 1.8
   }

经过更多分析后,问题似乎来自JAXB不再调用集合的setter方法(它曾经在JDK 1.7下使用)。现在在JDK 1.8下,它调用getter并直接修改集合。这带来了几个问题:

After more analysis, the problem seems to be coming from JAXB not calling the setter method for collections anymore (it used to under JDK 1.7). Now under JDK 1.8, it calls the getter and modifies the collection directly. This poses several problems:

1 - 强制用户向外界公开内部集合以进行免费修改(不良做法)
2 - 不是允许用户在列表更改时执行任何自定义代码(例如,如果调用setter,您可以执行此操作)。有可能创建一个可观察的集合并听取它,但这是一个比调用setter方法更复杂的解决方法。

1-forces the user to expose an internal collection to the outside world for free modification (bad practice) 2-doesn't allow the user to do any custom code when the list changes (such as what you could do if the setter was called). It might be possible to make an observable collection and listen to it, but this is a much more complicated workaround than just calling the setter method.

推荐答案

背景



当在JAXB中映射集合属性时,它首先检查getter以查看集合属性是否已预先初始化。在下面的示例中,我希望将我的属性公开为 List< String> ,但支持实现为 LinkedList 准备持有1000个项目。

Background

When a collection property is mapped in JAXB it first checks the getter to see if the collection property has been pre-initialized. In the example below I want to have my property exposed as List<String>, but have the backing implementation be a LinkedList ready to hold 1000 items.

private List<String> foos = new LinkedList<String>(1000);

@XmlElement(name="foo")
public List<String> getFoos() {
    return foos;
}



为什么你的代码曾经工作



如果以前让JAXB调用映射到从getter返回非null响应的集合的属性上的setter,则该JAXB实现中存在错误。您的代码也不应该在以前的版本中有效。

Why Your Code Used to Work

If you previously had JAXB call the setter on a property mapped to a collection that returned a non-null response from the getter, then there was a bug in that JAXB implementation. Your code should not have worked in the previous version either.

要拥有调用你的setter只需要让你的getter在对象的新实例上返回null。您的代码可能类似于:

To have the setter called you just need to have your getter return null, on a new instance of the object. Your code could look something like:

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement(name = "Foo")
public class Foo {

    private List<CustomObject> list = null;

    @XmlElementWrapper(name = "Wrap")
    @XmlElement(name = "Item", required = true)
    public synchronized void setList(List<CustomObject> values) {
        if (null == list) {
            list = new ArrayList<CustomObject>();
        } else {
            list.clear();
        }
        list.addAll(values);
    }

    public synchronized List<CustomObject> getList() {
        if (null == list) {
            return null;
        }
        return new ArrayList(list);
    }

}






UPDATE



如果您不需要对从JAXB解组返回的List执行任何逻辑,那么使用字段访问可能是一种可接受的解决方案。


UPDATE

If you don't need to perform any logic on the List returned from JAXB's unmarshalling then using field access may be an acceptable solution.

@XmlRootElement(name = "Foo")
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {

    @XmlElementWrapper(name = "Wrap")
    @XmlElement(name = "Item", required = true)
    private List<CustomObject> list = null;

    public synchronized void setList(List<CustomObject> values) {
        if(null == list) {
            list = new ArrayList<CustomObject>();
        } else {
            list.clear();
        }
        list.addAll(values);
    }

    public synchronized List<CustomObject> getList() {
        return new ArrayList(list);
    }

}

这篇关于通过从JDK 1.7升级到JDK 1.8 u05集合来破解JAXB配置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆