-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Problem: Collection properties modification in Interceptor.
PostPosted: Tue Mar 06, 2007 12:55 pm 
Newbie

Joined: Tue Mar 06, 2007 10:38 am
Posts: 1
I want to give certain permission for the logged user on some entities on their creation.

I am trying to use an Interceptor to add Permission object for the current user on creation of AuthorizedAccessEntity.


Now I tried implementing the interceptor using http://www.hibernate.org/318.html as a model but i ran into some trouble.

Here is the mapping for the collection which holds the permissions for each user in AuthorizedAccessEntity.

Code:
@OneToMany(
        targetEntity=PermissionResource.class,
        fetch=FetchType.LAZY,
        cascade={CascadeType.ALL}
    )
    @JoinColumn(name="RESOURCE_SUBJECT_ID")
    @MapKey(name="user")
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    public Map<User, IdentityPermission<Resource>> getAuthorizedUsers() {
        return authorizedUsers;
    }
   
    public void setAuthorizedUsers(Map<User, IdentityPermission<Resource>> authorizedUsers) {
        this.authorizedUsers = authorizedUsers;
    }




Here is the interceptor.

Code:
class RPXInterceptor extends EmptyInterceptor {
   
    /* This set holds the newly created AuthorizedAccessEntity objects (except User) we have to add user rights to.
     * We fill it in onSave and actually add the logged user rights in postFlush.
     */
    private Set inserts = new HashSet();
    private Session session = null;
       
   
    /**
     * If the object which is going to be saved is an AuthorizedAccessEntity we add it to
     * our set so we can set the control rights for the current user in postFlush.
     * This method is called only when new object is created.
     */
    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {       
        if ((entity instanceof AuthorizedAccessEntity) && !(entity instanceof User)) {
                                   
            Set<AuthorizedAccessEntity> sInserts = Collections.synchronizedSet(inserts);
            synchronized (sInserts) {
                sInserts.add((AuthorizedAccessEntity) entity);
            }
           
        }       
        return false;
    }
   
    /**
     * Iterate over the collection of freshly saved AuthorizedAccessEntity objects and add CONTROL rights for the current user.
     */
    public void postFlush(Iterator entities) {               
        for (Iterator iter = inserts.iterator(); iter.hasNext(); ) {
           
            Session tempSession = HibernateUtil.createSession(session.connection());
           
            AuthorizedAccessEntity subject = (AuthorizedAccessEntity) iter.next();
            User user = UserService.getLoggedUser();
           
            if (!subject.getAuthorizedUsers().containsKey(user)) {
                try {                   
                    subject.getAuthorizedUsers().put(user, SecurityService.createPermission(user, subject, PermissionType.CONTROL));
                   
                    tempSession.save(subject);                   
                    tempSession.flush();   
                } catch (Exception ex) {
                    throw new CallbackException(ex);
                } finally {
                    try {                       
                        tempSession.close();
                    } catch (HibernateException ex) {
                        throw new CallbackException(ex);
                    }
                }
            }
        }               
        inserts.clear();       
    }
   
    public void setSession(Session session) {
        this.session = session;
    }

    public void afterTransactionCompletion(Transaction tx) {
        //in case we had a rollback.
        inserts.clear();
    }
}


Note: SecurityService.createPermission(user, subject, PermissionType.CONTROL) creates a Permission object (let's say ResourcePersmission) like the one below:

Code:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name="T_PERMISSION")
@DiscriminatorColumn(
    name = "DATA_TYPE",
    discriminatorType = DiscriminatorType.STRING
)
@ForceDiscriminator
public class Permission extends Identity {
    private PermissionType permissionType;
    private User user;
   
    /**
     * Creates a new instance of Permission
     */
    public Permission() {
    }

    public PermissionType getPermissionType() {
        return permissionType;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "USER_ID")
    public User getUser() {
        return user;
    }

    public void setPermissionType(PermissionType permissionType) {
        this.permissionType = permissionType;
    }

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

@MappedSuperclass
public class IdentityPermission<E extends Identity> extends Permission {
   
    protected E subject;

    public IdentityPermission() {
        setName("");
    }
   
    public IdentityPermission(User user, PermissionType permissionType, E subject) {
        setUser(user);
        setPermissionType(permissionType);
        setSubject(subject);
        setName("");
    }

    public IdentityPermission(User user, PermissionType permissionType) {
        this(user, permissionType, null);
        setName("");
    }

    @ManyToOne(fetch=FetchType.LAZY)
    public E getSubject() {
        return subject;
    }

    public void setSubject(E subject) {
        this.subject = subject;
    }
   
}

@Entity
@DiscriminatorValue("RESOURCE")
@AttributeOverride(name="subject", column=@Column(name="RESOURCE_SUBJECT_ID"))
@AssociationOverride(name="subject", joinColumns=@JoinColumn(name="RESOURCE_SUBJECT_ID"))
public class PermissionResource extends IdentityPermission<Resource> {
   
    public PermissionResource() {
    }
   
    public PermissionResource(User user, PermissionType permissionType, Resource subject) {
        super(user, permissionType, subject);
    }

    public PermissionResource(User user, PermissionType permissionType) {
        super(user, permissionType);
    }
}



I get the following exception:

Code:
Caused by: org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
        at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
        at org.hibernate.event.def.WrapVisitor.processCollection(WrapVisitor.java:44)
        at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
        at org.hibernate.event.def.WrapVisitor.processValue(WrapVisitor.java:98)
        at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
        at org.hibernate.event.def.AbstractSaveEventListener.visitCollectionsBeforeSave(AbstractSaveEventListener.java:371)
        at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:273)
        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.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
        at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
        at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
        at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:535)
        at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
        at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
        at com.recoveryplanner.entity.util.RPXInterceptor.postFlush(RPXInterceptor.java:137)


So I guess I can't modify some collection property of the entity and save again in postFlush. Any other ideas how to implement this?

I tried saving only Permission object however no association between the AuthorizedAccessEntity and the row in t_permission table is made. (null in the field in t_permission where the entity's id should be.) so it's like no subject is set.

Any ideas?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.