Announcement Announcement Module
No announcement yet.
ACLS ... and Hibernate Page Title Module
Move Remove Collapse
This topic is closed
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • ACLS ... and Hibernate

    I spent a couple of days wrestling an issue so I thought I'd post the solution.

    I'm using the new acls on hibernate persisted objects. I am using a lot of code from the Contacts example including the JdbcMutableAclService.

    My app was able to create new ACL's for my hibernate persisted objects, but I was not able to retrieve the ACL for an object after I retrieved it from my hibernate DAO.

    The problem is Hibernate proxies the objects so a call to <object>.getClass() returns the CGLib proxied object... which means .getClass().getName() returns a string that is <className>$$$EnhancerByCGILIB$$$etc.etc

    Hibernate provides a static method that knows how to turn a proxied object into a real object... so, Hibernate.getClass(proxiedObject).getName() will return the correct class name.

    To fix this I had to create a new ObjectIdentityImpl mine is called HibernateObjectIdentityImpl

    public class HibernateObjectIdentityImpl extends ObjectIdentityImpl{
        private Class javaType;
        public HibernateObjectIdentityImpl(String javaType, Serializable identifier) {
        	super(javaType, identifier);
        public HibernateObjectIdentityImpl(Class javaType, Serializable identifier) {
        public HibernateObjectIdentityImpl(Object object) throws IdentityUnavailableException {
        	this.javaType = Hibernate.getClass(object);
        public Class getJavaType() {
            return javaType;
         * Important so caching operates properly.
         * @return the hash
        public int hashCode() {
            int code = 31;
            code ^= this.javaType.hashCode();
            code ^= super.getIdentifier().hashCode();
            return code;
        public String toString() {
            StringBuffer sb = new StringBuffer();
            sb.append("Java Type: ").append(this.javaType);
            sb.append("; Identifier: ").append(super.getIdentifier()).append("]");
            return sb.toString();
    I hacked up jdbcMutableAclService by replacing every occurrence of ObjectIdentityImpl with HibernateObjectIdentityImpl.

    Now you also have to tell your Voters and your afterInvocationProviders to use the HibernateObjectIdentityImpl... to do this you have to hack together an ObjectIdentityRetrievalStrategy:

    public class HibernateObjectIdentityRetrievalStrategy extends ObjectIdentityRetrievalStrategyImpl{
    	public HibernateObjectIdentityRetrievalStrategy() {
    		// TODO Auto-generated constructor stub
    	public ObjectIdentity getObjectIdentity(Object domainObject) {
            return new HibernateObjectIdentityImpl(domainObject);
    put this in your app context:
    <bean id="hibernateObjectIdentityRetrievalStrategy" class="net.fiftytwo.HibernateObjectIdentityRetrievalStrategy"/>
    and then add the following property to every one of your voters and your after invocation providers:

    <property name="objectIdentityRetrievalStrategy">
    		   <ref local="hibernateObjectIdentityRetrievalStrategy"/>
    That did it for me...

  • #2
    I ran into the same.

    You might be able to get around it without hacking Acegi. For example by using session.get() instead of session.load() - the latter returns a proxy while the former returns the real object. Not a perfect solution obviously since once must be aware of this detail and work around it but it works.

    It would be nice if Acegi provided a mechanism to plug in a custom mechanism for deciding on an object's type dealing specifically with this case. Retrieving Hiberante objects and domain object security go hand in hand.