这个问题已被问过几次,但并不令我满意。我对提出的解决方法并不感兴趣,但是如何做我真正想做的事情。
想要一个令人满意的解释,为什么这是不可能的,如果不是,并且因为我建议自己提交一个解决方案,我想了解为什么看似如此简单的东西没有尝试。
目前,为了确保ant可以使用一组jar,必须采用以下方法之一:
CLASSPATH
环境变量 - 文档$ANT_HOME/lib
或~/.ant/lib
- 需要在构建环境中进行配置-lib
调用ant
参数
最后一个选项是我已经确定的首选选项,但它仍然需要调用构建的人进行一些干预(我已经在我的开发存储库中的ant
包装器脚本中捕获了)。
特别是我试图调用Schematron Ant任务,该任务应根据the documentation设置,如下所示:
<taskdef name="schematron"
classname="com.schematron.ant.SchematronTask"
classpath="lib/ant-schematron.jar"/>
然而,这对撒克逊人具有传递依赖性,因此如果saxon.jar
上没有CLASSPATH
,则构建失败:
java.lang.NoClassDefFoundError: net/sf/saxon/TransformerFactoryImpl
ant documentation itself继续建议它应该是taskdef本身带来这些额外的CLASSPATH
条目,但我已尝试使用schematron ant-task无效。
关键问题是它是否应该是支持这种情况的schematron ant任务,或者ant build.xml是否可以在其内部配置其全局类路径?
似乎这是人们想要经常做的事情,并且由于ant文档本身建议不使用CLASSPATH本身我很惊讶build.xml本身没有其他选择!
答案 0 :(得分:1)
这似乎是Schematron任务中的一个错误。 Ant任务加载Saxon XSLT处理器的方式要求Saxon在系统类路径上,即使任务本身位于子类加载器上也是如此。
乍一看this code in ValidatorFactory看起来很合理:
private TransformerFactory _factory = TransformerFactoryImpl.newInstance();
(其中TransformerFactoryImpl
是撒克逊人对TransformerFactory
)的实现,但实际上TransformerFactoryImpl
并没有定义自己的newInstance()
方法,所以这是来自newInstance
的继承TransformerFactory
,它将根据javax.xml.transform.TransformerFactory
系统属性的值查找适当的工厂。 Ant任务does set this system property:
System.setProperty("javax.xml.transform.TransformerFactory",
"net.sf.saxon.TransformerFactoryImpl");
但TransformerFactory.newInstance()
将在系统类加载器上查找此类,而不一定在加载schematron任务的类加载器上查找。
修复方法是将ValidatorFactory
第120行更改为
private TransformerFactory _factory = new TransformerFactoryImpl();
将绕过所有动态查找并直接实例化正确的类。有了这个修复程序
<taskdef name="schematron"
classname="com.schematron.ant.SchematronTask"
classpath="lib/ant-schematron.jar:lib/saxon9he.jar"/>
会正常工作。
我建议您向开发人员报告错误,但该项目看起来并不活跃,因此您可能只需构建自己的本地分支......