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