JSF (1.2) bug when reRender h:selectOneRadio - jsf

When I do a reRender via a4j:support of Richfaces (3.3.3) on a h:selectOneRadio, I have a strange behavior (not every time).
Here is my xhtml section with the h:selectOneRadio:
<h:selectOneRadio id="toto" value="#controller.toto}" >
<f:selectItem itemLabel="#{bundle['oui']}"
itemValue="#{true}" />
<f:selectItem itemLabel="#{bundle['non']}"
itemValue="#{false}" />
</h:selectOneRadio>
<rich:message for="toto" />
When I go in a browser I get this html code:
<table id="formulaire:toto" >
<tbody>
<tr>
<td>
<input id="formulaire:toto:0" type="radio" onchange="A4J.AJAX.Submit('formulaire',event,{'control':this,'similarityGroupingId':'formulaire:support','parameters':{'ajaxSingle':'formulaire:toto','formulaire:support':'formulaire:support'} } )" value="true" name="formulaire:toto">
<label for="formulaire:toto:0"> oui</label>
</td>
<td>
<input id="formulaire:toto:1" type="radio" onchange="A4J.AJAX.Submit('formulaire',event,{'control':this,'similarityGroupingId':'formulaire:support','parameters':{'ajaxSingle':'formulaire:toto','formulaire:support':'formulaire:support'} } )" value="false" name="formulaire:toto" checked="checked">
<label for="formulaire:toto:1"> non</label>
</td>
</tr>
</tbody>
</table>
Everything is fine.
But when this one is reRender by another component, the html changes and the first radio element is out of the table:
<input type="radio" onchange="A4J.AJAX.Submit('formulaire',event,{'control':this,'similarityGroupingId':'formulaire:support','parameters':{'ajaxSingle':'formulaire:toto','formulaire:support':'formulaire:support'} } )" value="true" id="formulaire:toto:0" name="formulaire:toto" checked="checked">
<label for="formulaire:toto:0"> oui</label>
<table id="formulaire:toto">
<tbody>
<tr>
<td>
<input type="radio" onchange="A4J.AJAX.Submit('formulaire',event,{'control':this,'similarityGroupingId':'formulaire:support','parameters':{'ajaxSingle':'formulaire:toto','formulaire:support':'formulaire:support'} } )" value="false" id="formulaire:toto:1" name="formulaire:toto"><label for="formulaire:toto:1"> non</label>
</td>
</tr>
</tbody>
</table>
It's a very strange behavior and it breaks my style.
Why the reRender breaks the html code ?
Thanks.

After many searchs, the bug comes from neko.
To optimize performances, I change the xml parse (tiny by default) by neko and this one can break the html.

RichFaces 3 AJAX responses are served with the Content-Type: text/xml header.
They are therefore supposed to be valid XML and are parsed as such on the browser side by the RichFaces JavaScript client code.
On the other hand, the HTML generated from templates is not required to be valid XML, so when RichFaces re-renders a fragment of a template, it tidies it up by default with the Tidy parser to avoid parsing issues on the client side.
It is often recommended to replace the Tidy parser with NekoHTML for better performance.
However, NekoHTML can go too far in the tidying process and break some RichFaces/JSF components, mostly those based on the HTML element.
For instance, since version 1.9.13, NekoHTML automatically adds TBODY around TR nested directly within TABLE.
Downgrading to the 5.5 year old version 1.9.12 reverts this behaviour and fixes re-rendering of components.
But this is not an option IMHO as lots of issues have been fixed over the last years.
From my experience, a better way to gain performance and avoid those issues is to :
ensure the re-rendered parts of your templates are valid XML
drop the tidying parsers
Corresponding web.xml snippet:
<context-param>
<param-name>org.ajax4jsf.xmlparser.ORDER</param-name>
<param-value>NONE</param-value>
</context-param>
To avoid breaking too much at once, the transition can be managed on a page by page basis using patterns:
<context-param>
<param-name>org.ajax4jsf.xmlparser.ORDER</param-name>
<param-value>TIDY,NEKO,NONE</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.xmlparser.TIDY</param-name>
<param-value>/pages/tidy/.*\.xhtml</param-value>
</context-param>
<context-param>
<param-name>org.ajax4jsf.xmlparser.NEKO</param-name>
<param-value>/pages/neko/.*\.xhtml</param-value>
</context-param>

Related

JSF datatable not complying to WCAG due to unsupported aria-label attribute

