barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)
Показаны сообщения с ярлыком orbeon. Показать все сообщения
Показаны сообщения с ярлыком orbeon. Показать все сообщения

вторник, 16 октября 2012 г.

Orbeon: "java.io.IOException: PDF header signature not found." при печати формы

Проблема:

При попытке распечатать форму Orbeon Forms (имеющую собственный шаблон pdf-ки) валится исключение:
java.io.IOException: PDF header signature not found.
at com.lowagie.text.pdf.PRTokeniser.checkPdfHeader(Unknown Source)
at com.lowagie.text.pdf.PdfReader.readPdf(Unknown Source)
at com.lowagie.text.pdf.PdfReader.<init>(Unknown Source)
at com.lowagie.text.pdf.PdfReader.<init>(Unknown Source)
...
Причина:

Вероятнее всего, pdf-ки просто нет там, куда ссылается соотв. элемент формы (instance('fr-form-attachments')/pdf).

пятница, 14 сентября 2012 г.

Orbeon: рестилизация печатной формы

При генерации pdf по форме (без использования собственного pdf-шаблона формы) Orbeon корректно обрабатывает правило @media, поэтому управлять стилем генерируемой pdf-ки можно с помощью css, устанавливая различные стили для @media screen и @media print.

понедельник, 16 апреля 2012 г.

Orbeon: установка значения переменной в сессии по загрузке формы

Задача:

Установить некоторое значение в сессии по окончании загрузки Orbeon-формы.

Решение:

Внутри <xforms:model id="fr-form-model"> добавить следующий тег:

<xforms:action ev:event="xforms-ready">
<xforms:insert context="." origin="xxforms:set-session-attribute('sessionAttrName', 'sessionAttrValue')"/>
</xforms:action>

среда, 22 февраля 2012 г.

xforms:case и xpath в атрибуте "selected"

В атрибуте "selected" использовать xpath нельзя, его значение интерпретируется как текст, и любое значение, отличное от true, приводит к скрытию case`а (если все case`ы оказываются скрыты, первый из них все же отображается). По крайней мере в Orbeon это так.

вторник, 21 февраля 2012 г.

Orbeon: отличие xpath-функций instance() и xxforms:instance()

xxforms:instance() выбирает сущность по идентификатору также, как и стандартная функция instance() с той лишь разницей, что:
  1. Не учитывает область видимости, заданную текущей моделью (выбранной атрибутом "model")
  2. Осуществляет поиск в областях видимости вышестоящих XBL-компонентов
, в то время как instance() ищет только в текущей модели текущего компонента.

понедельник, 30 января 2012 г.

Orbeon xforms-jsp и теги <script> внутри <head> на включаемых jsp-страницах

Наткнулся тут на интересные грабли при размещении jsp-страниц в директории xforms-jsp веб-приложения Orbeon`а: мало того, что генерируемая jsp-шкой html-страница должна быть валидным xml (с чем я ещё готов как-то мириться), так ещё к тому же Orbeon умудряется по своему усмотрению переносить в пределах документа теги <script>. 
А именно: пусть есть некоторая jsp-страница header.inc.jsp, включаемая в другую страницу index.jsp с помощью тега  <jsp:include>. Тогда, если на странице header.inc.jsp в блоке <head> есть теги <script> с inline яваскриптом или со ссылками на внешние скрипты, в итоговом html-коде, генерируемом страницей index.jsp, теги <script> окажутся после закрывающегося тега </body>, а вовсе не в <head>. 
Такое поведение бывает крайней неудобно, например, когда переменные из js-файлов или inline js-кода используются в теле страницы т.к. предполагается, что js уже загружен в <head>. Единственное пока найденное мною решение - перенести теги <script> из <head> в начало тега <body>.
Вся эта неразбериха вызвана тем, что к jsp-страницам в директории xforms-jsp применяется фильтр org.orbeon.oxf.servlet.OrbeonXFormsFilter, выполняющий рендеринг xform`ы из xml в html (благодаря этому jsp-страницы в этой директории могут содержать xforms-код, который будет корректно отрендерен в html). 

вторник, 13 декабря 2011 г.

Формирование Орбеоном "эффективных" id элементов XBL-компонента при отрисовке страницы

При отрисовке страницы Орбеоном окончательные id ("эффективные" в терминологии Орбеона - http://wiki.orbeon.com/forms/doc/developer-guide/xforms-javascript-integration), присваиваемые элементам управления компонента (и по которым, можно, скажем, получить их значения  из JS вызовом ORBEON.xforms.Document.getValue()), отличаются от тех, которые были заданы в xbl-файле компонента.
Во-первых, в начало id-шника добавляется нечто вроде 'xf-396$', где вместо 396 будут другие цифры, выполняющие роль идентификатора компонента для разделения областей видимости id-шников разных компонентов, т.е. для разных экземпляров одного и того же компонента это число одинаково (не проверял, постоянно ли оно для последовательных загрузок формы или для различных запусков JVM, т.к. считаю, что в любом случае полагаться на это постоянство опасно). Если компонент вкладывается в другой компонент - соответственно, в начале id-шника оказывается уже несколько таких последовательностей.
Во вторых, если компонент вложен в repeat, то в конце к его id добавляется '·1', '·2' и т.п. в зависимости от текущей итерации repeat`а (где '·' - это символ U+00B7). Если repeat`ы - вложенные, то окончания эффективного id буду выглядеть как '·1-1', '·1-2', '·2-1' и т.п. (где первая цифра - итерация самого внешнего repeat`а, а после неё через дефис идут итерации вложенных в порядке углубления). Правило относительно repeat`ов относится не только к компонентам, но и к любым элементам управления.

Orbeon XPath: получение свойств из properties-local.xml

XPath-расширения Орбеона позволяют получать значения свойств, заданные в настроечном файле properties-local.xml (расположенном в 'WEB-INF\resources\config'). Так, например, XPath-выражение:
xxforms:property('some.property.name')
вернет содержимое свойства:
<property as="xs:anyURI"  name="some.property.name" value="http://ya.ru"/>

пятница, 9 декабря 2011 г.

Orbeon: отображение индикатора загрузки

Для того, чтобы вручную показать индикатор загрузки (появляющийся, например, когда orbeon отправляет запросы на сервер), нужно выполнить:
xformsDisplayIndicator('loading', 'Ваш текст для отображения на индикаторе');
Скрыть его можно следующим образом:

var form = ORBEON.xforms.Globals.requestForm;
if(form!=null && ORBEON.xforms.Globals.formLoadingLoadingOverlay[form.id]!=null)
     ORBEON.xforms.Globals.formLoadingLoadingOverlay[form.id].hide();

Orbeon: отображение и скрытие стандартной модальной панели ожидания

В Орбеоне есть своя модальная панель ожидания, которая затемняет всё окно и отображает крутящиеся стрелочки посередине (например, во время отправки формы). Показывается она вызовом:
ORBEON.util.Utils.displayModalProgressPanel();
, а скрывается:
ORBEON.util.Utils.hideModalProgressPanel()

понедельник, 5 декабря 2011 г.

Создание Document из строки в Orbeon

Подходы для парсинга строки в дерево Document на JavaScript различаются в разных браузерах (в IE используется ActiveX-компонент Microsoft.XMLDOM, в Firefox - XMLSerializer), но при написании кода для Orbeon можно использовать его кроссбраузерную функцию ORBEON.util.Dom.stringToDom().

пятница, 2 декабря 2011 г.

Orbeon: создание XML-элемента с пространством имен с помощью XPath

Задача: 

Создать элемент с пространством имен, описанным в этом же элементе (установить xmlns как атрибут, передав его вторым параметром функции xxforms:element, нельзя - Orbeon просто проигнорирует атрибуты с именем xmlns или из пространства имен xmlns). Например:
<foo:mytag xmlns:foo='some-name-space'/>

Решение:

xxforms:element(QName('some-name-space'),'foo:mytag'))

или, если, к примеру, нужно взять namespace другого узла:

xxforms:element(QName(namespace-uri(/path/to/other/node),'foo:mytag')

Правда, такое создание элемента связано со следующей проблемой (вернее, скорее всего, багом орбеона): при использовании пространства имен по-умолчанию (т.е. передавая в QName имя элемента без пространства имен), элемент не создается. Если пытаться выполнить эту операцию в XForms Inspector, вылетает "java.lang.StringIndexOutOfBoundsException: String index out of range: -1", при использовании этого XPath в других местах он также приводит к некорректному поведению орбеона. Другого способа создавать элементы с пространством имен по-умолчанию я не нашел, разве что описывать элемент строкой, после чего парсить её с помощью saxon:parse:

saxon:parse('<mytag xmlns=''some-name-space''/>')
В таком случае, однако, нельзя одновременно с созданием элемента добавить ему потомков без их сериализации в строку, как это позволяет сделать xxforms:element.

пятница, 26 августа 2011 г.

org.orbeon.saxon.trans.XPathException: An empty sequence is not allowed as the value of variable $control-resources

Проблема: при попытке получить pdf-ку из заполненной в orbeon формы вместо pdf-ки вываливается исключение "org.orbeon.saxon.trans.XPathException: An empty sequence is not allowed as the value of variable $control-resources".

Причина:
  • причина аналогичная таковой для исключения "org.orbeon.saxon.trans.XPathException: An empty sequence is not allowed as the value of variable $section-holder" (http://barbitoff.blogspot.com/2011/08/orgorbeonsaxontransxpathexception-empty.html) - не соотвтетствие id bind`а какого-то из элементов управления имени узла модели, к которому этот bind осуществлен.
  • если ошибка возникает из-за элемента управления select1, то, возможно, необходимо чтобы ресурсы, на которые он ссылается (label, hint, help, alert при организации их по ссылке через ref) находились завернутыми в тег, совпадающий по имени с тегом в модели (т.е. ссылка на них имела вид <xforms:label ref="$form-resources/{tagName}/label"/>, где {tagName} - имя тега модели, к которому привязан данный control). Совсем непонятный для меня факт, однако переименование ресурса заставляет форму работать..

Решение: bind`ы должны выглядеть следующим образом:

<xforms:bind id="{tagName}-bind" nodeset="{tagName}" name="..."/>

org.orbeon.saxon.trans.XPathException: An empty sequence is not allowed as the value of variable $section-holder

Проблема: при попытке получить pdf-ку из заполненной в orbeon формы вместо pdf-ки вываливается исключение "org.orbeon.saxon.trans.XPathException: An empty sequence is not allowed as the value of variable $section-holder".

Причина:
  • где-то в форме есть секция (fr:section), bind которой не имеет id вида "{sectionRootTagInModel}-bind", где {sectionRootTagInModel} - имя тэга в модели, к которому привязана секция с помощью конструкции bind. Т.е. секции должны быть привязаны к элементам модели следующим образом: <xforms:bind id="{sectionRootTagInModel}-bind " nodeset="{sectionRootTagInModel}"> для секции, объявленой как <fr:section id="{sectionRootTagInModel}-section" bind="{sectionRootTagInModel}-bind"> (использование другого id самой секции вроде как проблем не вызывает). 
  • в форме используются вложенные друг в друга bind`ы. Секции вкладывать друг в друга можно, но вот bind`ы - нет (за исключением вложения всех биндов в общий бинд к корневому тегу модели).

Решение: всегда присваивать bind`ам секций id вида "{sectionRootTagInModel}-bind". Не использовать вложенные секции