Session value transient when injected into EntityHome class
domagals.jame Oct 3, 2009 12:07 AMHello all,
I have a persistence issue that has been bugging me, if i could get some ideas on it, I would very much appreciat it.
I currently have the authenticator out-ject to the session the user who logged in, the variable labeled currentUser. I would like to use currentUser in other classes where the User needs to be saved as an owner of an object. An example of this is the Category class. Below are the Authenticator.java, Category.java, and CategoryHome.java
Authenticator.java
@Name("authenticator") public class Authenticator { @Logger private Log log; @In private Identity identity; @In private Credentials credentials; @In private EntityManager entityManager; @Out(scope = ScopeType.SESSION, required=false) private User currentUser; public boolean authenticate() { log.info("authenticating {0}", credentials.getUsername()); try { currentUser = (User) entityManager .createQuery( "select user from User user where user.username = #{credentials.username} and user.password = #{credentials.password}") .getSingleResult(); } catch (NoResultException e) { } boolean authenticated = (currentUser != null); if (authenticated) { log.info("Authenticated #{credentials.username}"); identity.addRole(currentUser.getAccountType().name()); return true; } else { return false; } } }
CategoryHome.java
@Name("categoryHome") @Restrict("#{identity.loggedIn}") public class CategoryHome extends EntityHome<Category> { @In(required = false, scope = ScopeType.SESSION) private User currentUser; public void setCategoryId(Long id) { setId(id); } public Long getCategoryId() { return (Long) getId(); } @Override protected Category createInstance() { Category category = super.createInstance(); category.setOwner(currentUser); return category; } public void load() { if (isIdDefined()) { wire(); } } public void wire() { getInstance(); } public boolean isWired() { return true; } public Category getDefinedInstance() { return isIdDefined() ? getInstance() : null; } }
Category.java
@Entity public class Category { private Long id; private User owner; private String name; @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(nullable = false) public User getOwner() { return owner; } public void setOwner(User owner) { this.owner = owner; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String toString(){ return name; } }
The issue I am having is when I call persist in the CategoryHome.java I always seem to get the error :
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: org.domain.examgenerator.entity.Category.owner at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72) at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290) at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107) at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:212) ... 87 more
I know that the currentUser being injected into CategoryHome is not null. ( I have used the debugger to confirm this to be true).
This leaves me to the conclusion that currentUser is transient. My question is how do I resolve it so that the currentUser value found in the session stays persistent?
I have tried merging the currentUser using entityManager within the CategoryHome class, which is shown below
@Override protected Category createInstance() { Category category = super.createInstance(); currentUser = this.getEntityManager().merge(currentUser); category.setOwner(currentUser); return category; }
but I get the following error.
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'student' for key 'username' at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at com.mysql.jdbc.Util.handleNewInstance(Util.java:406) at com.mysql.jdbc.Util.getInstance(Util.java:381) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3558) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3490) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2109) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2648) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2077) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2362) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2280) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2265) at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:365) at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:73) at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:33) ... 104 more
I am pretty new to seam so any help would be very much appreciated.
Thank you for you time.