Selenium and JSF 2.0 - jsf-2

When I a generate SelectOneMenu with JSF2.0 the the id I specified in the xhtml is attached to a generated ID from JSF.
e.g. out of my_fancy_id it generates j_idt9:my_fancy_id
Now I want to test my page with Selenium 2 Web Driver. I try to re-find my select menu:
driver.findElement(By.id("my_fancy_id"));
Of course it does't find anything because the id is changed. What is the best way to find the select menu on the page?

Usually the id of the form is prepended to all element ids inside the form. If you don't set a form id, JSF does it for you (the 'j_idt9'). Solution: Assign an id to your form and try to use the full id in your findElementmethod, e.g.:
<h:form id="myForm">
...
</h:form>
Call it this way:
driver.findElement(By.id("myForm:my_fancy_id"));

or you can add <h:form prependId="false"> so that the id of the form does not get prepended

You set the component identifier on controls; the renderers emit the client identifier to the markup.
This allows JSF to emit valid HTML ids (they must be unique) even in the face of templates and complex controls. A control will be namespaced by any parent that is a NamingContainer (such as a form).
In some containers, the client identifier will be namespaced by the view, but this generally only happens in portlet environments.
Some component libraries (like Tomahawk) have a forceId attribute, but care must be exercised in using them. I wrote a more extensive post on client identifiers here.

Related

How can I use a shared error message Dialog in PrimeFaces

In PrimeFaces, when you want to show an error Message you can:
create in View a command Component that calls an action
in 'update' attribute, you set the id of the p:message or p:growl component that will display the message
in The backing Bean, in the action function you throw a message
As a result, the error message will be displayed in the redirect page, in the message component with the matching id
But what if :
You want to display the message in another page, that doesn't contain the command component that called the action.
The action can redirect to lots of different pages, depending on some Backing bean Logic.
The action is not called from a command Component, at least not directly
I've thought of putting a p:message component with a specific id, and include it in every xhtml page. But this would not necessarily cover the 3rd scenario.
For example, there could be a function that checks the connection to another Web Service. A Connection error could be thrown from lots of different Actions.
Or a session expiration
Or a denial of permission
How would you manage this kind of generic error messages ?
You could put the common <p:dialog> or <h:message> in a template file which is being used for all pages and give it a unique id. That way, it will be rendered for all the pages using that template.
This, is assuming that you're using templates that is.
UPDATE: If you wish to programmatically update the component, you can do so using RequestContext#update()
For e.g.
if (someErrorCondition) {
RequestContext.getCurrentInstance().update("errorDialogId");
}
where errorDialogId is the ID of the common error dialog.
If you intend to use this approach, you need to remove the update atribute from your command component.
See Also
Calling Primefaces dialog box from Managed Bean function
Why not use the RequestContext#showMessageInDialog(FacesMessage)?
As per their User Guide:
Displaying FacesMessages in a Dialog is a common case where a
facesmessage needs to be added to the context first, dialog content
containing a message component needs to be updated and finally dialog
gets shown with client side api. DF (Dialog Framework) has a simple utility to bypass
this process by providing a shortcut;
Using this you don't need to have additional codes to put in every page you have. Just add it in your beans.

Open a new tab don't create new ViewAccessScoped bean

I have a sample use case: I have an edit page that use GET parameter "id".
eg. edit?id=1
This edit page is backed by a ViewAccessScoped (CODI) Bean.
In this edit page, I have a datatable with links that link to the same "edit" page, but with another id. (eg. edit?id=2)
<h:link value="#{mecaPart.id}" outcome="edit" target="_blank">
<f:param name="id" value="#{mecaPart.id}" />
</h:link>
The problem, is that the window open correctly, but it is the same bean that is used! And so I am editing the same part...
I have placed a log in #PostConstruct, and it is the same bean reference that is called multiple times. (even with the new ID!)
My question, how can I tell JSF to create a new ViewAccessScoped backing bean when I click the link, and not re-use the actually used one?
Finally, I discovered that #ViewScoped CODI bean did not preserved the backing bean from page refresh. So, I have to use ViewAccessScoped.
According to Gerhard Petracek: http://os890.blogspot.fr/2011/08/scopes-view-scope-vs-view-access-scope.html
the view-scope of jsf2+ is bound to a concrete jsf page. that means: as soon as you navigate to a different page, the state gets lost. that's better than nothing, but not useful for a lot of use-cases. the main use-case which needs it are ajax-requests on a page and the data used by them aren't needed on other pages, but it's pretty easy to break it e.g. with a browser-refresh on a page which stores the data in a view-scoped bean and has no form with input components. (in a previous blog post i described how to use the infrastructure provided by codi to create a session based view-scope to overcome such disadvantages cause by storing view scoped beans as part of the tree-state.)
like with the view-scope view-access-scoped beans are available on a page, but they also exist for the next page. that means: they are forwarded to the next page and get destroyed autom. if they don't get used during the first request of the next page. that's e.g. useful for wizards. if you have a wizard page which doesn't use the bean or you have to support the possibility to interrupt a wizard, you can use the grouped-conversation scope (and even the window-scope) provided by codi. however, due to the powerful api of codi you can also destroy the scope manually at any time (if needed).
So, to solve the problem of opening a new tab with another "ID", I had to set "CODI Client Side WindowHandler", according to the CODI Wiki.
https://cwiki.apache.org/confluence/display/EXTCDI/JSF+WindowHandler
So I added:
<alternatives>
<class>org.apache.myfaces.extensions.cdi.jsf.impl.scope.conversation.ClientSideWindowHandler</class>
</alternatives>
To the file beans.xml, and I used #ViewAccessScoped. Everything is working smoothly now.
You can use #ViewScoped which also works in CODI

