1
votes

I have a JSF application, and everything is working fine, except for calling methods in the ManagedBean that have a object as parameter:

<p:dataTable value="#{sContr.privileges}" var="privilege">
    <p:column>
        <h:outputText value="#{privilege.name}"/>
    </p:column>
    <p:column>
        <h:outputText value="#{privilege.description}"/>
    </p:column>
    <p:column>
        <h:commandButton action="#{sContr.deletePrivilege(privilege)}" image="somePath"/>
    </p:column>
</p:dataTable>

In the sContr:

public void deletePrivilege(Privilege privilege) {
    System.out.println("test");
}

All methods, that do not have own defined objects, work (e.g. Maps, Strings, Lists, ...) and accessing the objects and even sub-objects in the xhtml works like a charm.
However, calling this deletePrivilege results in:

javax.servlet.ServletException: javax.el.MethodNotFoundException: [...]privileges.xhtml @31,138 action="#{sContr.deletePrivilege(privilege)}": Method not found: [...][email protected](java.util.LinkedHashMap)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:659)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
[...]

The objects are defined in another module than the JSF application and are normal java objects (no specific JSF annotations).

So, for some reason, JSF can't auto-convert the LinkedHashMap back to an instance of the class that was used to render the page.

faces-config.xml:

<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
    http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
              version="2.2">

    <managed-bean>
        <managed-bean-name>currentDate</managed-bean-name>
        <managed-bean-class>java.util.Date</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>

    <application>
        <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
    </application>
</faces-config>

The maven includes for JSF and primefaces:

<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-api</artifactId>
    <version>2.2.6</version>
</dependency>
<dependency>
    <groupId>com.sun.faces</groupId>
    <artifactId>jsf-impl</artifactId>
    <version>2.2.6</version>
</dependency>
<dependency>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <version>5.1</version>
</dependency>
<dependency>
    <groupId>org.primefaces.extensions</groupId>
    <artifactId>primefaces-extensions</artifactId>
    <version>2.1.0</version>
</dependency>
<dependency>
    <groupId>org.primefaces.themes</groupId>
    <artifactId>all-themes</artifactId>
    <version>1.0.10</version>
</dependency>

My object:

@Entity
public class Privilege implements IEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column()
    private Long id;
    @Column()
    private String name;
    @Column()
    private String description;

    public Privilege(String name) {
        this.name = name;
    }

    public Privilege(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Privilege(Long id, String name, String description) {
        this(id, name);
        this.description = description;
    }

    public Privilege() {

    }

    @Override
    public Long getId() {
        return id;
    }

    @Override
    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(final String description) {
        this.description = description;
    }
}

Also to clarify: the LinkedHashMap contains the id, the name and the description (so it should have everything to build the correct object)

What could be the problem here? Do I need to define the package somehow in faces-config?

Using: Mojarra 2.2.6, primefaces 5.1, primefaces-extensions 2.1.0

1
So it works with an h:dataTable? And where is your bean? For all we know, the sContr.privileges is a list of hashMaps and JSF is right and you are wrong. And PLEASE state explicit version info. See also stackoverflow.com/tags/jsf/info - Kukeltje
private List<Privilege> privileges; and instantiated as an ArrayList. Everything is displayed correctly. The sContr is the ManagedBean annotated as @ManagedBean @SessionScoped and every method there works except for custom objects. I added the maven settings for the version in the question - Thomas Stubbe
and to clarify: everything works except: action="#{sContr.deletePrivilege(privilege)}". Other actions that do not send a object to the sContr like action="#{sContr.createDefaultPrivilege()}" work without problems - Thomas Stubbe
What EL version and implementation are you using? - Kukeltje
And where is the LinkedHashMap used? please... minimal reproducible example (with a minimal entity etc...). Your title and text mention something that is nowhere visible in your code... e.g. why this "Also to clarify: the LinkedHashMap contains the id, the name and the description (so it should have everything to build the correct object)" - Kukeltje

1 Answers

-3
votes

This depends on how you are solving the Privilege so if you are deserializing it some how it may, I had the same issue, I was deserializing Device model from json using jackson

class Device{}
devices = objectMapper.readValue(responseBody, List.class);

and it gave the same error exactly I solve deserializing like

devices = objectMapper.readValue(responseBody, new TypeReference<>() {});

and it worked perfectly.