#ConversationScoped bean behaves as #RequestScoped since OmniFaces 2.5 FacesViews - jsf

I tried to upgrade my Java EE 7 / JSF 2.2 application to Omnifaces 2.6. Currently I am running version 2.4.
After that, I have noticed a strange behavior when using #ConversationScoped and Ajax-Requests. When calling, the area, which should get rendered after the request, gets cleared (no exception on the server, response status code 200).
Next, I have a kind of wizard implementation, based on #ConversationScoped. It holds a class called ViewManager which has itself a List of Views. Initializing works fine and this list gets filled. But somehow it gets cleared (set to null) when the first form/view gets submitted. The setter for this is never called after the initialization, so it is not changed by my code. Somehow the view manager instance is still available, only this list of view within the view manager is null, which is kind of strange.
With omnifaces 2.4, everything did work fine (this is why I did not add some code of my wizard). I checked the changelog and noticed the MultiViews configuration when using ExtensionlessURLs. Don't know why this could effect my problem, but i tried it...with no success.
I have no idea what could be the problem, so maybe you can help me.
Thanks in advance :)

In OmniFaces, the FacesViews extensionless URLs feature got in version 2.5 an overhaul in order to support the so-called MultiViews as you can read on this blog.
During this overhaul I made a backwards compatibility mistake in the FacesViewsViewHandler where the <h:form> action URL is being manipulated in order to include the virtual folders of the MultiViews feature. The query string parameters were dropped from the original action URL and not added back.
The #ConversationScoped relies on the cid request parameter being present in the <h:form> action URL as in /context/page?cid=1. This thus became /context/page and therefore the conversation isn't retained across postbacks.
I will fix this in next OmniFaces release, for now you can get back the desired behavior by adding the below context parameter to web.xml.
<context-param>
<!-- Workaround for disappearing #ConversationScoped ?cid= parameter -->
<!-- This can be removed in next OmniFaces version after 2.6 -->
<param-name>org.omnifaces.FACES_VIEWS_VIEW_HANDLER_MODE</param-name>
<param-value>BUILD_WITH_PARENT_QUERY_PARAMETERS</param-value>
</context-param>
This parameter triggers a different way of building the URL whereby the entire query string from the original action URL is explicitly retained.

Related

Trinidad/ADF Faces, file upload, EOFException