I am using JSF to code my application and it has a datatable.
Each row of the datatable has a checkbox in the first column, and some text in the rest of the columns.
My application needs to comply to the WCAG 2.0 and I'm using a Chrome Extension "Axe" to scan my application.
The "Axe" tool flagged out that the datatable with the checkboxes is not complying to the clause "Ensure every form element has a label" and the proposed solution is to add the "aria-label" attribute.
However JSF datatable does not have the "aria-label" attribute.
Would need to ask if any experts out there have any solution?
JSF 2.2 Support pass through attributes. So it's easy to add customized attributes into the primefaces tag.
Add tag reference at the top:
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
Declare it inside the primefaces tag:
p:inputText value="#{bean.value}" pt:aria-label="Whatever you want"
A checkbox needs a label, whether visible or not, in order for screen readers to announce the checkbox properly. For sighted users, having a column header in your table is sufficient as the label for the checkboxes below it. However, for screen reader users, unless you associate the column header with each checkbox, it won't be announced. Ignoring JSF for a moment, if you are writing straight html, you could have something like this:
<table border="1" style="border-collapse: collapse">
<tr>
<th scope="col" id="check_label">select me</th>
<th scope="col">some other value</th>
</tr>
<tr>
<td>
<input type="checkbox" aria-labelledby="check_label">
</td>
<td>hello</td>
</tr>
<tr>
<td>
<input type="checkbox" aria-labelledby="check_label">
</td>
<td>there</td>
</tr>
</table>
Each checkbox has an aria-labelledby attribute pointing to the column header ("check_label"). This works pretty well for most screen readers, but there are some cases where the checkbox label is not read, for example in NVDA if you are using the table navigation keys (ctrl+alt+arrow) and navigate down the checkbox column, the name is not read for the checkboxes. That could be a bug with NVDA, I'm not sure.
An alternative to the above is to have a visually hidden <label> specifically associated with each checkbox. This works whether you navigate the table using the TAB key or ctrl+alt+arrow.
<table border="1" style="border-collapse: collapse">
<tr>
<th scope="col">select me</th>
<th scope="col">some other value</th>
</tr>
<tr>
<td>
<input type="checkbox" id="check1">
<label for="check1" class="sr-only">select me</span>
</td>
<td>hello</td>
</tr>
<tr>
<td>
<input type="checkbox" id="check2">
<label for="check2" class="sr-only">select me</span>
</td>
<td>there</td>
</tr>
</table>
Now, getting back to JSF, of which I knew nothing about until I read this question, it looks like there are two ways to specify a checkbox, https://docs.oracle.com/javaee/5/tutorial/doc/bnaqd.html#bnaqh.
selectBooleanCheckbox
selectManyCheckbox
selectBooleanCheckbox, by default, does not have a label associated with the checkbox where as selectManyCheckbox does. However, you can also specify an <h:outputLabel> to be paired with the selectBooleanCheckbox so I think that's your answer. See the example in the selectBooleanCheckbox doc.
And with more recent versions of JSF you can also add the aria related attributes by using JSF Passtrough attributes (Spec)
So provided you add the right namespacedeclaration, you can do
<h:selectBooleanCheckbox pt:aria-labbeledby="check_label" ...>
But it can also be put on a datatable
<h:datatable pt:aria-labbeledby="check_label" ...>

How can I show/hide row of table in jsf? [duplicate]

I'm trying to conditionally render a <tr> therefore I cannot use <h:panelGroup> as it will render to <span> or <div>
My current (working) approach is the following:
<h:outputFormat rendered="#{negotiator.maySend}">
<tr> my tr stuff </tr>
</h:outputFormat>
This works, but I'm not sure if that's the way to abuse <h:outputFormat> - before that I used <h:outputLabel> but this was rendered to <label> in IE.
I have also read the answers to this question, but as mentioned above, they won't work for me because of the <tr>: How to not render whole block in JSF?
I cannot use <h:panelGroup> as it will render to <span> or <div>
Apparently you didn't test it carefully. The <h:panelGroup> won't render anything if you don't specify attributes which should end up in the client side, like layout, id, styleClass, etc.
Thus, this should technically perfectly work fine.
<h:panelGroup rendered="#{negotiator.maySend}">
<tr> my tr stuff </tr>
</h:panelGroup>
However, better for the main purpose would be to use <ui:fragment>.
<ui:fragment rendered="#{negotiator.maySend}">
<tr> my tr stuff </tr>
</ui:fragment>
This is by the way also possible with <f:verbatim>, but this is deprecated since JSF 2.0 as it's designed specifically for usage in JSP.
See also:
Alternative to ui:fragment in JSF
Conditionally displaying JSF components
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
Ajax update/render does not work on a component which has rendered attribute

Content of <f:view> not visible when using "Inspect element" in webbrowser

