Thursday, March 13, 2014

Grails: Getting the Vaadin plugin to run. "Can not process requests before init() has been called"

I had the problem after I installed the grails-vaadin plugin when starting my application I would get the following error

There is a bug in the GrailsVaadinServlet where you have to add the service.init() call.


 
Fortunately when you install the plugin you edit the source code as it is downloaded to your grails project. Mine was found here:


Generate a Mailto Link in Java with to, bcc, cc, subject and body

This is very simply explained here:

http://java.dzone.com/articles/simple-way-sending-emails-java


Wednesday, March 5, 2014

How to finally solve the Hibernate Lazy Load problem: Make the Collection reconnectable


The problem

After years and years working with hibernate there are a few things I hate about it.

The logging and the error messages are not clear and sometimes misleading (I will not expound now) and then the most common problem of all, the lazy load exception.

There are solutions like SessionInView pattern etc, but I and thousands of others wonder why it is so complicated or bad to make the Collection reconnect itself when needed.

I mean eclipse link does it also with a readonly connection.

The solution

So here is my solution and it finally seems to work. I actually implemented Collection class that does the reconnecting for me.

For this to work i have to do several steps

In the hibernate mapping define field access.


You can do this with annotations or if there is hibernate mapping file it looks like this.

At the top do:
    <hibernate-mapping default-access="field">
..



In the entity in the getter of a relationship I return a wrapper class


public class MyEntity{
 //..
 Collection customers = new HashSet();
 
public Collection getCustomers() {
        return new LazyCollectionWithReconnect

(customers, this, new MyProjectRelationshipInitializer());

    }



The implementation of the wrapper class is in the end of this post

The RelationShipInitializer

The interesting stuff is in MyProjectRelationshipInitializer
We have a generic interface:

public interface RelationshipInitializer {
    void initializeRelationship(Object entity, Object propertyValue);
}

That must be implemented by the project
Here I lookup a Stateless sessionbean that has access to the PersistenceContext and does the loading of the relationship

public class MyProjectRelationshipInitializer implements RelationshipInitializer{
    @Override
    public void initializeRelationship(Object entity, Object propertyValue) {
        MyGenericServiceLocator.inst().getGenericPersistenceService()
        .initializeRelationship(entity, propertyValue);
    }

}

The GenericPersistenceServiceBean that actually initializes the hibernate proxy

looks like this:

@Stateless
@Local(GenericPersistenceService.class)
public class GenericPersistenceServiceBean implements GenericPersistenceService
{

   @PersistenceContext
    protected EntityManager em;
 


@Override
    public void initializeRelationship(Object entity, Object relationShipObject) {
        org.hibernate.Session session = getHibernateSession();
        // the lock method adds the entity back into the Entitymanager makes it  

        //managed.
        try {
            session.lock(entity, LockMode.NONE);

            if(!Hibernate.isInitialized(relationShipObject))
            {
                Hibernate.initialize(relationShipObject);
            }

        } catch (TransientObjectException e) {
            //ignore object that are not saved yet
        }
    }


private Session getHibernateSession() {
        //on web as
        if (em.getDelegate() instanceof Session){
            return (Session) em.getDelegate();
        }
        //in openejb
        if (em.getDelegate() instanceof HibernateEntityManager){
            HibernateEntityManager e = (HibernateEntityManager) em.getDelegate();
            return (Session) e.getDelegate();
        }
        throw new IllegalStateException(String.format("Invalid type of entity manager %s (%s). Expected it to be org.hibernate.Session or org.hibernate.ejb.HibernateEntityManager", em, em.getClass()));
    }


}

Note that the getHibernateSession() is a little bit J2EE Server dependent and might be different for your vendor.

The LazyColletionWithReconnect implementation

 is rather boring:

public class LazyCollectionWithReconnect implements Collection {
   
    private Collection srcCollection;
    private Object surroundingEntity;
    private RelationShipInitializer relationShipInitializer;
   

    public LazyCollectionWithReconnect(Collection srcCollection, Object surroundingEntity, RelationShipInitializer relationShipInitializer) {
        super();
        this.srcCollection = srcCollection;
        this.surroundingEntity = surroundingEntity;
        this.relationShipInitializer = relationShipInitializer;
    }


  

     protected void reconnectIfNecessary() {
        ensureRelationIsLoaded(

           this.surroundingEntity, 
           this.srcCollection, 
           this.relationShipInitializer
        );
    }


          public static boolean ensureRelationIsLoaded(
       Object entity, 
       Object propertyValue, 
       RelationShipInitializer initializer) {
        boolean wasLoaded = false;
        //    first check
        if(!Hibernate.isInitialized(propertyValue)){
            initializer

            .initializeRelationship(entity, propertyValue);
            wasLoaded = true;
        }
        return wasLoaded;
    } 

    public boolean add(E e) {
        reconnectIfNecessary();
        return srcCollection.add(e);
    }
   public boolean addAll(Collection c) {
        reconnectIfNecessary();
        return srcCollection.addAll(c);
    }
    public void clear() {
        reconnectIfNecessary();
        srcCollection.clear();
    }
    public boolean contains(Object o) {
        reconnectIfNecessary();
        return srcCollection.contains(o);
    }
    public boolean containsAll(Collection c) {
        reconnectIfNecessary();
        return srcCollection.containsAll(c);
    }
    public boolean equals(Object o) {
        return srcCollection.equals(o);
    }
    public int hashCode() {
        return srcCollection.hashCode();
    }
    public boolean isEmpty() {
        reconnectIfNecessary();
        return srcCollection.isEmpty();
    }

