Smalltalk перед Longtalk ;)
(Конечно, я не хочу побуждать вас читать весь этот длинный и подробный пост! Жирным шрифтом может быть уже достаточно, чтобы решить ваши проблемы, но я счел, что стоит задокументировать этот сложный материал в более подробной документации. подробно!)
Поскольку я потратил на это еще пару часов (после того, как я решил это несколько недель назад, сейчас было изменение, но я забыл правильно его задокументировать, забыл, как я это сделал, и не мог снова получить эту информацию в любой форме - при загрузке и настройке to/in JasperServer) ... вот некоторые агрегированные функции, упомянутые на различных сайтах в отношении ссылок на подотчеты, как это работает и что можно попробовать ...
(Я обновлю свои или другие выводы здесь, если, надеюсь, они будут)
Краткие сведения/рекомендации?!4
Пока, возможно, функциональность Jasper не предоставляет аналогичное решение для «обертывания» ...
Чтобы обойти все проблемы, связанные с запуском файлов *.jrxml, *.jasper либо локально в режиме предварительного просмотра, либо удаленно на JasperServer, я теперь использую следующий подход, который позволяет работать только с одним файлом *.jrxml, который будет работать локально и удаленно без модификаций, в среде с несколькими разработчиками, поддерживая независимый рефакторинг структур dir (пути, имена) для каждой среды (= как и должно быть ;-)):
- using some jasper-utils-*.jar
- put it in your project (Java) class path (
Project->Properties->Java Build Path->Libraries->Add
)
- поместите его в папку
../jasperserver/WEB-INF/lib/
- referencing some custom Jasper Java Scriptlet
jr.utl.EnvScriptlet
that does the ugly subreport path/reference magic in your master reports
- define the
REPORT_SCRIPTLET
by adding an attribute to your master report: report properties -> Report -> Data Set -> Scriptlet Class: jr.utl.EnvScriptlet
используя файл настраиваемых свойств jr.utl.properties
или иные предоставленные системные свойства (любой другой способ установки системных свойств Java также подойдет и будет работать — где уже настроенные свойства переопределяют свойства загруженного файла) для настройки различные среды, включая вашу
- current environment information via
jr.utl.env
property (prod, myOsUsrName, test, demo, staging, local, ...)
- which determines how the subreport references must be generated / look like
- ссылки на свойства родительского каталога подотчета сервера
- взять напр. это содержимое файла свойств и поместите здесь по одному для каждой среды:
на ваших серверах: ../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/
в вашем локальном пути исходного кода/сборки Java JasperSoft Studio (Eclipse): например. ../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
)
- defining the master subreport expressions as e.g.
jr.utl.EnvScriptlet.getSubrepPath( $P{BASE_DIR}, "subrep1.jrxml")
- automatically resolving the values from properties you could also use e.g. these variants:
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
или скриптлета может быть не лучшим способом, но, вероятно, он будет работать в подавляющем большинстве случаев использования.
- although both existing Jasper classes suggest this they do not seem to be able to handle the above properly:
(5: соответствующая специальная обработка закодирована здесь: EnvScriptlet.java/getSubrepPath( Строка,Строка,логическое значение,Строка[]))
Вступление (Фон)
Первое, что нужно знать, это то, что обработка/настройка в JasperStudio сильно отличается от обработки на Jasper Server (Repository)5< /суп> ...
предположим, что у нас есть следующие среды:
- наш установочный каталог Eclipse:
C:\eclipse\
- наше рабочее пространство 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/
- наш путь идентификатора репозитория графического интерфейса пользователя Jasper Report Server нашего основного отчета будет:
/x/y/z/
(который не следует путать с визуальным именованным путем, например, который может быть Financial Reports/Expenses/Current Year
)
В общем: Jasper Studio, JasperServer
(и другие «среды выполнения Jasper», такие как использование пользовательского пакета Java Jasper):
- it seems a good practice to declare a report parameter "prefix" which can vary depending on your Jasper runtime environment e.g. named
BASE_DIR
- important here is that it seems best to assume the suffixed
/
may be included1 because there are cases where you may have/want to use it in a way where it should be an empty or "unslashed" path expression
- e.g.
$P{BASE_DIR} + "subrep1.jrxml"
which should resolve to
repo:subrep1.jrxml
- см. напр. здесь для более подробной информации (ищите
SUBREPORT_DIR
)
(1: что я лично считаю плохой практикой в целом (не рассматривая Jasper Reports в этом отношении) при работе со структурами, подобными каталогам)
JasperStudio Designer (плагин Eclipse)
(официальный преемник IReport с большим количеством функций)
(если вы не используете функцию предварительного просмотра, это может быть вам неинтересно)
- unfortunately I found no practical way to fully support (normal) "team-development" with subreports (and likely other relative resources as well), meaning here the (currently to me unknown) inexistent possiblity to separate local paths and *.jrxml files :-(
- e.g. if you have a version control system in place and work in different environments (different local paths to repos and/or different developers) the master report has to contain a local path to your subreport in some way)
- I tried different approaches that failed:
- выражения относительного пути в
BASE_DIR
не работают, поскольку рабочим каталогом является каталог eclipse, например. C:\eclipse
Eclipse->Window->Preferences->JasperStudio->Properties->Add
e.g. my.base.dir
- it is not available in the Preview mode, e.g. via
new java.io.File(System.getProperty("my.base.dir")).getCanonicalPath() + "/"
for our BASE_DIR
expression (these props may be only used by the designer itself, but not set in preview runs)
- на всякий случай вы можете наткнуться (как и я):
Eclipse->Window->Preferences->JasperStudio->Report Execution->Virtualizer Temporary Path
- это что-то несвязанное (не полезное здесь), связанное с хранением результатов отчета "кэширование"
- конечно, я мог бы написать задачу ANT, чтобы заменить этот локальный шаблон на основе копии фильтра регулярного выражения при каждом использовании/выдаче, но это не лучший способ справиться с этим.
- если вы хотите работать исключительно с
*.jrxml
файлами (как я делаю3), вы должны сослаться на некоторые subrep1.jrxml
следующим образом: net.sf.jasperreports.engine.JasperCompileManager.compileReport($P{BASE_DIR} + "subrep1.jrxml")
(3: мне явно не нужны файлы *.jasper
, и я не понимаю, почему я хочу иметь с ними дело. Кстати, веб-интерфейс JasperServer, кажется, поддерживает только загрузку файлов *.jrxml
)
Веб-интерфейс JasperServer
(например, предоставляется некоторым сервером приложений Tomcat и хранит свои данные в некоторой базе данных postgres)
Сценарий 1: ссылка на прикрепленный(е) ресурс(ы) подотчета
- если вы не хотите повторно использовать свой отчет в целом, можно добавить свой вспомогательный отчет в основной отчет (чтобы он не был виден в дереве репозитория графического интерфейса — см. ниже подпункт, как вы все равно можете ссылаться на него вне вашего основного отчета)
- если вы прикрепите свой подотчет, он должен, как правило, иметь свое имя файла в качестве идентификатора ресурса, например. наш
subrep1.jrxml
сверху загружается с идентификатором ресурса subrep1.jrxml
(таким образом упрощается обработка ссылок на локальный дизайн и ссылок на сервер)
- taking the example reports from above we have to set our
BASE_DIR
to repo:
in the to-be-uploaded master report
- thus the subreport expressions
$P{BASE_DIR} + "subrep1.jrxml"
and $P{BASE_DIR} + "somesubdir/subrep2.jrxml"
should work on the server as well
- НЕ рекомендуется!: вы все равно можете ссылаться на эти отчеты из других отчетов с абсолютными путями, такими как этот2:
repo:/x/y/z/masterrep.jrxml_files/masterrep.jrxml_
(2: что я бы не рекомендовал в этом случае; это недокументировано и может измениться; лучше поместите свои подотчеты в «путь репозитория GUI», как описано ниже)
Сценарий 2: ссылки на ресурсы подотчетов репозитория
предположим, что мы загружаем наши подотчеты в главный репозиторий с идентификатором пути /x/y/z/
(как показано вверху)
снова нам нужно различать два разных варианта использования.
мы НЕ хотим использовать вложенный отчет как отдельный отчет (он всегда будет включен только в другие основные отчеты)
в этом случае мы должны загрузить его с помощью Add Resource->File->JRXML
и сослаться на него
../subrep1.jrxml
или ./subrep1.jrxml
не работают, так как кажется, что лежащая в основе логика не может обработать выражение относительного пути ..
(и вероятно, .
тоже) (что на самом деле было бы неплохо :-( )
поэтому здесь нам нужно указать абсолютный канонический путь в BASE_DIR
нашего masterrep.jrxml, например, 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)
- resulting in empty subreport sections in master report:
$P{REPORT_CONTEXT}.getRealPath("subrep1.jrxml")
$P{REPORT_CONTEXT}.getProperty("REPORT_FILE_RESOLVER").resolveFile("subrep1.jrxml")
Дополнительные подсказки
Поскольку мне нравится автоматизировать процесс проектирования и развертывания отчета настолько, насколько это имеет смысл, я написал несколько задач ANT, которые обрабатывают локальный файл *.jrxml для развертывания файла *.jrxml. преобразования относительно BASE_DIR
и других преобразований.
SQL помогает легко исследовать структуры пути идентификатора ресурса в метабазе данных postgres сервера jasper (после чего-то вроде 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, связанные с этим, включают:
person
Andreas Covidiot
schedule
04.12.2013