package org.springframework.flex.hibernate4;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.LazyInitializationException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.flex.core.io.SpringPropertyProxy;
import org.springframework.flex.hibernate4.domain.AddressNP;
import org.springframework.flex.hibernate4.domain.Company;
import org.springframework.flex.hibernate4.domain.CompanyNP;
import org.springframework.flex.hibernate4.domain.ContactInfo;
import org.springframework.flex.hibernate4.domain.ContactInfoNP;
import org.springframework.flex.hibernate4.domain.PersonNP;
import org.springframework.flex.hibernate4.domain.PrimitiveCompany;
import org.springframework.flex.hibernate4.domain.PrimitiveCompanyNP;
import org.springframework.flex.hibernate4.config.HibernateConfigProcessor;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import flex.messaging.io.PropertyProxyRegistry;
import flex.messaging.io.SerializationContext;
import flex.messaging.io.amf.AmfMessageDeserializer;
import flex.messaging.io.amf.AmfMessageSerializer;
import flex.messaging.io.amf.AmfTrace;
import flex.messaging.io.amf.MessageBody;
import flex.messaging.util.ToStringPrettyPrinter;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "hibernate-np-context.xml")
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class,
SpringPropertyProxyHibernateNativeFieldAccessTests.InternalDbTestExecutionListener.class})
public class SpringPropertyProxyHibernateNativeFieldAccessTests {
private static final Log log = LogFactory.getLog(SpringPropertyProxyHibernateNativeFieldAccessTests.class);
@Autowired
SessionFactory sessionFactory;
AmfMessageSerializer serializer;
AmfMessageDeserializer deserializer;
AmfTrace serializerTrace;
AmfTrace deserializerTrace;
MockHttpServletResponse response;
MockHttpServletRequest request;
@Before
public void init() throws Exception {
HibernateConfigProcessor processor = new HibernateConfigProcessor();
processor.setSessionFactory(this.sessionFactory);
processor.setUseDirectFieldAccess(true);
processor.afterPropertiesSet();
processor.processAfterStartup(null);
this.serializer = new AmfMessageSerializer();
this.serializerTrace = new AmfTrace();
this.response = new MockHttpServletResponse();
this.serializer.initialize(new SerializationContext(), response.getOutputStream(), serializerTrace);
this.deserializer = new AmfMessageDeserializer();
this.deserializerTrace = new AmfTrace();
this.request = new MockHttpServletRequest();
}
@After
public void trace() throws UnsupportedEncodingException {
log.info("Serializer Trace:\n" + serializerTrace);
log.info("Deserializer Trace:\n" + deserializerTrace);
}
@Test
public void serializationOutsideTransactionAfterHibernateGet() throws IOException, ClassNotFoundException {
Session session = this.sessionFactory.openSession();
PersonNP person = (PersonNP) session.get(PersonNP.class, 1);
session.close();
serialize(person);
PersonNP result = (PersonNP) deserialize();
assertNotSame(person, result);
assertEquals(new Integer(1), result.id);
assertEquals("Dad", result.name);
assertNotNull(result.address);
assertNull(result.spouse);
assertNull(result.children);
}
@Test
public void debugLoggingOutsideTransactionAfterHibernateGet() throws IOException, ClassNotFoundException {
Session session = this.sessionFactory.openSession();
PersonNP person = (PersonNP) session.get(PersonNP.class, 1);
session.close();
String result = log(person);
log.info("Result from Logger:\n" + result);
}
@Test
@Transactional
public void serializationInsideTransactionAfterHibernateGet() throws IOException, ClassNotFoundException {
Session session = this.sessionFactory.getCurrentSession();
PersonNP person = (PersonNP) session.get(PersonNP.class, 1);
serialize(person);
PersonNP result = (PersonNP) deserialize();
assertNotSame(person, result);
assertEquals(new Integer(1), result.id);
assertEquals("Dad", result.name);
assertNotNull(result.address);
assertNull(result.spouse);
assertNull(result.children);
}
@Test
public void serializationOutsideTransactionAfterHibernateGetAndInitializedCollection() throws IOException, ClassNotFoundException {
Session session = this.sessionFactory.openSession();
PersonNP person = (PersonNP) session.get(PersonNP.class, 1);
person.children.iterator();
session.close();
serialize(person);
PersonNP result = (PersonNP) deserialize();
assertNotSame(person, result);
assertEquals(new Integer(1), result.id);
assertEquals("Dad", result.name);
assertNotNull(result.address);
assertNull(result.spouse);
assertNotNull(result.children);
assertEquals(2, result.children.size());
for (PersonNP childResult : result.children) {
assertNotNull(childResult.id);
assertTrue(StringUtils.hasText(childResult.name));
assertNull(childResult.spouse);
assertNull(childResult.children);
}
}
@Test
@Transactional
public void serializationInsideTransactionAfterHibernateGetAndInitializedCollection() throws IOException, ClassNotFoundException {
Session session = this.sessionFactory.getCurrentSession();
PersonNP person = (PersonNP) session.get(PersonNP.class, 1);
person.children.iterator();
serialize(person);
PersonNP result = (PersonNP) deserialize();
assertNotSame(person, result);
assertEquals(new Integer(1), result.id);
assertEquals("Dad", result.name);
assertNotNull(result.address);
assertNull(result.spouse);
assertNotNull(result.children);
assertEquals(2, result.children.size());
for (PersonNP childResult : result.children) {
assertNotNull(childResult.id);
assertTrue(StringUtils.hasText(childResult.name));
assertNull(childResult.spouse);
assertNull(childResult.children);
}
}
@Test
public void serializationOutsideTransactionAfterHibernateLoad() throws IOException {
Session session = this.sessionFactory.openSession();
PersonNP person = (PersonNP) session.load(PersonNP.class, 1);
session.close();
try {
serialize(person);
fail("Expected a LazyInitializationException");
} catch (LazyInitializationException ex) {
// expected
}
}
@Test
@Transactional
public void serializationInsideTransactionAfterHibernateLoad() throws IOException, ClassNotFoundException {
Session session = this.sessionFactory.getCurrentSession();
PersonNP person = (PersonNP) session.load(PersonNP.class, 1);
serialize(person);
PersonNP result = (PersonNP) deserialize();
assertNotSame(person, result);
assertEquals(new Integer(1), result.id);
assertEquals("Dad", result.name);
assertNotNull(result.address);
assertNull(result.spouse);
assertNull(result.children);
}
@SuppressWarnings("unchecked")
@Test
public void serializationOutsideTransactionAfterHibernateQuery() throws IOException, ClassNotFoundException {
Session session = this.sessionFactory.openSession();
List<PersonNP> people = session.createQuery("from PersonNP").list();
session.close();
serialize(people);
List<PersonNP> results = (List<PersonNP>) deserialize();
for (PersonNP result : results) {
assertNotNull(result.id);
assertTrue(StringUtils.hasText(result.name));
if (result.spouse != null) {
assertTrue(results.contains(result.spouse));
}
assertNull(result.children);
}
}
@SuppressWarnings("unchecked")
@Test
@Transactional
public void serializationInsideTransactionAfterHibernateQuery() throws IOException, ClassNotFoundException {
Session session = this.sessionFactory.getCurrentSession();
List<PersonNP> people = session.createQuery("from PersonNP").list();
serialize(people);
List<PersonNP> results = (List<PersonNP>) deserialize();
for (PersonNP result : results) {
assertNotNull(result.id);
assertTrue(StringUtils.hasText(result.name));
if (result.spouse != null) {
assertTrue(results.contains(result.spouse));
}
assertNull(result.children);
}
}
@Test
@Transactional
public void deserializeAndPersistNewEntityWithNumericAutogeneratedId() throws IOException, ClassNotFoundException {
SpringPropertyProxy proxy = (SpringPropertyProxy) PropertyProxyRegistry.getRegistry().getProxy(PersonNP.class);
PersonNP person = new PersonNP();
proxy.setValue(person, "id", Double.NaN);
proxy.setValue(person, "name", "Bob");
assertEquals(null, person.id);
Session session = this.sessionFactory.getCurrentSession();
session.save(person);
assertNotNull(person.id);
assertTrue(person.id > 0);
}
@Test
@Transactional
public void deserializeAndPersistNewEntityWithPrimitiveNumericAutogeneratedId() throws IOException, ClassNotFoundException {
SpringPropertyProxy proxy = (SpringPropertyProxy) PropertyProxyRegistry.getRegistry().getProxy(ContactInfo.class);
ContactInfoNP contactInfo = new ContactInfoNP();
proxy.setValue(contactInfo, "id", 0);
proxy.setValue(contactInfo, "email", "bob@foo.com");
proxy.setValue(contactInfo, "phone", "5555551234");
assertEquals(0, contactInfo.id);
Session session = this.sessionFactory.getCurrentSession();
session.save(contactInfo);
assertNotNull(contactInfo.id);
assertTrue(contactInfo.id > 0);
}
@Test
@Transactional
public void deserializeAndPersistNewEntityWithVersion() throws IOException, ClassNotFoundException {
SpringPropertyProxy proxy = (SpringPropertyProxy) PropertyProxyRegistry.getRegistry().getProxy(PersonNP.class);
PersonNP person = new PersonNP();
proxy.setValue(person, "id", Double.NaN);
proxy.setValue(person, "version", Double.NaN);
proxy.setValue(person, "name", "Bob");
assertNull(person.version);
Session session = this.sessionFactory.getCurrentSession();
session.save(person);
assertNotNull(person.id);
assertTrue(person.id > 0);
assertNotNull(person.version);
assertTrue(person.version == 0);
person.name = "Robert";
session.flush();
assertTrue(person.version > 0);
}
@Test
@Transactional
public void deserializeAndPersistNewEntityWithPrimitiveVersion() throws IOException, ClassNotFoundException {
SpringPropertyProxy proxy = (SpringPropertyProxy) PropertyProxyRegistry.getRegistry().getProxy(ContactInfo.class);
ContactInfoNP contactInfo = new ContactInfoNP();
proxy.setValue(contactInfo, "id", 0);
proxy.setValue(contactInfo, "version", 0);
proxy.setValue(contactInfo, "email", "bob@foo.com");
proxy.setValue(contactInfo, "phone", "5555551234");
assertEquals(0, contactInfo.id);
Session session = this.sessionFactory.getCurrentSession();
session.save(contactInfo);
assertNotNull(contactInfo.id);
assertTrue(contactInfo.id > 0);
assertTrue(contactInfo.version == 0);
contactInfo.email = "bob@foobar.com";
session.flush();
assertTrue(contactInfo.version > 0);
}
@Test
@Transactional
public void deserializeAndPersistNewXMLMappedEntityWithVersion() throws IOException, ClassNotFoundException {
SpringPropertyProxy proxy = (SpringPropertyProxy) PropertyProxyRegistry.getRegistry().getProxy(Company.class);
CompanyNP company = new CompanyNP();
proxy.setValue(company, "id", Double.NaN);
proxy.setValue(company, "version", Double.NaN);
proxy.setValue(company, "name", "SpringSource");
assertNull(company.version);
Session session = this.sessionFactory.getCurrentSession();
session.save(company);
assertNotNull(company.id);
assertTrue(company.id > 0);
assertNotNull(company.version);
assertTrue(company.version == 0);
company.name = "VMware";
session.flush();
assertTrue(company.version > 0);
}
@Test
@Transactional
public void deserializeAndPersistNewXMLMappedEntityWithPrimitiveVersion() throws IOException, ClassNotFoundException {
SpringPropertyProxy proxy = (SpringPropertyProxy) PropertyProxyRegistry.getRegistry().getProxy(PrimitiveCompany.class);
PrimitiveCompanyNP company = new PrimitiveCompanyNP();
proxy.setValue(company, "id", 0);
proxy.setValue(company, "version", 0);
proxy.setValue(company, "name", "SpringSource");
assertEquals(0, company.id);
Session session = this.sessionFactory.getCurrentSession();
session.save(company);
assertNotNull(company.id);
assertTrue(company.id > 0);
assertTrue(company.version == 0);
company.name = "VMware";
session.flush();
assertTrue(company.version > 0);
}
private void serialize(Object data) throws IOException {
MessageBody body = new MessageBody();
body.setData(data);
serializer.writeBody(body);
}
private String log(Object data) {
MessageBody body = new MessageBody();
body.setData(data);
ToStringPrettyPrinter printer = new ToStringPrettyPrinter();
return printer.prettify(body);
}
private Object deserialize() throws ClassNotFoundException, IOException {
this.request.setContent(this.response.getContentAsByteArray());
this.deserializer.initialize(new SerializationContext(), this.request.getInputStream(), deserializerTrace);
MessageBody body = new MessageBody();
this.deserializer.readBody(body, 0);
return body.getData();
}
public static class InternalDbTestExecutionListener extends AbstractTestExecutionListener {
public void beforeTestClass(TestContext testContext) throws Exception {
SessionFactory sessionFactory = testContext.getApplicationContext().getBean(SessionFactory.class);
Session session = sessionFactory.openSession();
PersonNP father = new PersonNP();
father.name = "Dad";
session.save(father);
AddressNP address = new AddressNP();
address.street = "777 Techwood Drive";
address.city = "Atlanta";
address.state = "GA";
address.zipcode = "30022";
address.rooms = 5;
address.moveInDate = new Date();
session.save(address);
father.address = address;
session.update(father);
PersonNP mother = new PersonNP();
mother.name = "Mom";
mother.spouse = father;
session.save(mother);
father.spouse = mother;
session.update(father);
PersonNP child1 = new PersonNP();
child1.name = "Jack";
session.save(child1);
PersonNP daughterInLaw = new PersonNP();
daughterInLaw.name = "Lisa";
daughterInLaw.spouse = child1;
session.save(daughterInLaw);
child1.spouse = daughterInLaw;
session.update(child1);
PersonNP child2 = new PersonNP();
child2.name = "Jill";
session.save(child2);
Set<PersonNP> children = new HashSet<PersonNP>();
children.add(child1);
children.add(child2);
father.children = children;
mother.children = children;
session.update(father);
session.update(mother);
session.flush();
session.close();
}
}
}