2

i have these simple pages:

list.xhtml

<h:form id="form">  
    <h:dataTable value="#{testBean.model}" var="elem">
        <h:column>
            <f:facet name="header">code</f:facet>
            #{elem.code}
        </h:column>
        <h:column>
            <f:facet name="header">description</f:facet>
            #{elem.description}
        </h:column>
        <h:column>
            <f:facet name="header">action</f:facet>
            <h:commandButton action="#{testBean.edit(elem)}" value="edit"/>
        </h:column>
    </h:dataTable>
</h:form>

edit.xhtml

<h:form id="form">
    <h:panelGrid columns="2">
        <h:outputLabel value="code"/>
        <h:inputText value="#{testBean.selection.code}"/>

        <h:outputLabel value="description"/>
        <h:inputText value="#{testBean.selection.description}"/>
    </h:panelGrid>

    <h:commandButton action="#{testBean.update}" value="update"/>
</h:form>

and this bean:

@ManagedBean
public class TestBean implements Serializable
{
    private static final long serialVersionUID = 1L;

    @EJB
    private PersistenceService service;
    private Object selection;
    private List<UnitType> model;

    @PostConstruct
    public void init()
    {
        model = service.findAll(UnitType.class);
    }

    public String edit(Object object)
    {
        System.out.println(Tracer.current(object));
        setSelection(object);
        return "edit";
    }

    public String update()
    {
        System.out.println(Tracer.current(selection));
        return "list";
    }

    // getters and setters
}

so the table is rendered, when i click one of the "edit" buttons it navigates to "edit.jsf" showing filled input, but when i click the "update" buttons it gives me this error:

javax.el.PropertyNotFoundException: /test2/edit.xhtml @27,54 value="#{testBean.selection.code}": Target Unreachable, 'null' returned null

note that i know how to implement a @ViewScoped interface to manage CRUD operations, but this is a simple proof of concept that i need to better understand JSF lifecycle.

so i want "testBean" to be @RequestScoped


UPDATE trying with f:viewParam, still not understanding...

list.xhtml

<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>test list</title>
    </h:head>

    <h:body>
        <h:messages/>

        <h:form id="form">
            <h:dataTable value="#{testBean2.model}" rows="10" var="elem">
                <h:column>
                    <f:facet name="header">converterString</f:facet>
                    #{elem.converterString}
                </h:column>
                <h:column>
                    <f:facet name="header">first name</f:facet>
                    #{elem.firstName}
                </h:column>
                <h:column>
                    <f:facet name="header">last name</f:facet>
                    #{elem.lastName}
                </h:column>
                <h:column>
                    <f:facet name="header">action</f:facet>
                    <h:commandButton action="#{testBean2.edit}" value="edit">
                        <f:param name="entity" value="#{elem.converterString}"/>
                    </h:commandButton>
                    <h:commandButton action="#{testBean2.edit2}" value="edit2">
                        <f:param name="entity" value="#{elem.converterString}"/>
                    </h:commandButton>
                </h:column>
            </h:dataTable>
        </h:form>
    </h:body>
</html>

edit.xhtml

<?xml version="1.0" encoding="ISO-8859-1"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
    <f:metadata>
        <f:viewParam id="entityParam" name="entity" value="#{testBean2.selection}" converter="entityConverter" required="true"/>
    </f:metadata>

    <h:head>
        <title>test edit</title>
    </h:head>

    <h:body>
        <h:messages/>

        <h:form id="form">
            <h:panelGrid columns="2">
                <h:outputLabel value="selection"/>
                <h:outputText value="#{testBean2.selection.converterString}"/>

                <h:outputLabel value="firstName"/>
                <h:inputText value="#{testBean2.selection.firstName}"/>

                <h:outputLabel value="lastName"/>
                <h:inputText value="#{testBean2.selection.lastName}"/>
            </h:panelGrid>

            <h:commandButton action="#{testBean2.update}" value="update" ajax="false">
                <f:param name="entity" value="#{testBean2.selection.converterString}"/>
            </h:commandButton>
        </h:form>
    </h:body>
</html>

testBean2.java

@ManagedBean
public class TestBean2 implements Serializable
{
    private static final long serialVersionUID = 1L;

    @EJB
    private PersistenceService service;

    private Object selection;
    private List<Person> model;

    @PostConstruct
    public void init()
    {
        Tracer.out();
        model = service.queryAll(Person.class);
    }

    public String edit()
    {
        JsfUtils.addSuccessMessage("edited");
        return "edit";
    }

    public String edit2()
    {
        JsfUtils.addSuccessMessage("edited");
        return "edit?faces-redirect=true&amp;includeViewParams=true";
    }

    public void update()
    {
        Tracer.out(selection);
        JsfUtils.addSuccessMessage("updated");
    }

    // getters and setters
}

if i press "edit" button it goes to edit page, but selection is null and no message is showed.

if i press "edit2" button it goes to edit page, but selection is null, showing required message and the url is edit.jsf?entity=

what am i doing wrong?

