JSF + JPA (componente Primefaces Wizard)

Pessoal,

estou treinando/testando o exemplo do componente Wizard do Primefaces (http://www.primefaces.org/showcase/ui/wizard.jsf), incluindo uma funcionalidade extra (gravar em banco).

O problema é que o método save está passando null para gravar no banco e por isso é gerado NullPointerException.

Creio que estou fazendo alguma associação incorretamente.

Alguém pode me ajudar ?

wizard.xhtml:

[...]
<p:commandButton value="Submit" update="growl" actionListener="#{userWizard.save}" />
[...]

Classe UserWizard (vide método save, linha 30):

@ManagedBean(name = "userWizard")
@SessionScoped
public class UserWizard {

	private User user = new User();
	private List<User> users;
	private boolean skip;
	private static final Logger logger = Logger.getLogger(UserWizard.class.getName());

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public boolean isSkip() {
		return skip;
	}

	public void setSkip(boolean skip) {
		this.skip = skip;
	}

	public void setUsers(List<User> users) {
		this.users = users;
	}

	public void save(ActionEvent actionEvent) {
		// Persist user
		EntityManager manager = this.getEntityManager();
		UserRepository repository = new UserRepository(manager);

		repository.adiciona(this.user);
		this.user = new User();
		// this.users = null;

		FacesMessage msg = new FacesMessage("Successful", "Welcome:"
				+ user.getFirstname());
		FacesContext.getCurrentInstance().addMessage(null, msg);
	}

	public List<User> getUsers() {
		if (this.users == null) {
			EntityManager manager = this.getEntityManager();
			UserRepository repository = new UserRepository(manager);
			System.out.println("**** CHAMANDO O REPOSITORIO ****");
			this.users = repository.buscaTodos();
		}
		return this.users;
	}

	public String onFlowProcess(FlowEvent event) {
		logger.log(Level.INFO, "Current wizard step:{0}", event.getOldStep());
		logger.log(Level.INFO, "Next step:{0}", event.getNewStep());

		if (skip) {
			skip = false; // reset in case user goes back
			return "confirm";
		} else {
			return event.getNewStep();
		}
	}

	private EntityManager getEntityManager() {
		FacesContext fc = FacesContext.getCurrentInstance();
		ExternalContext ec = fc.getExternalContext();
		HttpServletRequest request = (HttpServletRequest) ec.getRequest();
		EntityManager manager = (EntityManager) request
				.getAttribute("EntityManager");

		return manager;
	}
}

Exception:

SEVERE: 'java.lang.NullPointerException' recebido ao invocar escuta de ação '#{userWizard.save}' para o componente 'j_idt56'
Mar 11, 2013 4:16:12 PM javax.faces.event.MethodExpressionActionListener processAction
SEVERE: java.lang.NullPointerException
	at org.primefaces.wizard.UserRepository.adiciona(UserRepository.java:16)
	at org.primefaces.wizard.UserWizard.save(UserWizard.java:50)
Mar 11, 2013 4:16:12 PM com.sun.faces.context.AjaxExceptionHandlerImpl log
SEVERE: JSF1073: javax.faces.event.AbortProcessingException obtido durante o processamento de INVOKE_APPLICATION 5: UIComponent-ClientId=j_idt4:j_idt56, Message=/wizard.xhtml @128,44 actionListener="#{userWizard.save}": java.lang.NullPointerException
Mar 11, 2013 4:16:12 PM com.sun.faces.context.AjaxExceptionHandlerImpl log
SEVERE: /wizard.xhtml @128,44 actionListener="#{userWizard.save}": java.lang.NullPointerException
javax.faces.event.AbortProcessingException: /wizard.xhtml @128,44 actionListener="#{userWizard.save}": java.lang.NullPointerException

Porque actionListener? Tente utilizar um action normal e com o <p:commandbutton> ajax = ‘false’

O que é feito aqui: repository.adiciona(this.user); ?

O nullpointer aparentemente acontece nesse metodo adiciona…

Estou me aprofundando em JSF e corrija-me se eu estiver errado:
O atributo actionListener deve ser associado a um método público do tipo void que recebe um ActionEvent como parâmetro.

O atributo action deve ser associado a um método público do tipo void ou String de um managed bean. Se esse método devolver uma String, ela será utilizada para determinar a navegação das páginas.

Além disso, creio que o componente em questão precisa estar envolvido com o Listener para ter a funcionalidade esperada que ele apresenta.

No caso do ajax, acho que não será necessário definir nada, já que não o declarei e não quero atualizar/processar uma parte específica da tela; estou realizando uma ação.

[quote=tarlix]O que é feito aqui: repository.adiciona(this.user); ?

O nullpointer aparentemente acontece nesse metodo adiciona…[/quote]

O adiciona está associado com o método persist da JPA:

package org.primefaces.wizard;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

public class UserRepository {
	private EntityManager manager;

	public UserRepository(EntityManager manager) {
		this.manager = manager;
	}

	public void adiciona(User user) {
		this.manager.persist(user);
	}

	@SuppressWarnings("unchecked")
	public List<User> buscaTodos() {
		Query query = this.manager.createQuery("select x from USUARIO x");
		return query.getResultList();
	}
}

Tenta verificar se esse manager não esta nulo.

Provavelmente esteja vindo nulo aqui:

[code]
private EntityManager getEntityManager() {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
HttpServletRequest request = (HttpServletRequest) ec.getRequest();
EntityManager manager = (EntityManager) request
.getAttribute(“EntityManager”);

    return manager;  
}  [/code]