I've got a pretty typical CRUD situation that I'm struggling with so I assume I must be misunderstanding something. I've put together a little demo app to better explain my problem. The two files of interest are shown below:
PersonView - CDI Managed Bean backing the JSF page
package example
import java.io.Serializable;
import java.util.List;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;
@ConversationScoped @Named
public class PersonView implements Serializable {
private Person selectedPerson;
@Inject private PersonService personService;
@Inject private Conversation conversation;
public PersonView() {}
public List<Person> getPeople() { return personService.findAll(); }
public void beginConversation() { if( conversation.isTransient() ) {conversation.begin();} }
public void endConversation() { if( !conversation.isTransient() ) { conversation.end();} }
public void createPerson() {
beginConversation();
setSelectedPerson( new Person() );
}
public void addPerson() {
personService.addPerson( getSelectedPerson() );
endConversation();
}
public void updatePerson() { personService.updatePerson( getSelectedPerson() ); }
public Person getSelectedPerson() { return selectedPerson; }
public void setSelectedPerson(Person selectedPerson) { this.selectedPerson = selectedPerson; }
}
index.xhtml - JSF page for manipulating people
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>CRUD Example</title>
</h:head>
<h:body>
<h:form prependId="false">
<p:dataTable var="p" value="#{personView.people}" id="person_table" rowKey="#{p.id}" selection="#{personView.selectedPerson}">
<p:column selectionMode="single"/>
<p:column><f:facet name="header">ID</f:facet>#{p.id}<p:column>
<p:column><f:facet name="header">Name</f:facet>#{p.name}</p:column>
<f:facet name="footer">
<p:commandButton value="Create Person" onclick="create_dialog.show();" actionListener="#{personView.createPerson}"/>
<p:commandButton value="Edit Person" onclick="edit_dialog.show();" update="edit_panel"/>
</f:facet>
</p:dataTable>
</h:form>
<p:dialog header="Create Person" id="create_dialog" widgetVar="create_dialog" modal="true" width="750" height="300">
<h:form prependId="false">
<p:panel id="create_panel">
<p>Name: <p:inputText value="#{personView.selectedPerson.name}" required="true"/></p>
<p><p:commandButton value="Add" actionListener="#{personView.addPerson}" oncomplete="create_dialog.hide();" update="person_table" /></p>
</p:panel>
</h:form>
</p:dialog>
</h:body>
On the index page the user is shown a data table containing all the people the system knows about. They then press the Create Person button at the bottom of the table. I have checked that this correctly calls the createPerson method and the conversation apparently starts. The create_dialog is then displayed where the user can enter a name. The problem comes when the user clicks the Add button. JSF attempts to store the persons name but the selectedPerson variable is now null so it fails with a NullPointerException.
I realize this isn't a common way of creating objects but in my current application is makes sense as I can guess some of the values of a new Person. It also fits quite well with how I'd like to do editing.
So my question(s): why doesn't the conversation propagate? The PersonView bean appears to be in request scope all the time. I've read about @ViewScoped in JSF2 but I'd rather stick with CDI if possible. From what I've read I think the problem is a failure to pass the CID name with the request but I'm at a loss to see how I could do that with AJAX.
The only solution that I've come up with is to move PersonView into the session but that feels like a huge kludge. e