JSF f:事件preRenderView在模板f:元数据,监听器不被每个页面访问调用 [英] JSF f:event preRenderView in template f:metadata, listener not being called on every page access

查看:345
本文介绍了JSF f:事件preRenderView在模板f:元数据,监听器不被每个页面访问调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个带有监听器的@SessionScoped后备bean跟踪器void reset() 。



以下内容在使用template.xhtml的所有XHTML页面的f:元数据中都可以正常工作,例如/block/view.xhtml,它也需要查询参数ID:

 < f:view> 
< f:metadata>
< f:viewParam name =idvalue =#{blockManager.id}/>
< f:event type =preRenderViewlistener =#{tracker.reset}/>
< / f:metadata>
< / f:view>

< ui:composition template =/ template.xhtml>

如预期的那样,每当我加载(GET)或重新加载一个页面,无论什么id查询参数,#{tracker.reset}监听器被调用(通过调试日志记录显示)。



然而,在每个XHTML页面(其中有数百个),我首先尝试将其放在我的template.xhtml的f:metadata中。但是当我发生了一些奇怪的事情。它只调用#{tracker.reset}一次,第一次加载了/block/view.xhtml(无论id查询参数是什么),之后它再次被调用,直到我加载了另一个具有不同viewId的页面,例如/actor/view.xhtml或/block/list.xhtml或/index.html。



我使用#{facesContext.viewRoot.viewId }在template.xhtml中。从viewId的角度来看,查询参数id在区分使用不同id查询参数调用的不同块/ view.xhtml?id = [id]页面方面没有任何作用,viewId始终只是'/ block /view.xhtml'。



在写这个stackoverflow发布过程中,我发现了我的问题的解决方案:只需将f:event放在模板的元数据之外: .xhtml(我正在使用f:元数据在template.xhtml中进行f:事件的分组)。这在template.xhtml中有效:

 < f:metadata> 
..
< / f:metadata>
< f:event type =preRenderViewlistener =#{tracker.reset}/>
< h:head>

但我还有以下问题:



问:为什么我会在模板中的f:元数据中放置一个f:事件?



我问的原因是那里在Stackoverflow中有很多例子,它们使用f:模板中的元数据以及模板中的f:元数据中的f:事件。



BalusC在何时使用f:viewAction / preRenderView与PostConstruct?


每个HTTP请求都调用preRenderView事件。


这只是似乎是真的(按预期工作),如果我在f:metadata中的preRenderView f:最后的XHTML页面,或者外部的f:模板的元数据,但不在f:元数据模板中。



似乎有一些辩论是否应该f:事件在f:模板的元数据,或使用f:元模块中的元数据。

JSF2完整参考(Burns和Schalk)p.540状态:


f:metadata标签封装了用于指定Facelets视图的元数据的元素集,因此必须是子的f:view标签,可能不会出现在模板中。从JSF2.0起,这个标签的唯一目的是封装f:viewParam标签。


但是有很多例子f:在模板中使用的元数据的堆栈流,f:元数据中有很多f:事件的例子。这里也讨论过:



是否将f:event放在f:元数据中吗?



BalusC有助于解释:


..< f:event>并不是严格要求放在< f:metadata> ;.它可以附加到任何组件。 ..确实是纯粹的自我纪录的目的放在< f:metadata>每当你有一堆< f:viewParam> s并想挂钩< f:event>在所有这些视图参数设置完毕后调用一个动作。但是我上面的经验表明,放置和f:事件在一个f:元数据的模板中略有不同(奇怪的)行为。为什么?

解决方案

< f:metadata> 本身只能在模板客户端中使用,而不是在主模板中使用。即它必须在您通过URL实际请求的页面中声明,而不是在< ui:composition template> 之后的页面中声明,否则将被忽略。这个特殊的限制与< f:event> 无关。



另请参见:




Mojarra-2.1.3 as per Glassfish3.1.1 (distributed with Netbeans7.1)

I have a @SessionScoped backing bean Tracker with a listener void reset().

The following works fine in the f:metadata of all XHTML pages that use a template.xhtml, for example /block/view.xhtml, which also takes a query parameter id:

<f:view>
    <f:metadata>
        <f:viewParam name="id" value="#{blockManager.id}"/>
        <f:event type="preRenderView" listener="#{tracker.reset}"/>            
    </f:metadata>
</f:view>

<ui:composition template="/template.xhtml">

As expected, whenever I load (GET) or reload a page, and no matter what the id query parameter, the #{tracker.reset} listener is invoked (as revealed by debug logging).

However, it is tedious to have to include that f:event in every XHTML page (of which I have hundreds), I tried first instead to have it in the f:metadata of my template.xhtml. But when I did something strange happened. It only called #{tracker.reset} once, the first time /block/view.xhtml was loaded (no matter what the id query parameter was), and thereafter it was not called again until I loaded another page with a different viewId, such as /actor/view.xhtml, or /block/list.xhtml, or /index.html.

I examined the viewId using #{facesContext.viewRoot.viewId} in the template.xhtml. It is clear from the point of view of the viewId that the query parameter id plays no role in distinguishing between different block/view.xhtml?id=[id] pages called with different id query parameters, the viewId is always just '/block/view.xhtml'.

During the writing of this stackoverflow posting I discovered the solution to my problem: just place the f:event outside the f:metadata of the template.xhtml (I was using the f:metadata in the template.xhtml for grouping of f:events). This works in template.xhtml:

<f:metadata>
..
</f:metadata>
<f:event type="preRenderView" listener="#{tracker.reset}"/>
<h:head>

But I still have the following question:

Q: Why does it make a difference whether or not I place an f:event inside the f:metadata in a template ?

The reason I ask is that there are lots of examples here on Stackoverflow both of use of an f:metadata in a template.xhtml, and of an f:event inside an f:metadata in a template.

BalusC states at When to use f:viewAction / preRenderView versus PostConstruct?:

The preRenderView event is invoked on every HTTP request.

This only seems to be true (to work as expected) if I have the preRenderView f:event in the f:metadata of the final XHTML page, or outside the f:metadata of a template, but not inside the f:metadata of a template.

There seems to be some debate about whether one should have f:event in the f:metadata of a template, or use f:metadata in a template at all.

JSF2 Complete Reference (Burns and Schalk) p.540 states:

The f:metadata tag encapsulates the set of elements used to specify the metadata for a Facelets view, and therefore must be the child of the f:view tag and may not appear in a template. As of JSF2.0, the only purpose of this tag is to encapsulate f:viewParam tags.

But there are lots of examples on Stackoverflow of f:metadata being used inside templates, and there are lots of examples of f:event being used inside f:metadata. It is also discussed here:

Does it matter whether place f:event inside f:metadata or not?

Where BalusC helpfully explained:

.. the <f:event> is not strictly required to be placed inside <f:metadata>. It can be attached to any component. .. It's indeed for pure self-documentary purposes placed inside the <f:metadata> whenever you have a bunch of <f:viewParam>s and would like to hook a <f:event> to invoke an action after all those view parameters have been set. ..

But my experience above indicates that placing and f:event inside an f:metadata of a template gives slightly different (strange) behaviour. Why ?

解决方案

The <f:metadata> itself can only be used in the template client, not in the master template. I.e. it has to be declared in the page which you're actually requesting by URL, not inside the page behind <ui:composition template>, it will otherwise just be ignored. This particular restriction is unrelated to the <f:event>.

See also:

这篇关于JSF f:事件preRenderView在模板f:元数据,监听器不被每个页面访问调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