Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > GWT+Hibernate проблема с сериализацией


Автор: _sten_ 29.5.2008, 17:04
 Есть клиент организован на GWT. Делаю так: по запросу клиента выгружаю с базы сущность, и асинхронно передаю клиенту:
Код

 public class UserServiceImpl extends RemoteServiceServlet implements UserService {
    public User getUser() {
        User user = ServiceLocator.getEntityService().loadUser(2l);  //грузим сущность из БД с помощью хибернета
        System.out.println(user.getLogin());
        User us = new User();
        us.setName(user.getName());
        us.setLogin(user.getLogin());
        return user; 
    }

}
 

вобщем в таком виде не работаєт, никакого эксепшина не выдает, просто не выполняется асинхронный метод на клиенте. Проблема скорей всего в сериализации потому, что если вернуть не user а us (как в даном примере) то все ок. Получается что надо клонировать сущности выгруженые хибернетом и только тогда сериализировать...
Как быть? 

Автор: Yauhen 31.7.2008, 13:26
Если ты делал маппинг при помощи аннотейшнс или использовал в бинах generics, то бины конечно сериализовываться не будут. Тогда тебе их придется продублировать для клиентской стороны (без аннотейшнов и дженериков). 

пример можно посмотреть здесь http://www.rbgrn.net/blog/2007/11/using-hibernate-with-google-web-toolkit-gwt.html. 

но в этом примере плохо реализована конвертация серверных бинов в клиенсткие. 
Здесь 
http://gwt-spring-hibernate-reference.googlecode.com/svn/trunk/GWT_Spring_Hibernate_Sample/server_src/org/gwtspringhibernate/reference/rlogman/server/GeneralHelper.java 
можно взять нормальный универсальный код для конвертации, который использует рефлексию.

Если ты в бинах не использовал ни аннотейшнов  ни дженериков. то бины, в которых есть Set-ы для организации связей, тоже сериализовываться не будут, т.к. без использования дженериков Hibernate возвращает не просто Set-ы, а org.hibernate.collection.PersistentSet, которые GWT сериализовывать не хочет.

Для решения этой проблемы нужно org.hibernate.collection.PersistentSet конвертить в HashSet-ы. Для этого йа написал такой код:

Код

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SetConverter {

    public static void convert(Object source){
        Class sourceClass = source.getClass();
        Method [] sourceMethods = sourceClass.getMethods();
        String methodName="";
        
        try{
            
            for (int i = 0; i < sourceMethods.length; i++) {
                methodName = sourceMethods[i].getName();
                
                if((methodName.length() > 3)
                        && (sourceMethods[i].getParameterTypes().length == 0)
                        && methodName.startsWith("get")
                        && Character.isUpperCase(methodName.charAt(3))){
                    
                    Object o = sourceMethods[i].invoke(source, (Object []) null);
                    if (o instanceof Set){
                        HashSet newSet = new HashSet((Set)o);
                        Iterator iterator = newSet.iterator();
                        while(iterator.hasNext()){
                            convert(iterator.next());
                        }
                        try{
                        Method set = sourceClass.getMethod("set"+getMethodPostfix(methodName), new Class[]{Set.class});
                        
                        set.invoke(source, new Object[]{newSet});
                        
                        }catch(NoSuchMethodException e){
                            System.out.println("can not find method set"+getMethodPostfix(methodName)+"in the class"+sourceClass.getName());
                            e.printStackTrace();
                        }
                    }
                }//if method is getter
            
            }//iterates through all methods of the source object
        
        }catch(IllegalAccessException e){
            System.out.println("Illegal access to method"+methodName+"of the class"+sourceClass.getName());
            e.printStackTrace();
        }
        catch(IllegalArgumentException e){
            System.out.println("Illegal arguments was passed to the method"+methodName+"of the class"+sourceClass.getName());
            e.printStackTrace();
        }
        catch(InvocationTargetException e){
            e.printStackTrace();
        }
    
    
    }//convert method

        
    private static String getMethodPostfix(String methodName) {
        return (methodName.substring(3));
    }

}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)