    public Iterator iterator() {
        reconnectIfNecessary();
        return srcCollection.iterator();
    }
    public boolean remove(Object o) {
        reconnectIfNecessary();
        return srcCollection.remove(o);
    }

    public boolean removeAll(Collection c) {
        reconnectIfNecessary();
        return srcCollection.removeAll(c);
    }

    public boolean retainAll(Collection c) {
        reconnectIfNecessary();
        return srcCollection.retainAll(c);
    }

    public int size() {
        reconnectIfNecessary();
        return srcCollection.size();
    }


    public Object[] toArray() {
        reconnectIfNecessary();
        return srcCollection.toArray();
    }
    public
T[] toArray(T[] a) {
        reconnectIfNecessary();
        return srcCollection.toArray(a);
    }

}



Some common problems

HibernateException "reassociated object has dirty collection reference" 

This error message actually can be misleading. In my case it stemmed from that the entity with the collection did not have equals and hashCode overriden
 











deep cloning

Here is a small utility to really clone an object by writing it first to outputstream and back.

    public static Object deepClone(Object src) throws IOException,ClassNotFoundException{
            ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(src);
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ClassLoaderObjectInputStream ois = new  ClassLoaderObjectInputStream(src.getClass().getClassLoader(),bais);
            Object deepCopy = ois.readObject();
            return  deepCopy;
    }

The class ClassLoaderObjectInputInputStream is needed to resolve the class if it is not in the same jar as the utility method deepClone

import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectStreamClass;
import java.io.StreamCorruptedException;

/**
 * A special ObjectInputStream that loads a class based on a specified
 * ClassLoader rather than the system default.
 *
 * This is useful in dynamic container environments.
 *
 * @author Paul Hammant
 * @version $Id: ClassLoaderObjectInputStream.java 437567 2006-08-28 06:39:07Z bayard $
 * @since Commons IO 1.1
 */
public class ClassLoaderObjectInputStream extends ObjectInputStream {
    /** The class loader to use. */
    private ClassLoader classLoader;

    /**
     * Constructs a new ClassLoaderObjectInputStream.
     *
     * @param classLoader  the ClassLoader from which classes should be loaded
     * @param inputStream  the InputStream to work on
     * @throws IOException in case of an I/O error
     * @throws StreamCorruptedException if the stream is corrupted
     */
    public ClassLoaderObjectInputStream(
            ClassLoader classLoader, InputStream inputStream)
            throws IOException, StreamCorruptedException {
        super(inputStream);
        this.classLoader = classLoader;
    }

    /**
     * Resolve a class specified by the descriptor using the
     * specified ClassLoader or the super ClassLoader.
     *
     * @param objectStreamClass  descriptor of the class
     * @return the Class object described by the ObjectStreamClass
     * @throws IOException in case of an I/O error
     * @throws ClassNotFoundException if the Class cannot be found
     */
    protected Class resolveClass(ObjectStreamClass objectStreamClass)
            throws IOException, ClassNotFoundException {
       
        Class clazz = Class.forName(objectStreamClass.getName(), false, classLoader);

        if (clazz != null) {
            // the classloader knows of the class
            return clazz;
        } else {
            // classloader knows not of class, let the super classloader do it
            return super.resolveClass(objectStreamClass);
        }
    }
}



Tuesday, March 4, 2014

Hibernate Lazy Load exception and how to load an relationship



Hibernate and lazy loading sucks. Especially in Web Dynpro where we cannot use the Session in View pattern. Therefore there is handy method can load a collection to make sure that a collection is loaded and load it on demand from the service layer

public abstract class GenericDaoBean implements GenericDao

// ....

public void initializeRelationship(T entity, String property) {
        org.hibernate.Session session = getHibernateSession();
        // the lock method adds the entity back into the Entitymanager makes it managed.
        try {
            session.lock(entity, LockMode.NONE);
            Object collectionProxy = getAttributeValue(entity, property);

            if(!Hibernate.isInitialized(collectionProxy))
            {
                Hibernate.initialize(collectionProxy);
            }
        } catch (TransientObjectException e) {
            //ignore object that are not saved yet
        }
    }

    public org.hibernate.Session getHibernateSession() {
        Object delegate = getEntityManager().getDelegate();
        org.hibernate.Session session = null;
        //This is in SAP J2EE
        if(delegate instanceof org.hibernate.Session){
            session = (org.hibernate.Session) delegate;
        }
        // this is in OpenEJB container
        else if(delegate instanceof HibernateEntityManager){
            HibernateEntityManager hbEm = (HibernateEntityManager) delegate;
            session = hbEm.getSession();
        }
        return session;
    }
}

public static Object getAttributeValue(Object bean, String attributeName){
        Map props = getPropertyDescriptors(bean.getClass(), new String[]{"class"});
        PropertyDescriptor desc = props.get(attributeName);
        if(desc == null) throw new IllegalArgumentException("attribute:" +attributeName + " does not exist in bean "+ bean);
       
        try {
            Object result = desc.getReadMethod().invoke(bean, null);
            return result;
        } catch (IllegalArgumentException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }