当前位置: 首页 > 知识库问答 >
问题:

通过将集合从JDK 1.7升级到JDK 1.8 u05,破坏了JAXB配置

童花蜂
2023-03-14

下面的代码过去是在JDK 1.7使用的JAXB实现下工作的,但现在在JDK 1.8下它被破坏了。在下面的代码中,您将发现关键的更改,它似乎在1.8中起作用。1.8下的“修复”并不是真正的修复,因为公开内部集合供外部世界直接修改是一种不好的做法。我想通过我的类来控制对内部列表的访问,我不想通过创建可观察的集合并聆听它们来使事情复杂化。这是不可接受的。

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

 @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并直接修改集合。这带来了几个问题:

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

共有1个答案

宗政鸿志
2023-03-14

当集合属性在JAXB中映射时,它首先检查getter以查看集合属性是否已预初始化。在下面的示例中,我希望将我的属性公开为List

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

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

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

要调用setter,您只需要在对象的新实例上让getter返回null。您的代码可能如下所示:

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);
    }

}

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

@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);
    }

}

 类似资料:
  • 测试使用Jetty服务器周围的包装器作为连接到的主机。对于主机和客户端来说,truststore和keystore是相同的。出于某种原因,从2.5到2.6的更改导致服务器提前关闭。 我唯一要改变的是maven中的OkHttp版本从2.5到2.6。测试类在这里(实现在TestInvokeHttpCommon中):https://github.com/apache/nifi/blob/8c2323dc

  • null 04:52:42.738警告:没有为分析源文件提供依赖项的字节码,最终可能会得到不太精确的结果。可以使用sonar.java.Libraries属性提供字节码

  • 我刚刚升级了我的android studio,它破坏了我的颤振构建过程。我现在在尝试构建以前工作过的项目时遇到了这个错误。我的andriod studio设置在最后。非常感谢您的帮助。 失败:构建失败,有一个异常。 出错原因: 任务执行失败:应用程序:processDebugMainManifest 无法使字段私有化。字符串java。木卫一。文件路径可访问:模块java。base不会将java.i

  • 我们公司让我们从Oracle WebLogic 12.1.3升级到12.2.1.4,因为12.1.3失去支持/即将失去支持。 我们有一个主要的应用程序,它使用Spring Framework v3.0.2。当我们将EAR部署到12.2.1.4并尝试使用任何web服务时,我们会得到这个错误堆栈跟踪。我已经删除了使用通用名称指定我们公司的名称,但您应该能够了解发生的事情的要点: 2021-06-02

  • 我最近通过从源代码编译在CentOS机器上安装了Python 2.7.3。Python 2.7.3安装在/opt/python2.7上,当我安装它时,我只需更改/usr/bin/Python以指向新版本。这显然是错误的,因为当我这样做的时候,它打破了百胜。我会得到以下内容。 我更改了/usr/bin/python以指向python 2.6.6,但现在2.6.6是python的默认版本。你知道怎么解

  • 我正在将我的django项目从1.8升级到2.2.0(使用virtualenv中的Python 3.6)。我做了以下更改。 将on_delete添加到所有外键字段 将url反向导入更改为来自django。URL反向导入 在所有应用程序的url文件中包含路径/re_path而不是url 将设置文件中的MIDDLEWARE_CLASSES导入更改为MIDDLEWARE={} 我试图运行服务器,但它仍然