多模块Java/Maven项目中dbunit的XML DTD的路径?
题
我有一个多模块的Maven项目。在Persist模块中,我有许多XML文件数据文件,这些数据文件引用DTD:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "myapp-data.dtd" >
<dataset>
.....omitted for brevity....
</dataset>
DTD与XML文件一起存储在同一目录中,甚至Eclipse将这些XML文件报告为有效。
但是,当我运行应用程序时,dbunit flatxmldataset会引发fileNotfound异常,因为它无法找到DTD。显然,它正在寻找根项目目录(例如myproject/)中的DTD。我本可以预期它会在与XML文件本身相同的目录中查找DTD(例如myproject/persist/target/test-data)。
查看dbunit源代码,它可以说:“相对Doctype URI是根据当前的工作双晶型解决的。”
解决此问题的好方法是什么?
解决方案
好的,我想我弄清楚了。谢天谢地,开源。
FlatxMldatAtaSetBuilder上有一种方法,该方法将流到达DTD。这是一个公共方法IMO真是太疯狂了,但是话又说回来,Dbunit看起来与DTD文件的XML相同的目录是疯狂的。所以这里是:
String dtdResourceName = "classpath:test-data/myapp-data.dtd";
Resource res = applicationContext.getResource(dtdResourceName);
builder.setMetaDataSetFromDtd(res.getInputStream());
现在,我将DTD与XML相同的目录保留在DTD的目录中,并使用此技巧来欺骗Dbunit做正确的事。
其他提示
始终使用正确的变量访问特殊目录,因为多模块构建的工作目录与本地构建不同:
所以
- 代替
mydir
利用${project.basedir}/mydir
- 代替
target/mydir
利用${project.build.directory}/mydir
- 代替
target/classes/mydir
利用${project.build.outputDirectory}/mydir
这些变量始终对当前项目进行评估,无论其何处。这是一个 POM变量的概述 (不完整,但最重要的东西在那里)
另外,如果您想进行一些交互式查询风格的调试, 帮助:评估Mojo 派上用场:
只是打电话
mvn help:evaluate
并会提示您表达表达。如果您输入表达式 ${project.build.plugins[0]}
,将列出指定元素的合并DOM
编辑:
好的,现在我想我看到了问题。那么,为什么不只是在XML中引用目录:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myapp-data SYSTEM "target/test-classes/myapp-data.dtd" >
我知道这不是很漂亮,但是应该有效,是否可以使用多模块。单位测试的当前目录始终是当前$ {project.basedir},而不是父级项目dir。
您可以将DTD发布到Web服务器,然后将其HTTP URL放入Doctype,例如:
<!DOCTYPE myapp-data SYSTEM "-//The Owner//The Description//EN" "http://host/path/to/myapp-data.dtd">
打开XML文件时,请尝试使用“文件”而不是“ fileInputStream”。
例如:
ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new File(fileName)));
这样,DTD的相对路径应从XML文件的目录开始。
如果您使用
ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new FileInputStream(fileName)));
路径应相对于当前的工作目录。
它涉及一些丑陋的重复,但是您可以将DTD的内容粘贴到相关的XML文件中,然后将其用作 内部DTD.