Wrong JSF 2 ID Chaining

Situation
JavaServer Faces Version: 2.1.6
I got a parent composite component with two nested cc. One of them contains a HtmlPanelGroup, which has a component binding. I use that binding to programmatically add HtmlCommandLink-Objects to the HtmlPanelGroup.
Let's call some IDs:
PARENT for the parent cc
CHILD_FIRST for the first child cc, nested in PARENT
CHILD_SECOND for the second child cc, nested in PARENT
GROUP for the PanelGroup, nested in CHILD_SECOND
LINK_1 for the first HtmlCommandLink-Object, progammatically added to GROUP
Expectation
I expect the following ID Chaining (with default javax.faces.SEPARATOR_CHAR):
PARENT (Composite Component, declarative)
PARENT:CHILD_FIRST (Composite Component, declarative)
PARENT:CHILD_SECOND (Component Component, declarative)
PARENT:CHILD_SECOND:GROUP (HtmlPanelGroup, declarative)
PARENT:CHILD_SECOND:GROUP:LINK_1 (HtmlCommandLink, programmatically)
Problem
The ID of the HtmlCommandLink-Object is wrong at the first page visit. Instead of "PARENT:CHILD_SECOND:GROUP:LINK_1" the ID is only "CHILD_SECOND:GROUP:LINK_1". After I refresh the page the ID is correctly "PARENT:CHILD_SECOND:GROUP:LINK_1". In fact every component in the second composite component ("CHILD_SECOND") is missing the first part of the ID ("PARENT"). After refresh all IDs are correctly.
Solution
I might automatically refresh the page after the first visit. But I don't want to.
the id after interpreted by the browser doesn't like what you thought. as far as i know it doesn't exceed 3 levels. For example:
<h:form id="form">
<h:panel id="panel">
<h:panel id="panel1">
<h:label id="lab"/>
</h:panel>
<h:panel id="panel2">
</h:panel>
</h:panel>
</h:form>
then the label's id will not be form:panel:panel1:lab but form:panel:lab. if the widget that you want to get the id is more deeper, then i can't tell but it won't exceed 3 levels. i can tell you how to find the id.
you can just write the page, and then view it on the chrome or firefox where you can see the source code after interpreted. so you can get the id you want.
good luck!

Dynamically added option in SelectOneMenu control on a JSF form submits as null

I have a standard JSF h:form which contains an h:SelectOneMenu control. As long as I am selecting an item from the list which is populated when the page is rendered it works perfectly. I don't think it is important, but to put it in context, the value from the select is used to build a query which returns a list of matching records.
I've implemented the JQuery autocomplete box on the control and it still works just fine as long as I'm selecting one of the original values.
The problem comes when I enter a value not in the select control when the page is rendered. Using JQuery, I've set it up so that when a value not on the list entered, the value is added to the select as a new option.
I can verify that the option is added to the underlying select control, and selected through the javascript. However when the setter is invoked in the backing bean immediately after that, the value passed in to the setter is null, and the function to run the query is never reached. The following error is returned in the AJAX response, but I have yet to be able to find a place where the value is validated. It isn't a required field either.
Validation Error: Value is not valid
Here is my front end code:
<h:selectOneMenu id="make" styleClass="combobox" value="#{listBean.make}"
effect="fade" label="#{listBean.makeLabel}" >
<f:selectItems value="#{listBean.makeList}" />
</h:selectOneMenu>
And the setter in the bean:
public void setMake(String make) {
this.make = make;
}
I'm guessing I just need to find a way to include the new option in the makeList List on the backing bean, but I'm not sure how to do that. Any help or suggestions would be appreciated.
Java EE 6, GlassFish 3.1, Eclipse 3.7 - problem observed on both FireFox and Chrome
You need to provide the dynamically added item through <f:selectItems>, not through JavaScript. If the item is not present in <f:selectItems>, then you will get exactly this validation error. This is done so as part of safeguard against tampered/hacked requests in an attempt to get illegal/unprovided values into the server side.
Easier is to use a JSF component library. PrimeFaces for example has a <p:autoComplete> for the exact purpose.

In Grails GSP, what is the equivalent to Spring MVC's <input name="entity.list[0].field">?

I'm coming from a Spring MVC background on a new Grails app. I have an object that contains a list of dependent objects. On the create and edit screen, I want to edit that object and its list of objects at the same time. In Spring MVC, you could use special names to bind the form fields to items in a list. Example:
Entity { String name, List items }
<form:input name="entity.items[0].value" value="${entity.items[0].value}"/>
I've tried similar variations in my GSP create and edit forms, but no luck.
I haven't used this with tag (is it a Java taglib?), but what you are doing is along the right path. I don't think you need the entity in there, the name should be just "items[0].value"
Here is some code I have that does what you need (using HTML input tag):
<input type="text" name="subItems[0].date"/>

Resources