如何使用 JasperReports (6.*) 解决 LinkageError?

How to resolve LinkageError with JasperReports (6.*)?

例如我们得到了:

net.sf.jasperreports.engine.JRException: ...
Caused by: net.sf.jasperreports.engine.fill.JRExpressionEvalException: 
  Error evaluating expression for source text: 
    $P{REPORT_SCRIPTLET}.setTestRaw_LogOn_TstMsgOn(true, true)
Caused by: java.lang.LinkageError: loader constraint violation: loader 
  (instance of java/net/FactoryURLClassLoader) previously initiated loading 
  for a different type with name "org/slf4j/Logger"

运行 Eclipse (Kepler) Preview with JR plugin v6.1.0,但not with another Eclipse 运行 5.5。 1.final

显然我们正在使用一些构建路径引用的自定义报告脚本,它本身使用 slf4j api 进行日志记录。

它似乎与同一个 class 的另一个不同版本冲突(对于相同的底层 class 加载隔离)。

对我们来说最简单的解决方案(在对库和设置进行一些摆弄之后)是使用 Jasper 插件 v5 切换回 Eclipse 目录备份版本.5.1.final(我们仍然为所有开发人员提供一份副本)。

通过 Eclipse 安装历史 "Revert" 并不容易,因为我们的基础更新站点仅指向最新版本,或者可能根本没有 5.5.1.final 的旧更新站点. (我们没有进一步调查)

(顺便说一句:在 Eclipse 中禁用自动更新以避免此类意外可能是安全的)

环境详细信息:

(...对于那些可能会找到其他可行解决方案的人的可能原因。)

对我们来说,这是 org.slf4j.Logger 的用法(具有 slf4j-api-1.7.5.jar slf4j-simple-1.7.5.jar 在构建路径中或将两者都删除 - 没关系......只需在更改后关闭并重新打开所有报告没有 Eclipse 重新启动)

运行 Eclipse with the eclipse.ini jvm option -verbose:class 显示冲突可能与this other loaded class(无论在哪里加载(可能由 jasper 预览编辑器本身使用):eclipse/plugins/org.slf4j.api_1.7.2.v20121108-1250.jar)

假设 Jasper 从 v6 开始就使用 SLF4J,并且不使用单独的 class 隔离它的 class 报告特定 classes/libs 加载来自其自身 class 版本(或 Eclipse 安装提供的版本)的加载程序,因此可能会导致此类链接错误(例如 How to deal with LinkageErrors in Java?。)。

6.0.4(我在其中添加了这些信息)已经有一个已知的已解决错误,但显然没有解决: http://community.jaspersoft.com/jaspersoft-studio/issues/3831#comment-818386

我遇到了同样的问题,我通过在项目的构建路径中添加这些 Jar 解决了这个问题:

  • slf4j-api-1.7.12.jar
  • slf4j-log4j12-1.7.12.jar
  • slf4j-simple-1.7.12.jar

并将 JasperReports LibraryJasperReports Library Dependencies 添加到项目中

通过这些步骤

  1. 在项目中右击
  2. 构建 Cath > 配置构建路径
  3. 转到库并使用 Add External JARs
  4. 添加 jar
  5. 使用 Add Library 添加 JasperReport 库和 JasperReport 库依赖项
  6. 然后转到 Order and Export 并检查新添加的库和 Jar,然后单击确定

你会得到这样的结果:

(哇...终于至少有一个可接受的 解决方法 显然 groovy class 加载已找到问题)

我们创建了一些非常简单的 帮助报告 hlprep.jrxml 本身

  • 使用提到的 scriptlet

    • 或者 use/call 任何其他 java class 你会遇到问题
  • 设置为language=java

    • (其他网站建议从 language=groovy 切换到 java 以消除上述错误,但这通常不是一个选项)

(现在 运行 在 Preview 中应该没问题)

每次您遇到此错误(这可能是随机的,因为 class 加载可能是正确的,具体取决于您之前在 IDE) 我们现在可以执行以下操作:

  1. 打开hlprep.jrxml

    • 最好使用 Open with ... JasperReports Preview(因此您不必在后续步骤中明确打开预览)
  2. 重启你的Eclipse

    • 重启后应该记住你打开的文件,否则重启后必须先打开助手报告
  3. select/preview hlprep.jrxml

    • 现在可以进行正确的 class 加载(由 'java' 上下文触发)
  4. select/preview(已打开)其他失败的报告

现在应该 运行 正常,即使在更改之后,但如果您再次 open/close 新的 可能会失败。 (因为 classes 可能会被回收或 groovy class 加载器隔离魔法以不同方式加载它)

我们的环境

  • 日食霓虹灯 3
    • 在内部使用 Groovy 2.4.5
    • JDK 1.8.0_121
    • 开头
  • Jaspersoft Studio 6.3.2.final
    • 我们有一个 6.3.0 服务器,但是在 6.3.1 中添加了完整的 Neon 支持,所以我们使用了最后一个补丁版本6.3.x
    • 我们之前遇到过较新的工作室版本无法与较旧的服务器一起使用的问题,因此我们在此处进行升级时更加谨慎
  • 可能无关紧要:
    • 仅依赖 pom.xml
    • 中的 slf4j api(在我们的例子中是 1.7.12)就足够了
    • 我们都提供了添加到项目中的 jasper 库:Jaspersoft Server LibraryJasperReports Library Dependencies
    • 我们还依赖于服务器功能,因此我们在 pom.xml 中也有 jasperreports-6.3.0.jar 和一些(不是通过一些可用的 public Maven 存储库)服务器 jar 作为项目的 User Library(我们从服务器复制过来)
    • pom.xml
    • 中没有 groovy 参考

答:有时 只需重新启动Eclipse/Studio就足够了。这可能与某些类加载器在执行某些操作或(间接)使用某些插件时加载 类 有关。

B:尝试排除 (显式或隐式)添加到项目类路径中的 classes/jars 也很有用、用户库、Eclipse 库或 Mavens pom.xml 例如,如果项目本身 use/need/reference 它们 用于设计时间 。 这样在设计时就不会发生冲突 time/in Studio/Eclipse.
也许人们必须记住,那些 classes/jars/libs 在运行时环境中可能是必需的或不同的 ,必须解决,例如通过 Mavens pom.xml 中的 scope 或类似的。