我正在使用jaxb进行应用程序配置
我觉得我正在做一些非常歪曲的事情,我正在寻找一种不需要实际文件或此交易的方法。
正如您在代码I中看到的那样:
1.从我的JaxbContext(实际上来自我的类注释)创建一个模式到一个文件 2.设置此模式文件,以便在我解组时允许进行真正的验证
JAXBContext context = JAXBContext.newInstance(clazz);
Schema mySchema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(schemaFile);
jaxbContext.generateSchema(new MySchemaOutputResolver()); // ultimately creates schemaFile
Unmarshaller u = m_context.createUnmarshaller();
u.setSchema(mySchema);
u.unmarshal(...);
你们是否知道如何在不需要创建计算机中的模式文件的情况下验证jaxb?
我是否需要创建用于验证的模式,当我通过JaxbContect.generateSchema获取它时看起来多余?
你是怎么做到的?
答案 0 :(得分:13)
关于上面的ekeren解决方案,在单个线程中使用PipedOutputStream / PipedInputStream不是一个好主意,以免溢出缓冲区并导致死锁。 ByteArrayOutputStream / ByteArrayInputStream有效,但如果您的JAXB类生成多个模式(在不同的名称空间中),则需要多个StreamSource。
我最终得到了这个:
JAXBContext jc = JAXBContext.newInstance(Something.class);
final List<ByteArrayOutputStream> outs = new ArrayList<ByteArrayOutputStream>();
jc.generateSchema(new SchemaOutputResolver(){
@Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
outs.add(out);
StreamResult streamResult = new StreamResult(out);
streamResult.setSystemId("");
return streamResult;
}});
StreamSource[] sources = new StreamSource[outs.size()];
for (int i=0; i<outs.size(); i++) {
ByteArrayOutputStream out = outs.get(i);
// to examine schema: System.out.append(new String(out.toByteArray()));
sources[i] = new StreamSource(new ByteArrayInputStream(out.toByteArray()),"");
}
SchemaFactory sf = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
m.setSchema(sf.newSchema(sources));
m.marshal(docs, new DefaultHandler()); // performs the schema validation
答案 1 :(得分:2)
我遇到了确切的问题,并在Apache Axis 2源代码中找到了解决方案:
protected List<DOMResult> generateJaxbSchemas(JAXBContext context) throws IOException {
final List<DOMResult> results = new ArrayList<DOMResult>();
context.generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(String ns, String file) throws IOException {
DOMResult result = new DOMResult();
result.setSystemId(file);
results.add(result);
return result;
}
});
return results;
}
并且在获得表示模式的DOMResults列表之后,您需要将它们转换为DOMSource对象,然后才能将它们提供给模式生成器。第二步可能如下所示:
Unmarshaller u = myJAXBContext.createUnmarshaller();
List<DOMSource> dsList = new ArrayList<DOMSource>();
for(DOMResult domresult : myDomList){
dsList.add(new DOMSource(domresult.getNode()));
}
String schemaLang = "http://www.w3.org/2001/XMLSchema";
SchemaFactory sFactory = SchemaFactory.newInstance(schemaLang);
Schema schema = sFactory.newSchema((DOMSource[]) dsList.toArray(new DOMSource[0]));
u.setSchema(schema);
答案 2 :(得分:1)
我相信你只需要在你的unmarshaller上设置一个ValidationEventHandler
。像这样:
public class JAXBValidator extends ValidationEventCollector {
@Override
public boolean handleEvent(ValidationEvent event) {
if (event.getSeverity() == event.ERROR ||
event.getSeverity() == event.FATAL_ERROR)
{
ValidationEventLocator locator = event.getLocator();
// change RuntimeException to something more appropriate
throw new RuntimeException("XML Validation Exception: " +
event.getMessage() + " at row: " + locator.getLineNumber() +
" column: " + locator.getColumnNumber());
}
return true;
}
}
在您的代码中:
Unmarshaller u = m_context.createUnmarshaller();
u.setEventHandler(new JAXBValidator());
u.unmarshal(...);
答案 3 :(得分:0)
如果你使用maven使用jaxb2-maven-plugin可以帮到你。它在生成资源阶段生成模式。