我正在Orbeon2021.1.2PE中创建表单,并且在处理错误调用时遇到了问题。我正在通过表单生成器创建HTTP服务和操作。我希望能解决这个问题,并能和Builder呆在一起。我将API称为类似于Twitter的API,因此它还会返回用于业务错误的Error状态代码(请参见Doc.HTTP和https://developer.twitter.com/ja/docs/basics/response-codes )。最简单的例子是:如果我试图在数据库中找到一个如果不在数据库中的东西,我会得到代码404,在响应体中有一个详细的错误。
我需要一个状态代码+完整的正文(标题也会很好)到表单。我不想使用模式窗口(在Orbeon中是默认的)来处理这个调用。它干扰用户+调用经常更改整个工作流(可见的内容,等等)。有些调用甚至是异步的。
在Orbeon,解决这个问题的最佳方法是什么?我试了几样东西,在几个地方找了块东西。
(1)通过属性oxf.fr.detail.process.action-service-error.*.*解决
这里是设置默认错误模式窗口。我删除了它,发现我可以获得一些值并将它们写在表单中,例如:
xf:setvalue(ref="//control-1", value="event('response-status-code')")具体来说,这些价值观是:
event('error-type')
event('response-status-code')
event('resource-uri')
event('response-headers') - get specific via event('response-headers')[lower-case(name) = 'content-lenght']/value
event('response-body') - This not working, it is still supported?因为它是一个全局配置,所以我开始在哪里放置这些值。我试图创建自己的实例,但最终得到了fr:insert()函数。
我想为每个提交创建一个新实例,然后输入单独的值(event ('response-status-code'),.)。但是,使用fr:insert()的进程不起作用,而且文档中有糟糕的示例(https://doc.orbeon.com/form-runner/advanced/buttons-and-processes/actions-xforms#xf-insert)。
这做我想做的,但在形式上:
<xf:insert context="xxf:instance('HTTP-ERROR-RESULT')" ref="responses" origin="xxf:instance('HTTP-ERROR-TEMPLATE')"/>我试着把它转换成进程,但没有运气:
xf:insert(into="xxf:instance('HTTP-ERROR-RESULT')/reponses", origin="xxf:instance('HTTP-ERROR-TEMPLATE')")如果这是正确的方法?如何修复xf:insert()中的语义错误以及如何获得响应体(event ('response-body')不工作.)?并且是在过程中获取提交或操作名称的某种方法(例如,我需要一些id来查找)。
2]我尝试过的另一种方法是通过xforms-submit-error在submit中提交,但它也不起作用。在构建者创建的结构下:
<xf:action event="xforms-submit-done" ev:observer="echo-submission">
<xf:action class="fr-set-control-value-action">
<xf:var name="control-name" value="'control-2'"/>
<xf:var name="control-value" value="/*"/>
</xf:action>
</xf:action>我试着插入类似的东西,但是用xforms-submit-error
<xf:action event="xforms-submit-error" ev:observer="echo-submission">
<xf:action class="fr-set-control-value-action">
<xf:var name="control-name" value="'control-2'"/>
<xf:var name="control-value" value="/*"/>
</xf:action>
</xf:action>我发现在提交中使用class="fr-service"时,我无法捕获xforms-submit-error。因此,在构建器之外编写整个提交并使用xforms-submit-error是正确的解决方案。
或者,在Orbeon还有另一个优雅的解决方案吗?谢谢您的回复!
发布于 2022-05-18 18:50:40
编写自己的XForms将为您提供最大的灵活性。您可以直接将该XForms放在表单定义中,使用表单生成器中的Edit Source,也可以放在自定义模型中,它是服务器上磁盘上的文件,我建议您参阅文档。
你似乎找到了所有的片段(你做了一些很好的研究!),但这是一个总结。如果您有一个服务my-service,您可以侦听xforms-submit-error,并将事件属性值存储在您自己的实例中。如果使用自定义模型,该文件将具有以下内容,您还可以通过表单生成器中的Edit将<xf:model>的内容直接放在表单定义的<xf:model>中。在这里,逻辑只是将状态代码保存在实例my-error-instance中,然后使用<xf:message>来显示是否用于调试。
<xf:model xmlns:xf="http://www.w3.org/2002/xforms">
<xf:instance id="my-error-instance">
<_>
<status-code/>
</_>
</xf:instance>
<xf:action observer="my-service-submission" event="xforms-submit-error">
<xf:setvalue
ref="instance('my-error-instance')/status-code"
value="event('response-status-code')"/>
<xf:message value="instance('my-error-instance')/status-code"/>
</xf:action>
</xf:model>您还需要通过设置以下属性来禁用错误的默认对话框。
<property as="xs:string" name="oxf.fr.detail.process.action-service-error.*.*"/>最后,我将表单定义的完整源代码放在下面,您可以使用my-service HTTP服务对http://httpbin.org/status/404进行测试,并调用表单加载,用于测试上述自定义模型逻辑。
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:exf="http://www.exforms.org/exf/1-0"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder">
<xh:head>
<xh:title>Calling service returning a 404 on form load</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true" xxf:analysis.calculate="true">
<!-- Main instance -->
<xf:instance id="fr-form-instance" xxf:exclude-result-prefixes="#all" xxf:index="id">
<form>
<section-1>
<grid-1>
<control-1/>
</grid-1>
</section-1>
</form>
</xf:instance>
<!-- Bindings -->
<xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
<xf:bind id="section-1-bind" name="section-1" ref="section-1">
<xf:bind id="grid-1-bind" ref="grid-1" name="grid-1">
<xf:bind id="control-1-bind" name="control-1" ref="control-1" xxf:whitespace="trim"/>
</xf:bind>
</xf:bind>
</xf:bind>
<!-- Metadata -->
<xf:instance id="fr-form-metadata" xxf:readonly="true" xxf:exclude-result-prefixes="#all">
<metadata>
<application-name>a</application-name>
<form-name>a</form-name>
<title xml:lang="en">Calling service returning a 404 on form load</title>
<description xml:lang="en"/>
<created-with-version>2021.1-SNAPSHOT PE</created-with-version>
<library-versions>
<app>4</app>
</library-versions>
</metadata>
</xf:instance>
<!-- Attachments -->
<xf:instance id="fr-form-attachments" xxf:exclude-result-prefixes="#all">
<attachments/>
</xf:instance>
<!-- All form resources -->
<xf:instance xxf:readonly="true" id="fr-form-resources" xxf:exclude-result-prefixes="#all">
<resources>
<resource xml:lang="en">
<section-1>
<label>Untitled Section</label>
</section-1>
<control-1>
<label/>
<hint/>
<alert/>
</control-1>
</resource>
</resources>
</xf:instance>
<xf:instance id="my-service-instance" class="fr-service" xxf:exclude-result-prefixes="#all">
<body xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
xmlns:fbf="java:org.orbeon.oxf.fb.FormBuilderXPathApi"><params/></body>
</xf:instance>
<xf:submission id="my-service-submission" class="fr-service"
resource="http://httpbin.org/status/404"
method="get"
serialization="none"
mediatype=""/>
<xf:action id="my-action-binding">
<xf:action event="fr-run-form-load-action-after-controls" ev:observer="fr-form-model"
if="true()">
<xf:send submission="my-service-submission"/>
</xf:action>
<xf:action event="xforms-submit" ev:observer="my-service-submission">
<xf:var name="request-instance-name" value="'my-service-instance'"/>
<xf:action/>
</xf:action>
<xf:action event="xforms-submit-done" ev:observer="my-service-submission"/>
</xf:action>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:p="http://www.orbeon.com/oxf/pipeline" xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:oxf="http://www.orbeon.com/oxf/processors">
<fr:section id="section-1-section" bind="section-1-bind">
<xf:label ref="$form-resources/section-1/label"/>
<fr:grid id="grid-1-grid" bind="grid-1-bind">
<fr:c y="1" x="1" w="6">
<xf:input id="control-1-control" bind="control-1-bind">
<xf:label ref="$form-resources/control-1/label"/>
<xf:hint ref="$form-resources/control-1/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</fr:c>
<fr:c y="1" x="7" w="6"/>
</fr:grid>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
</xh:html>发布于 2022-06-20 16:16:13
基于@avernet的答案,我为xforms-submit-error创建了通用处理程序。首先,如前所述,我通过设置此属性禁用默认对话框。
<property as="xs:string" name="oxf.fr.detail.process.action-service-error.*.*"/>然后,我将自己的自定义模型放到WEB-INF/resources/forms/resources中。整个看起来是这样的:
<xf:model xmlns:xf="http://www.w3.org/2002/xforms" id="my-model">
<xf:instance id="my-error-instance">
<reponseList>
</reponseList>
</xf:instance>
<xf:instance id="my-error-template-instance">
<submission name="">
<status-code/>
<uri/>
<date/>
</submission>
</xf:instance>
<xf:action observer="fr-form-model" event="xforms-submit-error">
<xf:insert if="not(exists(xxf:instance('my-error-instance')//submission[@name=event('target')]))" context="xxf:instance('my-error-instance')" ref="reponseList" origin="xxf:instance('my-error-template-instance')"/>
<xf:setvalue if="not(exists(xxf:instance('my-error-instance')//submission[@name=event('target')]))" ref="xxf:instance('my-error-instance')//submission[1]/@name" value="event('target')"/>
<xf:setvalue ref="xxf:instance('my-error-instance')//submission[@name=event('target')]/status-code" value="event('response-status-code')"/>
<xf:setvalue ref="xxf:instance('my-error-instance')//submission[@name=event('target')]/uri" value="event('resource-uri')"/>
<xf:setvalue ref="instance('my-error-instance')//submission[@name=event('target')]/date" value="event('response-headers')[lower-case(name) = 'date']/value"/>
</xf:action>
</xf:model>注意两个条件(插入和第一个设置值)。因为它们,模型只保存一个提交的最后一个错误。如果出于某种原因,您可以删除它们。
https://stackoverflow.com/questions/72286412
复制相似问题