JAXB Java 7与Java 8的区别 [英] Difference in JAXB Java 7 versus Java 8

查看:82
本文介绍了JAXB Java 7与Java 8的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现在Java 7上处理Jaxb与Java 8之间存在另一个区别。我已将问题简化为简化示例,并且代码应作为单个类运行。 (更改了类别,因此它与非工作相关等)当Unmarshaller调用List的setter时:
我的问题实际上是

I've found another difference between handling Jaxb on Java 7 versus Java 8. I've reduced the issue to a simplified example, and the code should run as a single class. (changed the categories so it's non-work-related etc) When the setter for a List is called by the Unmarshaller: My Question is really a variation of


  1. 编码JaxB时,编码List访问器的推荐做法是否完全省略
    Setter? (因为它似乎通过Getter处理
    列表)

  2. 是否有推荐的替代方法?

在Java 7中运行时,将使用List中的数据调用setter。
在Java 8中运行时,只会使用一个空的List对象调用setter,该对象显然会在解组过程中稍后填充。
我遇到的不同之处在于我不能让setter对List进行任何处理,而是只有在整个对象被解组后才调用的进程。或者总结一下,不要在设置器中进行任何处理。
示例如下:(三个类) - 在Java 7下,返回的结果是列表中第一个在setter中找到的album标题。在Java 8下,返回null。
代码应作为单个类运行,没有依赖项。
如果在Java 7中运行,则显示First Album标题为Abbey Road。
如果在Java 8中运行First Album标题为null

When run in Java 7 the setter will be called with data in the List. When run in Java 8 the setter will be called only with an empty List object which apparently gets populated later in the unmarshalling process. The difference I experience is that I must not have the setter do any processing on the List, but rather have a process that is invoked only after the overall object is unmarshalled. Or to sum it up, "don't do any processing in the setter". Example is below: (Three classes) - Under Java 7 the result returned is the first "album" title on the list as found in the setter. Under Java 8 a null is returned. The code should run as a single class with no dependencies. If run in Java 7 "First Album" title displayed is "Abbey Road". If run in Java 8 "First Album" title is null

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

public class MainJaxbCase {
    public static void main( String[] args ) {
        new MainJaxbCase().testIt();
    }
    private void testIt() {
        try {
        AlbumLib   myLib = (AlbumLib) loadJaxbDocFromString( inXmlStr, AlbumLib.class );
        System.out.println("category:"+ myLib.getCateg());
        List<AlbumItm> albumList = myLib.getAlbumList();
        System.out.println("AlbumList size is " + albumList.size());
        System.out.println("The first album is titled:"
                + myLib.getFirstAlbumTitle() 
                + "- shows \"null\" if using Java 8,  \"Abbey Road\" if using Java 7"
             );
        } catch ( Exception e ) {
            System.out.println( e.getClass().getSimpleName() + ", msg:" + e.getMessage() );
            e.printStackTrace();
        }
    }
    private final String inXmlStr = 
            "<my_lib categ='albums'>"
            + "  <album title='Abbey Road'/> "
            + "  <album title='Revolver'/>"
            + "  <album title='Sgt.Pepper'/>"
            + "</my_lib>";      


    private Object loadJaxbDocFromString ( String inStr, Class<?> clazz ) throws Exception {
        Object result = null;
        try {
            InputStream is = new ByteArrayInputStream( inStr.getBytes() );
            result = unmarshal( is, clazz  );
        } catch ( Exception e ) {
            String msg = this.getClass().getSimpleName() + ".loadJaxbDocFromResource() caught " + e.getClass().getSimpleName() + " msg:" + e.getMessage();
            throw new Exception(msg);
        }
        return result;
    }
    private Object unmarshal( InputStream prmIs, Class<?> clazz ) throws Exception{
        Object obj = null;
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance( clazz );
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            obj = jaxbUnmarshaller.unmarshal( prmIs );
        } catch ( Exception e ) {
            String msg = this.getClass().getSimpleName() + " caught " + 
                    e.getClass().getSimpleName() + ", msg:" + e.getMessage();
            msg += " Trying to Unmarshall class " + clazz.getName();
            System.err.println(msg);
            e.printStackTrace();
            throw new Exception(msg);
        }
        return obj;
    }
}



@XmlRootElement ( name= "my_lib")
class AlbumLib {
    private String      categ;
    private List<AlbumItm> albumList;
    private String firstAlbumTitle;

    @XmlAttribute ( name="categ")
    public String getCateg() {
        return this.categ;
    }
    public void setCateg( String val ) {
        this.categ=val;
    }

    @XmlElement ( name="album")
    public List<AlbumItm> getAlbumList() {
        return this.albumList;
    }
    public void setAlbumList( List<AlbumItm> newList ) {
        if ( newList != null && newList.size() > 0 ) {
            firstAlbumTitle = newList.get(0).getTitle();
        }
        this.albumList = newList;
    }
    public String getFirstAlbumTitle() {
        return this.firstAlbumTitle;
    }
}



@XmlType(name = "album")
class AlbumItm {
    private String title;
    @XmlAttribute ( name="title" )
    public String getTitle() {
        return this.title;
    }
    public void setTitle(String val ) {
        this.title = val;
    }
}

这个问题的出现是因为我们的代码开始表现为切换到Java 8时的微妙(但重要)差异,但没有任何明显的例外。

This question arose because we had code that started behaving with subtle (but important) differences when it was switched to Java 8, but without any obvious exceptions.

推荐答案

我们遇到了同样的问题和你一起,这个博客帖子陈述。

We met the same problem with you, as this blog post stated.



  1. 编码列表访问器的推荐做法是在完全省略Setter时编码JaxB? (因为它似乎通过Getter来处理List)

  2. 是否有推荐的替代方法?


关键是不要省略Setter,而不是为setter添加更多功能。塞特只是二传手,仅此而已。添加更多逻辑违反了setter的单一责任规则,并且该函数的名称与实际完成的内容不同,可能会出现更多错误。

The point is not to 'omit the Setter' but not to add more functionality to setter. Setter is just setter, nothing more. Adding more logic violate the 'single responsibility rule' for setter and the name of this function diff from what it actually done, where more bugs may arise.

当它出现时建议的方法,没有涵盖所有情况的标准答案。考虑到没有构造函数init(这对JAXB来说有点困难)而且我们在setter之后需要更多的逻辑,我们有两个方向你可以采取:

When it comes the recommended ways, there is no standard answer that covers all cases. Considering there exist no constructor init (which is somewhat hard for JAXB to do) and we need more logic after setter, we have two directions which you can take:


  • 使用 XmlAdapter 来自定义构造以添加逻辑:适配器示例;

  • 不在此类中添加任何逻辑,创建另一个类来处理来自xml的数据 - - (这是首选,因为这个类只是一些不应该有逻辑的DTO)

  • Use XmlAdapter to customize the construction to add logic: adapter examples;
  • Not adding any logic in this class, creating another class to process the data from xml -- (this is preferred, as this class is just some DTO which should not have logic)

这篇关于JAXB Java 7与Java 8的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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