我在 jaxb technology 从事金融行业项目。开发了一个 Web 服务消费部分并陷入了客户端报告的问题。我的日期类型的 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 类本身甚至没有到达服务层时给出异常。
任何解决问题的建议都是值得赞赏的。
谢谢。
最佳答案
基础问题
空 String
不是 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 提供者。在您使用 MOXy 的版本中,当遇到严重性为 ERROR
的 ValidationEvent
而不是像引用实现那样的 FATAL_ERROR
时,默认情况下会抛出异常.这已在以下错误中得到修复:
变通
如果您直接使用 JAXB API,您可以简单地覆盖默认的 ValidationEventHandler
。在 JAX-WS 环境中,XmlAdapter
可用于提供自定义转换逻辑。我们将利用 XmlAdapter
来覆盖如何处理与 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 模型(根)
使用 @XmlJavaTypeAdapter
注释引用 XmlAdapter
。如果您希望此 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
字段被编码为不存在的元素(请参阅: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>
关于java - SOAP UI 中 JAXB 中的空白非强制日期字段问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18617998/