Smalltalk перед Longtalk;)
(Конечно, я не хочу призывать вас прочитать все из этого длинного подробного поста! жирных маркеров уже может быть достаточно для решения ваших проблем но я нашел, что стоит документировать этот хитрый материал более подробно!)
Так как я потратил еще пару часов на это (после того, как я решил это несколько недель назад, у меня было изменение, но я забыл его документироватьправильно, забыл, как я это сделал, и не смог получить эту информацию снова в любой форме - при загрузке и настройке в / в JasperServer) ... вот некоторые агрегированные функциональные возможности, упомянутые на различных сайтах относительно ссылок на подотчеты, как это работает и что можнопопробуйте ...
(я обновлю мои или другие находки здесь, если они, надеюсь, будут)
Краткие сведения / лучшие практики?! 4
До тех пор, пока, возможно, функциональность Jasper не предоставит аналогичное решение "обертывания" ...
Чтобы обойти все проблемы, связанные с запускомРабота с файлами * .jrxml, * .jasper локально в режиме предварительного просмотра или удаленно на JasperServer. Сейчас я использую следующий подход, который позволяет работать только с одним файлом * .jrxml, который будет работать локально и удаленно безмодификации в среде с несколькими разработчиками, поддерживающие независимый рефакторинг структур dir (путей, имен) для среды (= как следует ;-)):
- с использованием некоторых jasper-utils - *. Jar
- поместите его в путь к классу вашего проекта (Java) (
Project->Properties->Java Build Path->Libraries->Add
) - вставьте егов вашей папке
../jasperserver/WEB-INF/lib/
- , ссылающейся на некоторый пользовательский Jasper Java Scriptlet
jr.utl.EnvScriptlet
, который делает уродливую магию пути / ссылки в вашем отчетеОсновные отчеты - определяют
REPORT_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/
в вашем локальном пути JasperSoft Studio (Eclipse) Java src / build : Например, ../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/
Для достижения независимости модификации источника в наших средах мы параметризовали эти значения и сгенерировали их один раз через некоторое рабочее пространство-dзависимый / специфичный для пользователя файл 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
или скриптлета, возможно, не лучший путь, но, вероятно, он будет работать в подавляющем большинстве случаев использования - , хотя оба существующих класса Jasper предполагают, что они, похоже, не подходятбыть в состоянии справиться с вышеизложенным правильно:
( 5 : соответствующая специальная обработка закодирована здесь: EnvScriptlet.java / getSubrepPath (String, String, boolean, String []) )
Введение (Справочная информация)
Первое, что нужно знать, это то, что обработка / настройка в 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/
- ИД-путь репозитория GUI нашего Jasper Report Server нашего основного отчета будет:
/x/y/z/
(который не следует путать с визуальным именованным путем, например, который может быть Financial Reports/Expenses/Current Year
)
В общем: Jasper Studio, JasperServer
(и другие "среды выполнения Jasper", например использование пользовательских пакетов Java Jasper):
- кажется Хорошая практика объявлять параметр отчета «префикс», который может варьироваться в зависимости от среды выполнения Jasper, например, с именем
BASE_DIR
- , важно, чтобы онЛучше всего предположить, что суффикс
/
может быть включен 1 , потому что есть случаи, когда вы можете / хотите использовать его так, как это необходимобыть пустым или «нерасщепленным» путевым выражением - например
$P{BASE_DIR} + "subrep1.jrxml"
, которое должно преобразовываться в repo:subrep1.jrxml
- см., Например, здесь для получения более подробной информации (см.
SUBREPORT_DIR
)
( 1 : что лично я считаю плохой практикой вообще (не смотря на это в отчетах Jasper Reports) при работе со структурами, подобными каталогам)
JasperStudio Designer (Eclipse Plugin)
(официальный преемник IReport с множеством дополнительных функций)
(если вы не используете функцию предварительного просмотра, это может быть вам неинтересно)
- к сожалению, я не нашел практического способаполностью поддерживать (нормальную) «командную разработку» с подотчетами (и, вероятно, с другими относительными ресурсами), что означает здесь (на данный момент мне неизвестно) несуществующую возможность разделения локальных путей и * .jrxml файлов :- (
- например, если у вас установлена система контроля версий и вы работаете в разных средах (разные локальные пути к репозиториям и / или разные разработчики), главный отчет должен содержать локальный путь кВаш подотчет каким-то образом )
- Я испробовал разные подходы, которые потерпели неудачу:
- выражения относительного пути в
BASE_DIR
не работают, так как рабочий каталог - 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
- это нечто не связанное (нездесь полезно иметь дело с хранением результата отчета "кеширование" - конечно, я мог бы написать задачу ANT, чтобы заменить эти локальные шаблоны, основываясь на копии фильтра регулярных выражений при каждом использовании / проверке, но это, кажется, нехороший способ справиться с этим
- если вы хотите работать только с
*.jrxml
файлами (как я 3 ), вам нужно сослаться на subrep1.jrxml
, например: net.sf.jasperreports.engine.JasperCompileManager.compileReport($P{BASE_DIR} + "subrep1.jrxml")
( 3 : мне явно не нужны файлы *.jasper
, и я не понимаю, почему я хочу иметь с ними дело. Кстати, веб-интерфейс JasperServer поддерживает только загрузку файлов *.jrxml
)
JasperServer Web GUI
(например, предоставленный некоторым сервером приложений Tomcat и хранящий его данные в некоторой базе данных postgres)
Сценарий 1: ссылка на вложенный ресурс (ы) вложенного отчета
- если вы не хотите повторно использовать свой отчет в целом, то, по-видимому, можно добавить свой суперпорт в свой основной отчет (поэтому он не отображается в дереве репозитория с графическим интерфейсом - см. Ниже подпункт, как можно ссылаться на него за пределами своего основного отчета в любом случае)
- если вы присоединяете свой подотчет, в общем случае оно должно иметь имя файла в качестве идентификатора ресурса , например, наш
subrep1.jrxml
сверху загружен с идентификатором ресурса subrep1.jrxml
(что делает обработку локальных проектных ссылок и ссылок на сервер менее сложной)
- взяв пример отчетов сверху, мы должны установить для
BASE_DIR
значение repo:
в основном отчете для загрузки
- при этом выражения подотчета
$P{BASE_DIR} + "subrep1.jrxml"
и $P{BASE_DIR} + "somesubdir/subrep2.jrxml"
должны работать и на сервере
- НЕ рекомендуется !: вы все равно могли бы ссылаться на эти отчеты из других отчетов с помощью абсолютных путей, подобных этому 2 :
repo:/x/y/z/masterrep.jrxml_files/masterrep.jrxml_
( 2 : что я бы не рекомендовал в этом случае; оно недокументировано и может измениться; лучше поместите ваши подотчеты, чем в «путь репозитория GUI», как описано ниже)
Сценарий 2: ссылочный ресурс подотчета репо
предположим, что мы загружаем наши подотчеты в id-путь главного репо /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)
- , что приводит к пустым разделам подотчета в основном отчете:
$P{REPORT_CONTEXT}.getRealPath("subrep1.jrxml")
$P{REPORT_CONTEXT}.getProperty("REPORT_FILE_RESOLVER").resolveFile("subrep1.jrxml")
Дополнительные подсказки
Поскольку мне нравится автоматизировать процесс разработки и развертывания отчетов настолько, насколько это имеет смысл, я написал некоторые задачи ANT , которые обрабатывают локальный файл * .jrxml, для развертывания * .jrxmlпреобразования файлов, относящиеся к BASE_DIR
и другим преобразованиям.
SQL полезны для простого исследования структур пути идентификатора ресурса в мета-базе данных jasper server postgres (после чего-тонапример 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, связанные с этим, включают: