2010-06-10 54 views
8

我有一个多模块maven项目。内坚持模块我有很多的引用DTD的XML文件中的数据文件:多模块Java/Maven项目中用于DBUnit的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从当前工作dicrectory解析”。

解决这个问题的好方法是什么?

回答

8

好吧,我想我想出了这一个。谢天谢地,开源。

FlatXmlDataSetBuilder上有一个将流传送给DTD的方法。这真是疯了,这是一个公共方法IMO,但是再一次,它的疯狂之处在于DBUnit不会像dtd文件的XML那样查看相同的目录。所以在这里,它是:

String dtdResourceName = "classpath:test-data/myapp-data.dtd";  
Resource res = applicationContext.getResource(dtdResourceName); 
builder.setMetaDataSetFromDtd(res.getInputStream()); 

现在我离开DOCTYPE声明与DTD在同一目录中的XML,并使用这个技巧来愚弄DBUnit的去做正确的事情。

+0

你使用的是什么版本?我在这里找不到这个代码:http://dbunit.sourceforge.net/xref/org/dbunit/dataset/xml/FlatXmlDataSetBuilder.html – 2010-06-13 09:49:17

+0

它在你提供的链接中...检查第195行 - 很难找到其实。 http://dbunit.sourceforge.net/xref/org/dbunit/dataset/xml/FlatXmlDataSetBuilder.html#195 – HDave 2010-06-13 21:40:55

3

始终使用正确的变量来访问特殊目录,因为多模块构建有不同的工作目录比本地编译:

所以

  • ,而不是mydir使用${project.basedir}/mydir
  • ,而不是target/mydir使用${project.build.directory}/mydir
  • 而不是target/classes/mydir使用${project.build.outputDirectory}/mydir

这些变量总是评估为当前项目,无论它从哪里调用。下面是一个Overview of POM variables(没有完成,但最重要的东西是在那里)

另外,如果你想要做一些交互式查询式的调试,help:evaluate 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。

+1

我不认为问题是与Maven,它与DBUnit。它在DTD的错误位置查找。是否有另一种更好的方式来指定在XML文件内?有没有我缺少的DBUnit设置? – HDave 2010-06-11 18:35:13

+0

使用新方法解决了运行时问题 - 但现在Eclipse正在抱怨它无法找到用于验证的DTD。我想要我的蛋糕,也吃它! – HDave 2010-06-13 00:26:44

+0

“目标”目录仅在maven构建之后才存在。如果我运行mvn clean,它不在那里,然后Eclipse回归抱怨!我已经检查了源代码到DBUnit,他们真的走出去了,没有找到dtd .... – HDave 2010-07-09 02:12:53

0

打开XML文件时,请尝试使用“File”而不是“FileInputStream”。

例如:

ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new File(fileName))); 

这种方式,DTD相对路径应与XML文件的目录中启动。

如果您使用

ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(new FileInputStream(fileName))); 

路径应是相对于当前的工作目录。

1

你可以发布DTD到Web服务器,然后把它的HTTP URL到DOCTYPE,如:

<!DOCTYPE myapp-data SYSTEM "-//The Owner//The Description//EN" "http://host/path/to/myapp-data.dtd"> 
0

它涉及到一些丑陋的重复,但你可以在DTD的内容粘贴到XML有问题的文件,然后用它们作为internal DTDs