I'm getting this error with f:setPropertyActionListener and i can't figure out why:
HTTP Status 500 - For input string: "selectedItem"
exception:
javax.servlet.ServletException: For input string: "selectedItem"
javax.faces.webapp.FacesServlet.service(FacesServlet.java:667)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause:
java.lang.NumberFormatException: For input string: "selectedItem"
java.lang.NumberFormatException.forInputString(Unknown Source)
java.lang.Integer.parseInt(Unknown Source)
java.lang.Integer.parseInt(Unknown Source)
javax.el.ListELResolver.coerce(ListELResolver.java:157)
javax.el.ListELResolver.getType(ListELResolver.java:50)
com.sun.faces.el.DemuxCompositeELResolver._getType(DemuxCompositeELResolver.java:215)
com.sun.faces.el.DemuxCompositeELResolver.getType(DemuxCompositeELResolver.java:242)
org.apache.el.parser.AstValue.getType(AstValue.java:60)
org.apache.el.ValueExpressionImpl.getType(ValueExpressionImpl.java:168)
com.sun.faces.facelets.el.TagValueExpression.getType(TagValueExpression.java:98)
com.sun.faces.facelets.tag.jsf.core.SetPropertyActionListenerHandler$SetPropertyListener.processAction(SetPropertyActionListenerHandler.java:209)
javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:813)
javax.faces.component.UICommand.broadcast(UICommand.java:300)
javax.faces.component.UIData.broadcast(UIData.java:1108)
javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:654)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
Table Class:
// imports omitted
public class Table<E> extends ArrayList<E> {
private E selectedItem;
public E getSelectedItem() { return selectedItem; }
public void setSelectedItem(E value) { selectedItem = value; }
}
MyTable Bean:
// Imports omitted
#ManagedBean
#ViewScoped
public class MyTable extends Table<File> {
#PostConstruct
public void initBean() {
// Loading some files into the list
}
}
This is the XHTML:
<html> <!-- Namespaces and stuff omitted -->
<h:head>...</h:head>
<h:body>
<h:form>
<h:dataTable var="item" value="#{myTable}">
<h:column>
<h:commandButton value="Try Me!">
<f:setPropertyActionListener value="#{item}" target="#{myTable.selectedItem}"/>
<!-- I'm getting a warning from eclipse here: property not found -->
</h:commandButton>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
I'm using Eclipse Luna (Java EE IDE) with Tomcat 8 and JSF 2.2.11 (mojarra). Any hints are accepted, thank you!
You kind of coded your self into a corner with your fancy bean implementation. Take a look at the processing steps for the f:setActionPropertyListener. Your code is choking at step 3:
If the value of the "value" expression is not null, call getType() on the "value" and "target" ValueExpressions to determine their property types
for the following reasons:
The EL processor has determined that myTable is a List. Because of this, it has delegated the evaluation of the expression myTable.selectedItem to the javax.el.ListELResolver class
The ELResolver, on encountering the myTable base object, determines it's a List and automatically assumes that the following string is referring to a list index, i.e. myTable.selectedItem, where selectedItem is supposed to be a list index (per the EL specification, the [] and . are interchangeable for lists). You can see it in action here. While it may not be immediately apparent in the tomcat source, if you check the comment in a similar implementation in Jboss for example, you have the following comment:
If the base object is a list, returns the value at the given index. The index is specified by the property argument, and coerced into an integer
"property argument" here is referring to the selectedItem portion of your expression
The EL processor now attempts to convert the string selectedItem to an integer (to be used as a list index) which in turn explodes in a 500
You'll make your work a whole lot easier by not combining your data structure and your backing bean, like Rami. Q suggested. Much cleaner that way IMO
my Answer should be a comment, but its too long for that, so i write it as an answer.
i see some "ERRORS" in your code:
ALL JSF Beans & objects have to be Serializable
if you use Generic Types, they should be Serializable TOO:
public class GenericObject<T extends Serializable> implements Serializable {...}
Setter & Getter of a JSF Object should be like (this.attr = ...;):
public void setSelectedItem(E value) { this.selectedItem = value;}
be sure that you import the managedBean correctly:
import javax.faces.bean.ManagedBean;
instead of <h:dataTable var="item" value="#{myTable}"> you should use <h:dataTable var="item" value="#{myTable.items}">
and declare items as List Attribute of your bean with getter and setter
Related
The value in f:selectItem is an Integer (Const.DB_NEW_DATASET) but the output of testlistener is always java.lang.String. That's not what I had expected.
xhtml
<f:metadata>
<f:importConstants type="foo.bar.Const" />
</f:metadata>
<h:selectOneListbox value="#{viewScope.foo}">
<f:selectItem
itemValue="#{Const.DB_NEW_DATASET}"
itemLabel="foo" />
<f:selectItem
itemValue="#{Const.DB_NEW_DATASET}"
itemLabel="bar" />
<f:ajax listener="#{myBean.testlistener}" />
</h:selectOneListbox>
bean
#Named
#ViewScoped
public class MyBean implements Serializable {
#Inject
#ViewMap
private Map<String, Object> viewMap;
public void testlistener() {
System.out.println(viewMap.get('foo').getClass());
}
}
public class Const {
public static final Integer DB_NEW_DATASET = -1;
}
Mojarra 2.3.9.SP01
It's actually not "cast to java.lang.String" at all. It's just the default type of ServletRequest#getParameter() which is then left unconverted by JSF.
This is because the ValueExpression#getType() of #{viewScope.foo} returns java.lang.Object and thus JSF won't perform any automatic conversion against any registered #FacesConverter(forClass).
You need to explicitly specify the built-in javax.faces.Integer converter which is essentially a #FacesConverter(forClass=java.lang.Integer).
<h:selectOneListbox ... converterId="javax.faces.Integer">
This is not necessary if you're using e.g. #{bean.foo} with a private Integer foo, because this way the ValueExpression#getType() will return java.lang.Integer and thus JSF can find the built-in converter.
See also:
Why does JSF put String values in a Map<..., Integer>? And how to work around it?
Conversion Error setting value for 'null Converter' - Why do I need a Converter in JSF?
Following on from the response by the legendary BalusC to this post:
How to programmatically or dynamically create a composite component in JSF 2
Had I sufficient points I would attach a comment to that post -- but I don't have sufficient points .
Problem as follows.
I'm trying to set up a commandButton which adds a JSF composite component dynamically to an xhtml file. With the intention that clicking it multiple times will put multiple instances of the component on the page.
So I have a button on an XHTML file:
<h:commandButton action="#{assessingController.addQuestion}" value="Add a Question"></h:commandButton>
Which calls a method on AssessingController:
public void addQuestion() {
UIComponent parent = null;
includeCompositeComponent(parent, "http://xmlns.jcp.org/jsf/composite/components", "questionComposite", "someId");
}
UIComponent parent = null; -- because it has to be instantiated or referenced somehow, before being passed into includeCompositeComponent . But as noted below - making it null might be causing the null pointer exception, (so what should I do instead?)
includeCompositeComponent method is as per the JSF 2.2 method referred to by BalusC in the above post:
public void includeCompositeComponent(UIComponent parent, String taglibURI, String tagName, String id) {
FacesContext context = FacesContext.getCurrentInstance();
UIComponent composite = context.getApplication().getViewHandler()
.getViewDeclarationLanguage(context, context.getViewRoot().getViewId())
.createComponent(context, taglibURI, tagName, null);
composite.setId(id);
parent.getChildren().add(composite);
}
When I click on the commandButton, logs as follows:
javax.faces.el.EvaluationException: java.lang.NullPointerException
at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:101)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
at javax.faces.component.UICommand.broadcast(UICommand.java:315) ...
Caused by: java.lang.NullPointerException
at controllers.AssessingController.includeCompositeComponent(AssessingController.java:123)
AssessingController.java:123 is this line:
parent.getChildren().add(composite);
Composite is not null (checked that).
So, obviously perhaps, - parent is null and that's where the problem is.
So how can I better reference UIComponent parent to begin with?
Do I need to make it refer to something on the xhtml file? I'm presuming it needs some kind of a placeholder which will serve as the parent(?). Right now all there is on the xhtml page is the commandButton.
Thank you all.
The parent is supposed to represent the component where you'd like to include the composite component in.
Imagine that you ultimately want to end up with this plain XHTML representation:
<h:panelGroup id="questions">
<your:questionComposite />
</h:panelGroup>
You should then supply exactly that <h:panelGroup> component as parent.
<h:form>
<h:commandButton ... action="#{bean.addQuestion}" />
</h:form>
<h:panelGroup id="questions" />
public void addQuestion() {
UIComponent parent = context.getViewRoot().findComponent("questions");
// ...
}
Or, by passing the concrete component itself:
<h:form>
<h:commandButton ... action="#{bean.addQuestion(questions)}" />
</h:form>
<h:panelGroup id="questions" binding="#{questions}" />
public void addQuestion(UIComponent parent) {
// ...
}
Unrelated to the concrete problem: there's a thinking/design mistake here. You should rather use an <ui:repeat><your:compositeComponent> and then feed from a #ViewScoped bean to the <ui:repeat> a dynamically sized list of entities representing the composite's model value.
<h:form>
<h:commandButton ... action="#{bean.addQuestion}" />
</h:form>
<ui:repeat value="#{bean.questions}" var="question">
<your:questionComposite value="#{question}" />
</ui:repeat>
private List<Question> questions;
public void addQuestion() {
questions.add(new Question());
}
Anytime you need to deal with raw UIComponent instances in a backing bean, take a pause and carefully research or ask if you're really doing things the right way. Perhaps it belongs in a backing component instead, or could just be done with pure XHTML.
See also:
How to dynamically add JSF components
How does the 'binding' attribute work in JSF? When and how should it be used?
I have different objects which all implements the same interfaces. All of these objects need to be selectable by <p:selectCheckboxMenu/>. Default values for those objects and selected values are placed in same Map<?,?>, and few such Maps grouped together inside another Map. It sounds complicated but please look at the code below and all will be clear.
When I select an object, converter get a list of all objects from MyBean (CDI bean), looking by uuid required object and return it, without throwing any exception. The problem begins when I try to work with selected objects. For example this line of code inside:
onObjectChange() method from MyBean:
List<AllObjects> objects= objectContainer.getControllers().get("Object 1").get("selected");
throws an exception:
java.lang.ClassCastException: [Ljava.lang.Object; incompatible with java.util.List
And indeed when I hover mouse over objectContainer I see that it contains object of type selected=[Ljava.lang.Object;#dba1b6e7} But when I evaluate same line of code inside Expressions panel of Eclipse I get the required values: MyObject1#d8f0f5f8
I don't understand in general is it possible to do what am I doing, i.e. few different objects with same interface to be selectable by <p:selectCheckboxMenu/>. And if yes, why do I have this casting problem? My colleague said that it might be a problem with my converter and I tend to agree with she, but don't know is it correct and if yes, how to solve it.
UPDATE: It looks that problem not inside Converter but due to fact that I pass Collection to collect selected values dynamically, as a value of <ui:param/>. I pass it as List<AllObjects> and get it back as Object. I can cast it then to Object[] and every object inside it to appropriated object by using introspection and it works. But why it mutates initial object? It shouldn't do this.
Thank you in advance and my code below:
This is an interface:
public interfaces AllObjects{
public String getName();
}
There are multiple objects, MyObject, MyObject1, MyObject2 which implement interfaces above:
public MyObject implements AllObjects{
...
}
This is my bean and how my objects are initialized:
public MyBean {
Map<String, Map<String,List<AllObjects>>> objectContainer = new LinkedHashMap<String, Map<String,List<AllObjects>>>();
public void init(){
Map<String,List<AllObjects>> nameValuesPairs1 = new LinkedHashMap<String,List<AllObjects>>();
List<AllObjects> allSelectedObjects1 = new ArrayList<AllObjects>();
List<AllObjects> allDefaultObjects1 = new ArrayList<AllObjects>();
nameValuesPairs.put("default",allDefaultObjects1);
nameValuesPairs.put("selected",allSelectedObjects1);
Map<String,List<AllObjects>> nameValuesPairs2 = new LinkedHashMap<String,List<AllObjects>>();
List<AllObjects> allSelectedObjects2 = new ArrayList<AllObjects>();
List<AllObjects> allDefaultObjects2 = new ArrayList<AllObjects>();
nameValuesPairs.put("default",allDefaultObjects2);
nameValuesPairs.put("selected",allSelectedObjects2);
objectContainer.put("Object 1", nameValuesPairs1);
objectContainer.put("Object 2", nameValuesPairs2);
}
public void onObjectChange(){
...
List<AllObjects> objects= objectContainer .getControllers().get("Object 1").get("selected"); //throws exception
...
}
}
My *.xhtml page:
<h:panelGroup id="object_panel">
<ui:repeat id="objects_id" var="object" value="#{myBean.objectContainer.entrySet().toArray()}">
<p:selectCheckboxMenu
value="#{object.value['selected']}" label="#{object.key}"
converter="#{myObjectConverter}"
filter="true"
filterMatchMode="startsWith"
panelStyle="width:250px">
<f:selectItems value="#{object.value['default']}" var="value" itemValue="#{value}" itemLabel="#{value.name}" />
<p:ajax event="change" process="#this #parent" listener="#{myBean.onObjectChange}"/>
</p:selectCheckboxMenu>
</ui:repeat>
</h:panelGroup>
And converter:
public class ChartParameterConverter implements Converter, Serializable {
#Inject
private MyBean myBean;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
AllObjects result = null;
...
//here to result assigned MyObject1 or MyObject2 type depends on condition and it being returned
...
return result;
}
...
}
Ok, it looks that <ui:repeat> and <p:selectCheckboxMenu> not work well with DataModel which I used, Map<String,Map<String,List<MyObject>>>. I've changed my DataModel in the following way:
public ObjectContainer{
private String name;
private List<MyObject> defaultObjects;
private List<MyObject> selectedObbjects;
}
and pass to <ui:param> it as List<ObjectContainer>. so my *.xhtml page looks in the following way:
<p:selectCheckboxMenu
value="#{object.selectedObjects}" label="#{object.name}"
converter="#{myObjectConverter}"
filter="true"
filterMatchMode="startsWith"
panelStyle="width:250px">
<f:selectItems value="#{object.defaultObjects}" var="value" itemValue="#{value}" itemLabel="#{value.name}" />
<p:ajax event="change" process="#this #parent" listener="#{myBean.onObjectChange}"/>
</p:selectCheckboxMenu>
</ui:repeat>
And now everything works as it should.
And I throwed away my custom converter and use SelectItemsConverter from Omnifaces's library. Highly recommended change, code become much simpler and readable.
You could do a unique Tuple for each Object, The Tuple must be converted to unique String.. And you could have the posible values in a Array..
static Map<String,Object> uniques = new LinkedHashMap<>();
static{
//you could save the possible values in a Singleton Bean
uniques.put(key,value)...
}
In your Converter
getAsString -> Return a Key from Value
getAsObject -> Return a Value by Key
In my JSF 2.1 facelets environment, I would like to set a bean property of int type:
facelets template:
<c:set target="#{mybean}" property="size" value="3"/>
java setter:
public void setSize(int size){
this.size = size;
}
But it throws an exception:
javax.el.ELException: Can't set property 'size' on class 'MyBean' to value '3'.
at javax.el.BeanELResolver.setValue(BeanELResolver.java:398)
...
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
Looking into the code of BeanELResolver, I have noticed that the value "3" is unfortunately simply passed to the setter method without any coercion, which obviously does not work. It is a pity that BeanELResolver does not make use of the type knowledge it has there.
Is there a way to coerce the value to an int somehow? I already tried value="#{3}" but this yields a Long. Next thing that comes to my mind is value="#{f:toInt(3)}" using a custom function.
I tried to reproduce the problem you're having. I created a simple RequestScoped bean with a single property.
public class IndexBean {
private int value;
public void setValue(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Then When I used a defered expression (the one that starts with a #) within the target attribute...
<c:set target="#{indexBean}" property="value" value="5"/>
<h:outputText value="#{indexBean.value}"/>
...I received a JSP exception, saying
Its illegal to specify deferred expression for dynamic attribute.
...which lead me to change the expression to be immediate evaluated.
<c:set target="${indexBean}" property="value" value="5"/>
<h:outputText value="#{indexBean.value}"/>
...and the value was correctly shown on the screen.
How about using fmt:formatNumber?
<fmt:formatNumber var="i" type="number" value="3" />
<c:set target="#{mybean}" property="size" value="${i}"/>
when I try to render the view, browser show this error
01:46:11,371 GRAVE [javax.enterprise.resource.webcontainer.jsf.application] (http--127.0.0.1-8080-1) Error Rendering View[/index.xhtml]: javax.el.PropertyNotFoundException: /index.xhtml #15,74 value="#{actividades.getAll}": The class 'org.pfc.controller.principal.ActividadesController' does not have the property 'getAll'.
at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:111) [jsf-impl-2.1.5-jbossorg-1.jar:2.1.5-SNAPSHOT]
ActvidadController code
#ManagedBean(name="actividades")
#ViewScoped public class ActividadesController implements Serializable {
private static final long serialVersionUID = 1L;
private final static Log logger=LogFactory.getLog(ActividadesController.class);
#ManagedProperty(value="#{actividadBO}")
private ActividadBO actividad;
public void setActividad(ActividadBO actividad) {
this.actividad = actividad;
}
public List<Actividad> getAll(){
logger.trace("ActividadesController.getAll");
return actividad.getAll();
}
}
View code
<h:body>
<ui:composition template="/WEB-INF/templates/main-template.xhtml">
<ui:define name="content">
<h:dataTable value="#{actividades.getAll}" var="actividad">
<h:column>
<f:facet name="header">
<h:outputText>Título</h:outputText>
</f:facet>
<h:outputText value="{actividad.titulo}"></h:outputText>
</h:column>
</h:dataTable>
</ui:define>
</ui:composition>
</h:body>
I use JBOSS 7 and my project has el-impl2.2.jar,el-api.1.1.jar and icefaces3 libraries.
I don´t understand why the render not working.
Any suggestions?
Kind regards.
Here,
<h:dataTable value="#{actividades.getAll}" var="actividad">
Your EL expression is invalid. It's looking for a method getGetAll(), but you only have a getAll() method representing a getter for the (fictive) property all. The property doesn't need to exist at all (it's supposed to be private anyway).
So, to fix your problem, it must be
<h:dataTable value="#{actividades.all}" var="actividad">
or, if you're using EL 2.2 (but this way is not recommended)
<h:dataTable value="#{actividades.getAll()}" var="actividad">
Either way, it will call the proper getAll() method.
Unrelated to the concrete problem, you've by the way another design flaw in your code. A getter is invoked as many times as EL needs to resolve it. Doing business/database access job inside a getter method is a bad idea. A getter is supposed to just return bean properties. Rather move the DB job out to bean's (post)constructor.
private List<Actividad> all;
#PostConstruct
public void init() {
all = actividad.getAll();
}
public List<Actividad> getAll(){
logger.trace("ActividadesController.getAll");
return all;
}
See also:
Why JSF calls getters multiple times