Michele Mariotti
  • 7,372
  • 5
  • 41
  • 73
  • Read this you will get idea [Difference between View and Request scope in managed beans][1] [1]: http://stackoverflow.com/questions/6025998/difference-between-view-and-request-scope-in-managed-beans – Pradeep Gamage Aug 16 '12 at 11:47
  • i already know the difference. i'm asking something different. please read the question carefully. – Michele Mariotti Aug 16 '12 at 11:53
  • Hi Michele, Have you been able to solve the above issue? I am using the request scope to do CRUD. I am getting the same error as you got. – Unknown Nov 04 '14 at 05:15
  • Hi @Madhava, I posted what I found as an answer. Nevertheless it is simpler to implement CRUD using at least `@ViewScope` beans, but this PoC can be a suggestion for something more advanced. Hope it helps you :) – Michele Mariotti Nov 04 '14 at 09:05
  • Thank you for your comment . I have already implemented using View Scope and it work well too. But I wanted to use @RequestScope and here update and delete does not work for me :( – Unknown Nov 04 '14 at 09:10

3 Answers3

1

As my understand, when your second request come to testBean, selection Object is null. If you run this with session bean you may not get this error.

Pradeep Gamage
  • 585
  • 4
  • 8
  • 21
0

The way I see it, there's no clean way to achieve what you want.

I'll suggest you simply pass around an Id attr between requests as a simple request parameter. So in your post constructor, check if the parameter value is set and based on that, perform a look in your persistence layer.

Alternatively, using the setup you already have, bind the:

<h:inputText value="#{testBean.selection.code}"/>

component to your backing bean and call getValue() on it when necessary. Either way, still untidy.

If you find any other way, please let us know.

Mihai Iorga
  • 39,330
  • 16
  • 106
  • 107
kolossus
  • 20,559
  • 3
  • 52
  • 104
  • you're right, it seems it's impossible to achieve it in a clean way, i tried everything i know. your second solution is something i havn't tried, interesting but still too much industrious. but worth an upvote :) – Michele Mariotti Aug 28 '12 at 08:50
0

Finally I found a way: data will be in a long scope, bean in short.

Note that this is just a proof of concept, not a real use case. And be aware, when dealing with @RequestScope beans, of PrimeFaces lazy DataTable model scope

@ManagedBean
public class TestBean
{
    @EJB
    private PersistenceService service;

    @ManagedProperty("#{viewScope.item}")
    private Item item;

    @ManagedProperty("#{sessionScope.model}")
    private EntityDataModel<Item> model;

    @PostConstruct
    public void init()
    {
        if(model == null)
        {
            model = new EntityDataModel<Item>(Item.class);
            Faces.setSessionAttribute("model", model);
        }
    }

    public String update()
    {
        Faces.getFlash().setKeepMessages(true);

        try
        {
            item = service.update(item);
            Faces.setViewAttribute("item", item);

            JsfUtils.addSuccessMessage("updated");

            return "view?faces-redirect=true&includeViewParams=true";
        }
        catch(Exception e)
        {
            e.printStackTrace();
            JsfUtils.addErrorMessage(e);
        }

        return null;
    }

    // getters and setters, other actions, ...
}

list.xhtml

<p:dataTable value="#{testBean.model}" var="elem" ...>
    ...

    <p:column exportable="false" toggleable="false" headerText="#{bundle.actions}">

        <!-- two techniques available for navigation -->

        <p:button outcome="view?id=#{elem.converterString}" icon="#{icons.view}" />

        <p:commandButton rendered="#{user.isEditAllowed(elem)}"
            action="edit?faces-redirect=true&amp;includeViewParams=true" process="@form"
            icon="#{icons.edit}">
            <f:param name="id" value="#{elem.converterString}" />
        </p:commandButton>
    </p:column>
</p:dataTable>

view.xhtml

<f:metadata>
    <o:viewParam id="itemId" name="id" value="#{viewScope.item}" required="true"
        converter="entityConverter" />
</f:metadata>

<ui:composition template="/WEB-INF/templates/template.xhtml">
    <ui:define name="content">
        <p:panelGrid columns="2">
            <h:outputLabel value="#{bundle.name}" />
            <h:outputText value="#{item.name}" />

            ...
        </p:panelGrid>

        <p:button outcome="list" value="#{bundle.list}" icon="#{icons.list}" />

        <p:button rendered="#{user.isEditAllowed(item)}" 
            outcome="edit?id=#{item.converterString}" value="#{bundle.edit}"
            icon="#{icons.edit}" />
    </ui:define>
</ui:composition>

edit.xhtml

<f:metadata>
    <o:viewParam id="itemId" name="id" value="#{viewScope.item}" required="true"
        converter="entityConverter" />
</f:metadata>

<ui:composition template="/WEB-INF/templates/template.xhtml">
    <ui:define name="content">
        <p:panelGrid columns="2">
            <h:outputLabel value="#{bundle.name}" />
            <h:panelGroup>
                <p:inputText id="name" value="#{item.name}" />
                <p:message for="name" />
            </h:panelGroup>

            ...
        </p:panelGrid>

        <p:commandButton process="@form" update="@form" action="#{testBean.update}" 
            value="#{bundle.update}" icon="#{icons.update}" />

        <p:button outcome="view?id=#{item.converterString}" value="#{bundle.cancel}" 
            icon="#{icons.cancel}" />
    </ui:define>
</ui:composition>
Community
  • 1
  • 1
Michele Mariotti
  • 7,372
  • 5
  • 41
  • 73