草庐IT

java - 为什么 MOXy JAXB 编码为空字符串而 JAXB 引用实现却没有?

coder 2024-07-03 原文

下面显示的 JUnit 测试在使用 MOXy 时失败(在我的环境中),但适用于 JAXB 引用实现。

预期的结果 XML 是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<itemManager>
    <items>
        <value>2</value>
    </items>
</itemManager>

但打开 MOXy - jaxb.properties 包含:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

生成的 XML 字符串为空。

这种行为的原因可能是什么,需要采取什么措施来解决?

我已尝试使用 EclipseLink MOXy 版本 2.5.1 和 2.4.2 - 请参阅下面的 pom.xml 片段。依赖项是 pom.xml 中的第一个,然后是许多其他依赖项(这可能也破坏了展示)。

<!-- Eclipselink moxy -->
<dependency>
  <groupId>org.eclipse.persistence</groupId>
  <artifactId>org.eclipse.persistence.moxy</artifactId>
  <version>2.4.2</version> 
  <!--  <version>2.5.1</version>   -->
  <scope>test</scope>
</dependency>

JUnit测试的Java代码:

package com.bitplan.storage.moxy;

import static org.junit.Assert.*;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import org.junit.Test;

/**
 * show problem with empty xml result for Jaxb Marshaller
 * 
 * @author wf
 * 
 */
public class TestEmptyXml {

    public interface Copyable<T> {
        /**
         * copy me from the copyable
         * 
         * @param othe
         *          - the source copyaqble to copy from
         */
        public void copyFrom(T other);
    }

    public interface BO<BO_T> extends Copyable<BO_T> {

    }

    public interface ItemInterface {

    }

    @XmlRootElement
    public static class Item implements ItemInterface {
        int value;

        /**
         * @return the value
         */
        public int getValue() {
            return value;
        }

        /**
         * @param value
         *          the value to set
         */
        public void setValue(int value) {
            this.value = value;
        }

        public Item() {

        }

        public Item(int pValue) {
            value = pValue;
        }

    }

    public interface ItemManagerInterface {
        public void setItems(List<Item> pItems);

        public List<Item> getItems();
    }

    public interface MoxyList<BO_T> extends Collection<BO_T> {

    }

    public interface MoxyManager<BO_T> extends MoxyList<BO_T> {
    }

    public static class MoxyManagerImpl<BO_T> implements MoxyManager<BO_T> {
        public transient List<BO_T> bolist = new ArrayList<BO_T>();

        @Override
        public boolean add(BO_T arg0) {
            boolean result = bolist.add(arg0);
            return result;
        }

        @Override
        public boolean addAll(Collection<? extends BO_T> arg0) {
            boolean result = bolist.addAll(arg0);
            return result;
        }

        @Override
        public void clear() {
            bolist.clear();
        }

        @Override
        public boolean contains(Object arg0) {
            boolean result = bolist.contains(arg0);
            return result;
        }

        @Override
        public boolean containsAll(Collection<?> arg0) {
            boolean result = bolist.containsAll(arg0);
            return result;
        }

        @Override
        public boolean isEmpty() {
            boolean result = bolist.isEmpty();
            return result;
        }

        @Override
        public Iterator<BO_T> iterator() {
            Iterator<BO_T> result = bolist.iterator();
            return result;
        }

        @Override
        public boolean remove(Object arg0) {
            boolean result = bolist.remove(arg0);
            return result;
        }

        @Override
        public boolean removeAll(Collection<?> arg0) {
            boolean result = bolist.removeAll(arg0);
            return result;
        }

        @Override
        public boolean retainAll(Collection<?> arg0) {
            boolean result = bolist.retainAll(arg0);
            return result;
        }

        @Override
        public int size() {
            int result = bolist.size();
            return result;
        }

        @Override
        public Object[] toArray() {
            Object[] result = bolist.toArray();
            return result;
        }

        @Override
        public <T> T[] toArray(T[] arg0) {
            T[] result = bolist.toArray(arg0);
            return result;
        }

    }

    @XmlAccessorType(XmlAccessType.NONE)
    @XmlTransient
    public static abstract class MyMoxyManager<BO_T> extends
            MoxyManagerImpl<BO_T> {
        public abstract Class<? extends BO<?>> getEntityType();

    }

    @XmlRootElement
    public static class ItemManager extends MyMoxyManager<Item> implements
            ItemManagerInterface {
        public ItemManager() {

        }

        private List<Item> items = new ArrayList<Item>();

        @Override
        @XmlElement
        public void setItems(List<Item> pItems) {
            items = pItems;
        }

        @Override
        public List<Item> getItems() {
            return items;
        }

        @SuppressWarnings("unchecked")
        @Override
        public Class<? extends BO<?>> getEntityType() {
            return (Class<? extends BO<?>>) Item.class;
        }
    }

    /**
     * convert the target to XML Format
     * 
     * @param target
     * @return
     * @throws Exception
     */
    public String asXML(Object target) throws Exception {
        JAXBContext jaxbContext = JAXBContext.newInstance(target.getClass());
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
        // output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        StringWriter sw = new StringWriter();
        jaxbMarshaller.marshal(target, sw);
        String result = sw.toString();
        return result;
    }

    @Test
    public void testMarshall() throws Exception {
        ItemManager im = new ItemManager();
        im.items.add(new Item(2));
        String xml = asXML(im);
        System.out.println(xml);
        assertNotEquals("xml should not be empty", "", xml);
    }

}

最佳答案

在您的示例中,正在编码的 target 参数是 ItemManager 的一个实例。由于以下类组织,MOXy 最终认为 ItemManager 是一个集合而不是域对象,这就是奇怪的事情发生的原因。

  • ItemManager -extends-> MyMoxyManager
  • MyMoxyManager -extends-> MoxyManagerImpl
  • MoxyManagerImpl -实现-> MoxyManager
  • MoxyManager -extends-> MoxyList
  • MoxyList -extends-> 集合

我仍然需要研究这个用例的正确行为应该是什么。您能否继续为这个问题打开一个错误。

关于java - 为什么 MOXy JAXB 编码为空字符串而 JAXB 引用实现却没有?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19347743/

有关java - 为什么 MOXy JAXB 编码为空字符串而 JAXB 引用实现却没有?的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  5. ruby-on-rails - unicode 字符串的长度 - 2

    在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

  6. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  7. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  8. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  9. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  10. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

随机推荐