Здравствуйте! Система построена на основе Jboss Seam версии 2.3.1. В системе используется Java версии 6, а так же Apache Tomcat выступающий в роли сервера. Вместо EJB используются Spring Bean, для того, чтобы запускать приложение в сервлет контейнере (Tomcat) вместо сервера приложения (TomEE, GlassFish, Weblogic) и тд. Зачем это сделано не суть.
Версии используемых компонентов:
Jboss Seam 2.3.1
Spring Web 3.2.2
Spring Bean 3.2.2
Spring Remote
Hibernate 4.1.4
Проблема вот в чем. В метод сохранения сущности (назовем его saveEntity()) приходит persistent объект. Мне необходимо в этом методе, сделать копию этого объекта. У объекта есть потомки, то есть необходимо также сделать deep copy, чтобы все ссылки были сохраненны. Грубо говоря, мне необходимо сохранить такой же объект, но с другим ID. После нескольких дней чтения ответов в гугле, и на StackOverflow в частности, использовал несколько способов.
1) Использовать следующий метод, как советуют
здесь:
public static <T> T clone(Class<T> clazz, T dtls) {
T clonedObject = (T) SerializationHelper.clone((Serializable) dtls);
return clonedObject;
}
2) Использовать самописный метод, суть которого в распроксировании объекта (unproxy) и последующим копированием:
public static <T> T initializeAndUnproxy(T entity) {
if (entity == null) {
return null;
}
try {
Hibernate.initialize(entity);
}
catch (Exception e) {
logger.error("Exception occured:", e);
}
if (entity instanceof HibernateProxy) {
entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer().getImplementation();
}
return entity;
}
public static Object clone(Object obj) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
byte buf[] = baos.toByteArray();
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
ObjectInputStream ois = new ObjectInputStream(bais);
Object newObject = ois.readObject();
ois.close();
return newObject;
}
У объекта entity (который необходимо скопировать), есть поле Author, с типом, который имплементит UserDetails (Spring Security). Поле соответствует пользователю системы, который сохраняет запись. Проблема в следующем, при использовании любого из вышеперечисленных способов, кидается следующий exception:
xxx.yyy.zzz.User cannot be cast to org.jboss.seam.intercept.Proxy
При использовании самописного метода, падает конкретно вот здесь:
ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj); <--- тут валится
Я не эксперт в Spring Security, но подозреваю, что это он не дает мне сделать копию, но не уверен. В документации JBoss, ничего нет по интерфейсу org.jboss.seam.intercept.Proxy. Гугл тоже молчит по этому поводу. Тип сущности имплеменитит Serializable. Заранее спасибо за любую помощь.
P.S С помощью грязного хака удается сохранить сущность под другим id, но это попродило другие проблемы, поэтому временно от него отказался
this.getSessionFactory().getCurrentSession().evict(entity);
((AEntity) entity).setEntryKey(null);
this.getSessionFactory().getCurrentSession().merge(entity);