2

我正在从事 jaxb 技术的金融部门项目。开发了一个 Web 服务消费部分并陷入了一个问题 BEEN REPORTED FROM CLIENT END。我的日期类型的 bean 类中有两个字段,如下所示

 @XmlElement(name = "abc")
    @XmlSchemaType(name = "date")
    private Date abc;

    @XmlElement(name = "qwe")
    @XmlSchemaType(name = "date")
    private Date qwe;

现在,当这些字段没有数据时,它会给出异常这些字段也不是强制性的,按照公历日历按照注释标签采用 yyyy-mm-dd 中的日期。使用 SOAP UI 在本地完成测试时的请求

            </data>
               <!--Optional:-->
               <abc></qwe>
               <!--Optional:-->
               <qwe></qwe>
            </data>


Exception Description: The object [], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[abc-->abc/text()]] with descriptor [XMLDescriptor(fully qualified package name --> [])], could not be converted to [class java.util.Calendar].

这两个字段的情况相同,并且当日期仅以预期格式填写时效果很好。

我不知道如何通过标签或任何其他方式正确处理此问题,因为它在 bean 类本身给出异常甚至没有到达服务层。

任何解决问题的建议都是值得赞赏的。

谢谢。

4

1 回答 1

0

基本问题

EmptyString不是该类型的有效值xsd:date。为了对 XML 模式有效,可选元素应表示为不存在的节点。,


为什么基本问题会影响您

所有 JAXB 实现都将认识到空String不是xsd:date. 他们通过将其报告给ValidationEventHandler. 您可以通过执行以下操作自己查看:

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    unmarshaller.setEventHandler(new ValidationEventHandler() {

        @Override
        public boolean handleEvent(ValidationEvent event) {
            System.out.println(event);
            return true;
        }
    });

您正在使用的 JAX-WS 实现利用EclipseLink MOXy作为 JAXB 提供者。ValidationEvent在您使用 MOXy 的版本中,默认情况下,当遇到严重性时会抛出异常,ERROR而不是FATAL_ERROR像参考实现那样。这已在以下错误中得到修复:


解决问题

如果您直接使用 JAXB API,您可以简单地覆盖默认的ValidationEventHandler. 在 JAX-WS 环境中,aXmlAdapter可用于提供自定义转换逻辑。我们将利用 anXmlAdapter来覆盖转换到/从Date的处理方式。

XmlAdapter (日期适配器)

import java.text.SimpleDateFormat;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateAdapter extends XmlAdapter<String, Date>{

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Date unmarshal(String v) throws Exception {
        if(v.length() == 0) {
            return null;
        }
        return dateFormat.parse(v);
    }

    @Override
    public String marshal(Date v) throws Exception {
        if(null == v) {
            return null;
        }
        return dateFormat.format(v);
    }

}

Java 模型(根)

使用注解XmlAdapter引用。@XmlJavaTypeAdapter如果您希望这XmlAdapter适用于Date您可以在包级别注册它的所有实例(请参阅: http ://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html )。

import java.util.Date;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlSchemaType(name = "date")
    @XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
    private Date abc;

    @XmlSchemaType(name="date")
    @XmlJavaTypeAdapter(value=DateAdapter.class, type=Date.class)
    private Date qwe;

}

演示代码

下面是一个独立的示例,您可以运行它来查看一切正常。

jaxb.properties

在一个使用 MOXy 作为 JAXB 提供程序的独立示例中,您需要包含一个jaxb.propeties在与域模型相同的包中调用的文件,其中包含以下条目(请参阅: http ://blog.bdoughan.com/2011/05/specifying-eclipselink -moxy-as-your.html)。

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

输入.xml

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <abc></abc>
    <qwe>2013-09-05</qwe>
</root>

演示

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Root.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum18617998/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

输出

请注意,在编组的 XML 中Date,为 null 的字段被编组为不存在的元素(请参阅:http ://blog.bdoughan.com/2012/04/binding-to-json-xml-handling-null.html )。

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <qwe>2013-09-05</qwe>
</root>
于 2013-09-05T14:24:50.480 回答