我搜索了几天来解决这个错误没什么新问题。
我有一个包含多级子报表的报告,iReport 3.7.5
上的一切正常。我在第一级&中使用subreport.jasper
作为子报表表达式。还有subreportA.jasper
,subreportB.jasper
在第二级&将所有(主报告和子报告)放在同一路径中。
当我尝试在JasperServer
上部署它时出现的问题。
当我尝试上传第一个主报告时,iReport
向导要求我附加资源文件夹中的第一个subreport.jrxml
,并使用repo:subreport.jrxml
或repo:subreport.jasper
访问它。
然后我手动上传第二级子报表并执行相同的操作,将子报表表达式更改为repo:subreportA.jasper
和repo:subreportB.jasper
。
我收到了编译错误:Unable to locate the subreport with expression: ""repo:subreport.jasper"". java.lang.Exception: repo:subreport.jrxml not found.
我尝试打解决方案,没有任何作用。 使用:SUBREPORT_DIR @开头,
使用完整路径:repo:/Circuit_Reports/Connectivity/Connectivity_files/
,
在.jasper
&之间切换.jrxml
。
在lib文件夹中使用jasperserver_api_engine_impl_0_fix.jar
作为对此错误的修复,
我还搜索了数据库记录,以确保它们位于同一个文件夹中,并且具有相同的父文件夹。
答案 0 :(得分:8)
(当然我不想鼓励你阅读这篇长篇详细文章的内容!大胆的标记可能已足以解决你的问题但我发现值得记录这个更详细一些棘手的东西!)
因为我在这上面投入了几个小时(在我几周前解决之后,现在有了改变,但忘记了正确记录,忘了我是怎么做的,并且无法以任何形式再次检索这些信息 - 当上传和配置到/在JasperServer中)...这里有一些关于子报告引用的各种网站上提到的聚合功能,它是如何工作的以及可以尝试的...
(如果有希望的话,我会更新我的或其他调查结果)
直到Jasper的功能可能会提供类似的"包装"解决方案本身......
要解决与在预览模式下本地运行* .jrxml,* .jasper文件或在JasperServer上远程运行相关的所有问题,我现在使用以下方法,只允许使用单个*。 jrxml文件,在多开发人员环境中本地和远程无需修改即可工作,支持每个环境独立重构dir结构(路径,名称)(=应该;-)):
Project->Properties->Java Build Path->Libraries->Add
)../jasperserver/WEB-INF/lib/
文件夹jr.utl.EnvScriptlet
,它在主报告中执行丑陋的子报告路径/引用魔术
REPORT_SCRIPTLET
:报告属性 - >报告 - >数据集 - > Scriptlet类:jr.utl.EnvScriptlet 使用一些自定义属性文件 jr.utl.properties
或以其他方式提供的系统属性(设置Java系统属性的任何其他方式也可以正常工作 - 已经设置的位置属性将覆盖已加载的文件属性)以配置包括
jr.utl.env
属性(prod,myOsUsrName,test,demo,staging,local,...)
:../jasperserver/WEB-INF/classes/jr.utl.properties
jr.utl.env=prod
mycompany.local.jr.gui.rep.subrep1.parentdir=repo:/x/y/z/
mycompany.local.jr.gui.rep.subrep2.parentdir=repo:/x/y/z/
mycompany.local.jr.gui.rep.subrep3.parentdir=repo:/x/y/foobar/
:例如。 ../myrepproject/src/java/jr.utl.properties
强>
jr.utl.env=dietrian
mycompany.local.jr.gui.rep.subrep1.parentdir=D:/reporting/src/reports/
mycompany.local.jr.gui.rep.subrep2.parentdir=D:/reporting/src/reports/
mycompany.local.jr.gui.rep.subrep3.parentdir=D:/reporting/src/reports.otherdir/
在我们的环境中实现源修改独立性,我们根据这个想法,通过一些依赖于工作空间/用户特定的local.properties
文件对这些值进行参数化并生成一次:
|- build.xml (containing the ANT build magic) |- build.properties (containing global properties) |- local.properties (ignored in version control, e.g. .hgignore, user-specific generated from local.template.properties) |- local.template.properties (source for ANT build task generating the local.properties above) |- mycomp.local.proj.reporting.dir=D:/reporting |- src/reports |- jr.utl.properties (ignored in version control, user-specificly generated based on template below) |- jr.utl.template.properties (source for ANT build task generating the jr.utl.properties above) jr.utl.env=${user.name} mycompany.local.jr.gui.rep.subrep1.parentdir=${mycomp.local.proj.reporting.dir}/src/reports/ mycompany.local.jr.gui.rep.subrep2.parentdir=${mycompany.local.jr.gui.rep.subrep1.parentdir} mycompany.local.jr.gui.rep.subrep3.parentdir=${mycomp.local.proj.reporting.dir}/src/reports.otherdir/
将 BASE_DIR
主报告参数定义为例如
$P{REPORT_SCRIPTLET}.getProp("mycompany.allsubreports.parentdir")
(匹配jr.utl.properties
文件中某些与环境相关的属性)
jr.utl.EnvScriptlet.getSubrepPath( $P{BASE_DIR}, "subrep1.jrxml")
强>
jr.utl.EnvScriptlet.getSubrepPathByPropKey( $P{BASE_DIR}, "mycompany.local.jr.gui.rep.subrep1.name")
jr.utl.EnvScriptlet.getSubrepPathByPropKeys( "mycompany.local.jr.gui.rep.subrep1.parentdir", "mycompany.local.jr.gui.rep.subrep1.name")
$P{REPORT_SCRIPTLET}.getSubrepPath(...)
在这里不起作用:-((我不知道为什么)( 4 :当然我在这里仍然看到一些小的改进,但它似乎比我迄今发现的所有丑陋的解决方案要好得多。改进我会看到:
REPORT_SCRIPTLET
或scriptlet功能可能不是最好的方法,但它可能适用于绝大多数用例( 5 :相关的特殊处理在此编码:EnvScriptlet.java/getSubrepPath(String,String,boolean,String[]))
首先要知道的是,JasperStudio中的处理/设置与 Jasper Server(存储库) 完全不同 > 5 ...
假设我们有以下环境:
C:\eclipse\
C:\workspace\
C:\workspace\report-project\
C:\workspace\report-project\src/reports
C:\workspace\report-project\src/reports/masterrep.jrxml
C:\workspace\report-project\src/reports/subrep1.jrxml
C:\workspace\report-project\src/reports/somesubdir/subrep2.jrxml
BASE_DIR
(在下一节中说明)设置为C:\workspace\report-project\src/reports/
/x/y/z/
(不要与视觉命名路径混淆,例如可能是Financial Reports/Expenses/Current Year
)(和其他" Jasper运行时环境"像自定义Java Jasper包使用):
BASE_DIR
/
可能包括 1 似乎最好,因为有些情况下你可能/想要以一种空的方式使用它,或者#34; unslashed"路径表达
$P{BASE_DIR} + "subrep1.jrxml"
repo:subrep1.jrxml
SUBREPORT_DIR
)( 1 :在处理类似目录的结构时,我个人觉得这是一个不好的做法(在这方面没有看Jasper Reports)
(具有更多功能的官方IReport继任者)
(如果您不使用预览功能,这可能对您无趣)
BASE_DIR
中的相对路径表达式不起作用,因为工作目录是eclipse目录,例如C:\eclipse
Eclipse->Window->Preferences->JasperStudio->Properties->Add
例如 my.base.dir
new java.io.File(System.getProperty("my.base.dir")).getCanonicalPath() + "/"
获取BASE_DIR
表达式(这些道具可能仅供设计师使用,但未在预览中设置)Eclipse->Window->Preferences->JasperStudio->Report Execution->Virtualizer Temporary Path
是与报告结果存储无关的(在这里没用)和#34;缓存" *.jrxml
个文件(就像我做 3 ),您必须像这样引用一些subrep1.jrxml
:<强> net.sf.jasperreports.engine.JasperCompileManager.compileReport($P{BASE_DIR} + "subrep1.jrxml")
强> ( 3 :我不明确地需要*.jasper
个文件,并且不明白为什么我要处理它们.BTW JasperServer WebGUI似乎只支持上传*.jrxml
个文件)
(例如,由某些Tomcat应用程序服务器提供并将其数据存储在某些postgres数据库中)
subrep1.jrxml
上传了资源ID为subrep1.jrxml
(从而使本地设计引用和服务器引用的处理变得不那么复杂)BASE_DIR
到repo:
$P{BASE_DIR} + "subrep1.jrxml"
和$P{BASE_DIR} + "somesubdir/subrep2.jrxml"
也可以在服务器上运行repo:/x/y/z/masterrep.jrxml_files/masterrep.jrxml_
( 2 :在这种情况下我不推荐;它没有记录,可能会改变;最好把你的子报告放到&#34; GUI repo路径&#34; as如下所述)
假设我们将子报告上传到主repo id-path /x/y/z/
(如上图所示)
我们必须区分两个不同的用例
我们不想要将子报告用作独立报告(它将始终只包含在其他主报告中)
在这种情况下,我们应该使用 Add Resource->File->JRXML
上传并引用它
../subrep1.jrxml
或./subrep1.jrxml
不起作用,因为基础逻辑似乎无法处理相对路径表达式..
(并且可能.
不)(这实际上很不错:-()
所以我们要做的就是在masterrep.jrxml的 BASE_DIR
中提供绝对规范路径,例如repo:/x/y/z/
强>
我们希望将子报告用作独立报告
在这种情况下,我们应该使用 Add Resource->JasperReport
这显然会创建一个包含报告本身和其他资源的隐藏文件夹repo:/x/y/z/subrep1.jrxml_files
这就是为什么我们不仅要调整BASE_DIR
(如上所述),还要将子报表表达式调整为,例如。 $P{BASE_DIR} + "subrep1.jrxml_files/subrep1.jrxml_"
(指向子报告本身)
和可能会删除net.sf.jasperreports.engine.JasperCompileManager.compileReport(...)
包装功能,因为服务器自动执行此操作用于*.jrxml
个文件
我没有完全调查一些其他可能不正确使用的方法,这些方法对我来说无法解决上述问题(也许其他人在这里有一些结果/更正):
$P{REPORT_FILE_RESOLVER}.resolveFile("subrep1.jrxml")
(NullPointerException)$P{REPORT_CONTEXT}.getRealPath("subrep1.jrxml")
$P{REPORT_CONTEXT}.getProperty("REPORT_FILE_RESOLVER").resolveFile("subrep1.jrxml")
因为我喜欢自动化报表设计和部署过程,所以我写了一些 ANT任务来处理本地* .jrxml文件以便部署* .jrxml关于BASE_DIR
和其他转换的文件转换。
SQL 有助于轻松调查 jasper服务器postgres元数据库中的资源ID路径结构(类似jdbc:postgresql://myjasperhost/jasperserver
连接,例如与postgres用户连接) :
select
f.id as folder_id,
r.id as res_id,
case when f.hidden = true then 1 else 0 end as hidden,
f.uri||case when f.uri = '/' then '' else '/' end||coalesce(r.name,'') as res_uri,
r.resourcetype,
r.creation_date,
r.update_date,
f.uri,
r.name,
-- less important
r.version,
r.parent_folder,
r.childrenfolder,
f.parent_folder,
f.version,
f.name
-- select *
from jiresourcefolder f
left outer join jiresource r on (r.parent_folder = f.id)
where not f.uri like '/themes%'
order by f.uri||coalesce(r.name,'')
有关此问题的Jaspersoft论坛的问题包括:
答案 1 :(得分:3)
不确定此机制是否适用于所有情况,但它确实适用于JasperSoft Studio 5.6.0
和Jasper Reports Server 5.6.0
。
基本上我们需要一种简单的方法来检测我们在服务器上运行 - 我使用$P{REPORT_CONTEXT}
参数的存在(或不存在),实验显示该参数存在于服务器上但在预览期间不存在。
<parameter name="OnServer" class="java.lang.Boolean" isForPrompting="false">
<parameterDescription><![CDATA[Are we running on server]]></parameterDescription>
<defaultValueExpression><![CDATA[Boolean.valueOf($P{REPORT_CONTEXT}!=null)]]></defaultValueExpression>
</parameter>
完成后,您可以从两个选项中定义子报告的位置:
<parameter name="SubReportProducts" class="java.lang.String" isForPrompting="false">
<parameterDescription><![CDATA[The products subreport]]></parameterDescription>
<defaultValueExpression><![CDATA[$P{OnServer}.booleanValue() ? "repo:OrderPicksheetProducts.jrxml" : "OrderPicksheetProducts.jasper"]]></defaultValueExpression>
</parameter>
然后包括子报告:
<subreportExpression><![CDATA[$P{SubReportProducts}]]></subreportExpression>
然后,您可以在工作室中使用Preview
,并且在部署到服务器时仍可正常工作。
答案 2 :(得分:0)
我不是这个答案的100%但是:你必须将你的子报告作为jrxml资源上传并放入“repo://subreport.jrxml”才能使它工作。 如果您在这些日子中读到这一天,请告诉我它是否有效或您找到了哪些解决方案。 此致
答案 3 :(得分:0)
尝试完全删除扩展程序并使用“repo:/ subreportFolder / subreportName”。主报告在iReport中提取jasper文件,但是在jasperserver上你上传了jrxml。