I use JSF 2.3 (Mojarra 2.3.3), Trinidad (2.2.1) and its file upload component (tr:inputFile) in a web.xml-version 3.1 on a Tomcat 8.5 server.
I get following exception and no valid uploaded file (i.e. the "value"-binded bean attribute remains null):
java.io.EOFException: null
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler._readLine(MultipartFormHandler.java:253) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler._readLine(MultipartFormHandler.java:237) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler._skipBoundary(MultipartFormHandler.java:223) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler.<init>(MultipartFormHandler.java:102) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.share.util.MultipartFormHandler.<init>(MultipartFormHandler.java:75) ~[trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.config.upload.FileUploadConfiguratorImpl.beginRequest(FileUploadConfiguratorImpl.java:139) [trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl._startConfiguratorServiceRequest(GlobalConfiguratorImpl.java:763) [trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.config.GlobalConfiguratorImpl.beginRequest(GlobalConfiguratorImpl.java:244) [trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:178) [trinidad-impl-2.2.1.jar:2.2.1]
at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92) [trinidad-api-2.2.1.jar:2.2.1]
(Info: The JSF 1.2 version with Trinidad 1.2.14 with web.xml-version 2.5 on Tomcat 6 or a Weblogic 10 does not have this problem.)
While searching for a solution I found that this seems to affect not only my concrete situation, but also:
ADF Faces (at least 12.x)
Trinidad 2.1
JSF 2.x in general
Wildfly (10.1)
Searching for an answer I developed a solution I want to share.
Use JSF's <h:inputFile> (since JSF 2.2) instead of <tr:inputFile>.
You may continue to use <tr:form usesUpload="true">, but see notes below.
In the backing bean you have to simply replace org.apache.myfaces.trinidad.model.UploadedFile with javax.servlet.http.Part and use getSubmittedFileName() instead of getFileName().
With this, file upload already works, but the EOFException still occurs and is logged (but ignored internally).
To prevent the needed TrinidadFilter (configured in web.xml) from processing the file upload, add your own javax.servlet.Filter (most apps will already have one, I guess) and put in its doFilter():
request.setAttribute("org.apache.myfaces.trinidadinternal.config.upload.FileUploadUtils.PROCESSED", Boolean.TRUE);
Of course, your filter must be executed before the TrinidadFilter, so either use a broader filter-mapping or place it before TrinidadFilter in your web.xml.
Additional notes:
When using <tr:form> the <h:inputFile> will output the wrong error/warning "File upload component requires a form with an enctype of multipart/form-data" via FacesMessage - but not for javax.faces.PROJECT_STAGE Production.
You may simply ignore it in development or use <h:form enctype="multipart/form-data"> instead. But note: <h:form> is a naming container and <tr:form> is not, so addressing input elements differs (hformId:inputId instead of simple inputId)
If your <tr:inputFile> is used inside a <tr:panelFormLayout>, put the <h:inputFile> inside a <tr:panelLabelAndMessage> and put the label there.
CSS styling for af|inputFile::content must also be done for input[type="file"].
See also:
https://stackoverflow.com/a/27681292/5074004
https://developer.jboss.org/thread/274824?_sscc=t
http://myfaces.10567.n7.nabble.com/Trinidad-File-upload-issue-td30231.html

JSF: Mojarra vs. OmniFaces #ViewScoped: #PreDestroy called but bean can't be garbage collected

This question is specific to the OmniFaces #ViewScoped bean (however of interest to wider discussion about memory leakage and resource disposal with JSF #ViewScoped). It is based on the results of this NetBeans8.1 test web app available on GitHub:
Investigation of undesirable holding of references to various forms of JSF #ViewScoped beans by navigation type
https://github.com/webelcomau/JSFviewScopedNav
That test web app has a comprehensive README with complete instructions, as well as annotated test web pages comparing obsolete JSF2.0-style #ManagedBean #ViewScoped, JSF2.2-style CDI-friendly #Named #ViewScoped, and OmniFaces #Named #ViewScoped beans.
The results using JVisualVM for diagnosis are summarised in a downloadable spreadsheet (see also screenshot below), and indicate that while the OmniFaces-2.5.1 #ViewScoped bean invokes #PreDestroy methods under GET-based navigation cases when leaving a view (giving the opportunity to release most resources), it does not seem to permit garbage collection of the actual bean (at least not with the current context parameter settings).
In web.xml the application is set to use:
com.sun.faces.numberOfViewsInSession 4
com.sun.faces.numberOfLogicalViews 4
By default this OmniFaces-specific parameter is commented out:
org.omnifaces.VIEW_SCOPE_MANAGER_MAX_ACTIVE_VIEW_SCOPES
The javax.faces.STATE_SAVING_METHOD defaults to 'server'.
The main question is:
Q1: Is it correct that these OmniFaces #ViewScoped beans can't by design be garbage collected "live" (meaning through say provocation using a Profiler's garbage collectiong action, not waiting until a session is over) ?
Q2: If this is so, how can (should) one best force release of them on navigating away from pages (especially under GET navigations) ?
Q3: If not so (if my results are incorrect because of some other setting) why aren't I witnessing provoked garbage collection of them, and what can I do to ensure they are indeed automatically released ?
Since the test web app is downloadable, well documented and hopefully self-explanatory, I won't give code here, but simply the comparitive results so far, as well as screenshots of the test web app pages in action:
The cause of this problem seems to be due to strange behaviour JVisualVM when attached to Glassfish/Payara.
The test case used for this question is still extremely useful, however the conclusions concerning Garbage Collection in the original post (and images) were based on JVisualVM, and I have since found they are not valid.
Use the NetBeans Profiler instead !
I am now getting completely consistent results for OmniFaces ViewScoped with the test app on forcing GC from within the NetBeans Profiler (with 1 omnifaces view scoped bean left per open tab).
When using JVisualVM attached to GlassFish/Payara I am getting references still held (even after #PreDestroy called) by field sessionListeners of type com.sun.web.server.WebContainerListener within ContainerBase$ContainerBackgroundProcessor, and they won't GC.
The image shows a screenshot of JVisualVM attached to Payara with only 1 tab open but still 9 OmniViewBean instances held, no matter how often GC is forced.
Updated results table using Mojarra-2.3.0 vs OmniFaces-2.6.6 in NetBeans IDE 8.2 Profiler
Updated test app sequence:

When does mojarra adds a naming container to the list of optional parameters?

In the source of the class AjaxBehaviorRenderer (line 260) there is a line that apparently appends the NamingContainer Id to the list of optional parameters of mojarra.ab(...). I've never come across it so I'm curious as to when it is used:
RenderKitUtils.appendProperty(ajaxCommand, "com.sun.faces.namingContainerId", namingContainerId, true);
line 260
While working on spec issue 790 last week, which should solve a.o. Rendering other form by ajax causes its view state to be lost, how do I add this back?, this was explained to me by Neil Griffin, a portlet guy.
It appears that portlets can have multiple JSF views rendering to the same HTML document, each with its own view state. In portlets, there's a special UIViewRoot instance which implements NamingContainer. During regular rendering, all forms, inputs and commands will have IDs and names prefixed with the view's own client ID. This will work fine during synchronous postbacks. The portlet can this way identify the exact view to restore.
However, during asynchronous postbacks, the jsf.js will create a bunch of additional ajax-specific request parameters such as javax.faces.source, javax.faces.partial.event, etc. Those request parameter names are not prefixed with the view's own client ID. Therefore the portlet cannot associate them with a specific view. Hence the impl issue 3031.
There was another problem of view state identifiers in ajax responses not being properly namespaced this way. Therefore the portlet implementation had to customize the partial response writer in the so-called "JSF bridge". This will be taken into account during implementing spec issue 790. Instead of sniffing a "portlet environment" as in current implementation, there will be checks on UIViewRoot instanceof NamingContainer which is more flexible and portlet-independent. The Mojarra-specific com.sun.faces.namingContainerId will also be removed. Instead, this value will be rendered to <partial-response id="..."> so that the jsf.js can just extract from there.
All in all, not really important if you're only targeting servlet based environments.
As per balusC comment :
It's only interesting for portlet based apps (not servlet based apps).
I can't exactly explain why and what it is used for (a portlet/liferay
guy might), but the portlet specific feature is called "namespaced
parameters". See https://web.liferay.com/web/meera.success/blog/-/blogs/liferay-requires-name-spaced-parameters

JSF / EL occasional failure to resolve action method

Environment:
JSF 2.1.11
el-api 2.2
Eclipse Kepler
Tomcat 7
Chrome
IE-11
I have a working xhtml and bean which contains several action methods and work fine.
I added another commandButton:
<h:commandButton id="idBtnSave" value="Save"
action="#{imageMetadataEditProvider.saveLabelWithBox}"></h:commandButton>
...and the action method:
public void saveLabelWithBox() {
saveBoundingBox();
saveImage();
}
... then for some inexplicable reason, EL cannot find method saveLabelWithBox on the bean.
I did several rounds of renaming the method, rebuilding, undeploying and cleaning the Tomcat environment, redeploy. That almost always failed.
HOWEVER, What seemed to work was simply to move the saveLabelWithBox(){} block to elsewhere in the bean. Suddenly, it worked again, so I gullibly renamed the method to something more meaningful, then it failed again... EL could not find the method. So I again renamed it and moved it, rebuilt, redeployed, now it works again.
I'm curious whether others have had such quirky behavior and what you think might cause this, beyond the typical suspects of corrupt Eclipse workspace, or being on a microwave beam path.
I finally resolved this quirky problem which seemed related to corruption in the environment. The cure seemed to be to create a new bean with a different name and import all the methods from the formerly unreliable bean. I also did the usual Eclipse -clean startup, although that seemed to have no effect. I also removed the Eclipse .metadata and restarted, although that also seemed to have no effect.
Oddly, after building a new replacement bean, it would not load via annotations:
#ManagedBean
#ViewScoped
...so I was obliged to define the replacement bean in faces-config, and then it would load at page request time. I think there is still something screwed up in the environment. But all the methods are now being resolved and it's been working OK for a couple of days.
Your mileage may vary.

How JSF manages the lfecycle of an UI component

In this beginner's JSF tuorial
section 1.1 says:
JSF UI components and their state are represented on the server with a defined life-cycle of the UI components.
But in the example that follows, I am unable to see how the state of an UI component is managed by the server? The example looks like a standard servlet jsp example minus the servlet mappings.
My other question is that in the example, we are accessing the jsp directly. Is this the standard thing to do in JSF as opposed to using servlet mappings?
First of all, if you're a beginner, I encourage you not to look at that old tutorials and find a good JSF 2.x one. JSF 2 was released in 2009 and you should consider it as the branch to learn, as it brings several advantages comparing with 1.x old versions.
JSF has its own lifecycle for any request you make from the browser which can be a GET or POST request, even an ajax based one. What you basically have to understand about JSF comparing with other frameworks is that it's stateful. In other words, you can keep a component's state from one request to another (you actually have a view state, which can be kept no matter how many requests you do, until you change the view).
Appart from that, about your last statement, in old JSF ages the servlet mapping used to be done over .*jsf suffix. It means, when you make a request for that in the browser, jsf will convert the matching jsp page and display it.
JSF 2 however introduced facelets, which are based in .xhtml view pages. It's now also possible to do the mapping as .xhtml having the source code in an .xhtml too and JSF will make the conversion. The main advantage for this is that end user will not be allowed to see the sources, as browser's request matches source page's url, so JSF servlet will always be invoked.

Resources