I'm using JSF and Materialize to develop an e-commerce site. I had no problem so far: the form to insert new products in the db works fine, login and registration forms too. Now I'm trying to create a product's catalog, so I need to visualize on the page all the products, but the code isn't interpreted correctly. In inspect element, inside <div class="card-image"> there's no code.
Here's my products.jsp page:
<div class="row">
<div class="col s12 z-depth-3">
<div class="card">
<div class="card-image">
<f:view>
<h1>Products</h1>
<h:form>
<table>
<tr>
<th>Name</th>
<th>Price</th>
</tr>
<c:forEach var="product" items="#{productController.products}">
<tr>
<td><h:commandLink
action="#{productController.findProduct}"
value="#{product.name}">
<f:param name="id" value="#{product.id}" />
</h:commandLink></td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
</h:form>
</f:view>
</div>
</div>
</div>
</div>
That's the page on the browser:
Instead if I use only the JSF code it works fine. Do you know how to fix that problem? Thank you all.
Don't use HTML DOM inspector in webbrowser to explore the JSF-generated HTML output. The HTML DOM inspector only shows browser's interpretation of the raw HTML output. In case browser doesn't recognize a certain element as per the doctype, or misses an element while it's expected as per the doctype, or finds an element in the wrong place as per the doctype, then the average webbrowser will leniently hide, autoinsert or move it (otherwise surely half of Internet would be broken).
Always look at raw HTML output by rightclick and View page source (or press Ctrl+U in Chrome) in case you want to explore the real JSF-generated HTML output.
My bet that you still see unparsed JSF/JSTL tags in there. This question is then already answered in JSF returns blank/unparsed page with plain/raw XHTML/XML/EL source instead of rendered HTML output. That HTTP 500 error in your browser console confirms this more. You're opening the page using .jsp extension instead of whatever is being mapped on FacesServlet which is apparently /faces/*. Note that while the answer deals with JSP's successor Facelets (JSP is deprecated in JSF more than 5 years ago), the same principle applies to JSP as well. You need to ensure that the FacesServlet is invoked in order to get JSF tags to run. In case you actually got a HTTP 500 error on that, then you should read (or search) the exception and stack trace for the answer.

What is the JSF 2.0 code for handling user authentication?

The standard tutorials for J2EE 6 show the handling of user authentication as follows:
<form method="POST" action="j_security_check">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="right">Username: </td>
<td>
<input type="text" name="j_username">
</td>
</tr>
<tr>
<td align="right">Password: </td>
<td>
<input type="password" name="j_password">
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Login">
</td>
</tr>
</table>
</form>
The approach uses the special container function "j_security_check" with special fields "j_username" and "j_password".
* Would this be possible to do in JSF 2.0 ?
* Are the j_username/j_password fields available after successful authentication? More precisely, how do I identify the user after they have authenticated?
Any simple, example code snippets would be much appreciated.
Would this be possible to do in JSF 2.0 ?
Yes. It's after all just a bunch of HTML and the container is the one who's doing the authentication, not JSF itself. An alternative is programmatic login by HttpServletRequest#login(). This allows you to use a fullworthy JSF form with JSF based validation, ajax fanciness and all on em. See also this answer for a kickoff example: Does JSF support form based security
Are the j_username/j_password fields available after successful authentication? More precisely, how do I identify the user after they have authenticated?
Only the username is in JSF context available by ExternalContext#getRemoteUser() and in views by #{request.remoteUser}. The password is not available for obvious security reasons.
Quite some time ago I tried to accomplish a jsf (1.2) login page with spring security. However as I did not succeed I finally gave up and did it with a "regular" jsp as you're doing it above.
You can identify the current user by injecting the current SessionContext into your EJB:
#Resource
SessionContext sessionContext;
public void doSth() {
log.info("The current user's name is: "
+ sessionContext.getCallerPrincipal().getName() );
}
You can do the same on HttpServletRequest:
request.getUserPrincipal();
Or from FacesContext:
FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();

Calling servlet post from jsf in different war

I want to call a Servlet which exists in a different war from my war. When user clicks a button we need to call the post method of the servlet. To implement this I did see an existing example which is slightly different but works in that case.
I am using jsf, so in the jsp there is a h:form with another html form inside of it. Below is the code:
<h:form>
<div id="gform" class="column span-20 append-1">
<h:outputText value="Text." /><br/><br/>
<h:commandLink id="addPaymentButton" styleClass="button" onclick='autorenew();return false;'> <span><h:outputText value="Payment Option"/></span> </h:commandLink>
<a id="noThanksButton" href="#"><span><h:outputText value="No Thanks"/></span></a><br/><br/><br/>
<h:outputText style="color:grey" value="Some text" />
<div> </div>
</div>
<form id="hiddenSubmit" method="post" action="https://localhost.myapp.com/myapp/LoginRouter" >
<input type="hidden" name="redirectUrl" value="/myapp/customers/addNewSavedCCInfo.faces"/>
<input type="hidden" name="jump_message" value="IAmJumpingToCC"/>
<input type="hidden" name="jump_url" value="/premiumServices/myPage.htm"/>
<input id="hiddenSubmitButton" type="submit" name="submit" style="display: none" value='' />
</form>
</h:form>
<script language="javascript">
function autorenew(){
window.alert('In js fnt');
document.hiddenSubmit.getElementById('hiddenSubmitButton').click();
window.alert('In js fnt COMPLETE');
return false;
}
So when the button is clicked, javascript is executed which submits the form to the servlet. However I can see in firebug that the second form which I need to submit does not appear. I am not sure how I can call the post method of a servlet class in a different war. Any ideas welcome, I am really stuck!
Thanks.
As per the HTML specification it's forbidden to nest <form> elements. The (mis)behaviour is browser dependent. Some browsers will send all parameters, some browsers will send only the data of the parent form, other browsers will send nothing.
You want to have a single form here. You can perfectly replace the <h:form> by a plain vanilla HTML <form> with the desired action pointing to the servlet in question.

Resources