Issue with JpaIdentityStore use
shsharma79 Dec 16, 2009 10:27 PMHi, I am a newbie to Seam. I am working on a simple user registration app where I am trying to use JpaIdentityStore for Identity management. I have followed the steps given in the sample seamspace
example. But I am not able to get it working. The main issue is that I have a field userId in my user class which I want to use as the primaryKey for my User table. That is why I have annotated this field with @Id and @GeneratedValue. Now, when I am trying to invoke identityManager.createUser() method, everything goes fine until when IdentityManager invokes HibernateEntityManager to persist the new user. At that point, I am getting an exception that userId field is null. As I have put @GeneratedValue annotation on the field, I am expecting this value to be auto-generated but that's not the case. Any help will be appreciated. Here are the code artifacts:
User.java @Entity @Name("user") @Scope(ScopeType.SESSION) public class User implements Serializable{ private Long userId; private String emailAddress; private String firstName; private String middleInitial; private String lastName; private String password; private int age; private List<Role> roles; public User(Long userId, String emailAddress, String firstName, String mi, String lastName, String password, int age) { this.userId = userId; this.emailAddress = emailAddress; this.firstName = firstName; this.middleInitial = mi; this.lastName = lastName; this.password = password; this.age = age; } public User() {} @Id @GeneratedValue public Long getUserId() { return userId; } public void setUserId(Long userId) { this.userId = userId; } @UserPrincipal @NotNull @Email @Column(unique = true) public String getEmailAddress() { return emailAddress; } public void setEmailAddress(String emailAddress) { this.emailAddress = emailAddress; } @NotNull @Length(min = 1, max = 30) @UserFirstName public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @Length(max = 1) public String getMiddleInitial() { return middleInitial; } public void setMiddleInitial(String middleInitial) { this.middleInitial = middleInitial; } @NotNull @Length(min = 1, max = 30) @UserLastName public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @UserPassword(hash = "md5") @NotNull @Length(min = 6, max = 14) public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @NotNull @Range(min = 18, message = "You must be 18 or older to register.") public int getAge() { return age; } public void setAge(int age) { this.age = age; } @UserRoles @ManyToMany(fetch = FetchType.EAGER) @JoinTable( joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ID")} ) public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; } } RegisterAction.java @Stateful @Name("register") @Scope(ScopeType.EVENT) public class RegisterAction implements Register{ @Logger private Log log; @In private User user; @In private IdentityManager identityManager; @In private StatusMessages statusMessages; @In EntityManager entityManager; private boolean registered; private String verifyPassword; public void register() { if(verifyPassword.equals(user.getPassword())) { // Try to persist the user so that we can get the id generated for it // entityManager.persist(user); try { new RunAsOperation() { public void execute() { identityManager.createUser(user.getEmailAddress(), user.getPassword(), user.getFirstName(), user.getLastName()); } }.addRole("admin").run(); statusMessages.add("User #0 #1 registered successfully.", user.getFirstName(), user.getLastName()); registered = true; } catch (IdentityManagementException e) { statusMessages.add(e.getMessage()); } } else { statusMessages.addToControl("verifyPassword", "Verify Password does not match the Password."); verifyPassword = null; } } @Observer(JpaIdentityStore.EVENT_PRE_PERSIST_USER) public void onPrePersist(User user) { log.info("***** Pre-persist observer called. Setting user properties *****"); user.setMiddleInitial(this.user.getMiddleInitial()); user.setAge(this.user.getAge()); log.info("***** User properties set *****"); } public String getVerifyPassword() { return verifyPassword; } public void setVerifyPassword(String verifyPassword) { this.verifyPassword = verifyPassword; } public boolean isRegistered() { return registered; } public void setRegistered(boolean registered) { this.registered = registered; } public void invalid() { statusMessages.add("Validation failed. Please try again"); } @Remove @Destroy public void destroy() {} } Components.xml .... .... <security:jpa-identity-store entity-manager="#{entityManager}" user-class="com.shal.seam.entity.User" role-class="com.shal.seam.entity.Role"/> .... .... <persistence:managed-persistence-context name="entityManager" auto-create="true" persistence-unit-jndi-name="java:/validationEntityManagerFactory"/> .... .... And here is the exception: .... .... Caused by: javax.persistence.PersistenceException: org.hibernate.AssertionFailure: null id in com.shal.seam.entity.User entry (don't flush the Session after an exception occurs) at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:527) at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:114) at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:247) at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:86) at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:177) at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1389) ... 54 more Caused by: org.hibernate.AssertionFailure: null id in com.shal.seam.entity.User entry (don't flush the Session after an exception occurs) at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:55) at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:164) at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:120) at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:196) at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338) at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:515) ... 59 more