Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

jsf - Process f:viewParam only on page load

I'm using an <f:viewParam> to pass a parameter as follows.

<ui:define name="metaData">
    <f:metadata>
        <f:viewParam name="id" value="#{bean.entity}" converter="#{converter}"/>
    </f:metadata>
</ui:define>

Is it possible to process this <f:viewParam>, only when the page is loaded/refreshed?

It is just because the converter as specified with the <f:viewParam> is costly that converts the value passed through the query-string to a JPA entity. Hence, it involves an expensive database transaction, even when doing ajaxical postbacks using components like <p:commandButton>, <p:commandLink> which is unnecessary.

So, when for example, a <p:commandLink> (ajaxical) is clicked, the expensive business service (in the converter) should not be executed. Can this be done?


This somehow works (strange enough nevertheless), when the rendered attribute is evaluated against facesContext.postback like rendered="#{not facesContext.postback}" but the attribute rendered is not documented. Hence, it is unreliable.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can achieve this by creating a custom tag extending <f:viewParam> wherein you store the submitted value as an instance variable which isn't stored in JSF view state instead of in the JSF view state as the <f:viewParam> by default does. By end of request, all UI component instances are destroyed. They are recreated in beginning of the request. When submitted value is null, then it won't call the converter nor the model setter. This all is elaborated in Arjan Tijms' blog.

OmniFaces offers already since version 1.0 a ready to use solution in flavor of <o:viewParam>, see also my own blog on that. Based on your question history, you're already using OmniFaces, so all you basically need to do is to replace f: by o:.

<ui:define name="metaData">
    <f:metadata>
        <o:viewParam name="id" value="#{bean.entity}" converter="#{converter}"/>
    </f:metadata>
</ui:define>

This won't call the model setter (nor the converter) during postbacks on the same view.


This somehow works (strange enough nevertheless), when the rendered attribute is evaluated against facesContext.postback like rendered="#{not facesContext.postback}" but the attribute rendered is not documented. Hence, it is unreliable.

That's because the <f:viewParam> is in essence an UIInput component (else it wouldn't be able to perform conversion, validation, model-update and all that stuff like usual input components) which is thus just an UIComponent supporting a rendered attribute. This is however not explicitly documented as it actually doesn't render anything to the HTML output (that's also why it's a f:xxx, not a h:xxx). But with this attribute you can actually control the behavior during postback as this attribute is also evaluated in processDecodes() method which is invoked during apply request values phase.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...