Hi,
I'm integrating a spring-flex app with Hibernate.
I've followed the tutorial in
http://static.springsource.org/sprin...e-introduction
to prevent the n+1 select on entities sets from happening.
The docs state that the HibernateProxyConverter should be automatically registered but, just in case, I manually registered it to be able to debug the calls.
Here's the problem:
The converter's getConvertibleTypes method is called at startup, proofing that the converter is been registered, but the convert method for HibernateProxy is never called, resulting in the "no session or session was closed" exception for lazy collections.
I tried registering my own converter for PersistentBag/PersistentSet and, for eager collections, the convert method is called (no much use, is it?). Still, for lazy collections, the convert method is never invoked.
From my understanding, HibernateProxy should automatically wrap persistent collections and the converter should catch the getter's invokation during serialisation and return the appropriate value depending on whether the proxy is initialised or not.
That is not happening.
Here's my entity (the getRoles() getter is the one showing the problem here)
here's my flex config snippetCode:package it.aekidna.wottudu.model.vo; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; import javax.persistence.Transient; import org.springframework.flex.core.io.AmfIgnore; @Entity @Table(name="`PERSON`") public class UserEntity { private String firstName; private Integer id; private String lastName; private String password; private Set<SecurityRoleEntity> roles; private String username; /** * @return the firstName */ public String getFirstName() { return firstName; } @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name="id") public Integer getId() { // TODO Auto-generated method stub return Integer.valueOf(0); } /** * @return the lastName */ public String getLastName() { return lastName; } @AmfIgnore public String getPassword() { // TODO Auto-generated method stub return password; } @ManyToMany(cascade = CascadeType.ALL, fetch=FetchType.LAZY ) @JoinTable( name = "`PERSON_PERSONROLE_MTM`", joinColumns = { @JoinColumn(name = "personid") }, inverseJoinColumns = { @JoinColumn(name = "personroleid") }) public Set<SecurityRoleEntity> getRoles() { return roles; } /** * @return the username */ public String getUsername() { return username; } @Transient public boolean isActive() { // TODO Auto-generated method stub return true; } /** * @param firstName the firstName to set */ public void setFirstName(String firstName) { this.firstName = firstName; } /** * @param id the id to set */ public void setId(Integer id) { this.id = id; } /** * @param lastName the lastName to set */ public void setLastName(String lastName) { this.lastName = lastName; } /** * @param password the password to set */ public void setPassword(String password) { this.password = password; } /** * @param roles the roles to set */ public void setRoles(Set<SecurityRoleEntity> roles) { this.roles = roles; } /** * @param username the username to set */ public void setUsername(String username) { this.username = username; } }
Here's the CustomProcessor:Code:<bean id="amfConfigProcessor" class="it.aekidna.wottudu.spring.CustomProcessor"> <constructor-arg><value>it.aekidna.wottudu.model.vo</value></constructor-arg> <property name="useDirectFieldAccess" value="false" /> </bean> <flex:message-broker > <flex:config-processor ref="amfConfigProcessor" /> <flex:message-service default-channels="my-streaming-amf,my-longpolling-amf,my-polling-amf" /> <flex:secured per-client-authentication="true" /> </flex:message-broker>
and here's the converterCode:package it.aekidna.wottudu.spring; import org.springframework.core.convert.converter.ConverterRegistry; import org.springframework.flex.core.io.ClassPathScanningAmfConversionServiceConfigProcessor; import org.springframework.flex.core.io.PersistentCollectionConverterFactory; public class CustomProcessor extends ClassPathScanningAmfConversionServiceConfigProcessor { public CustomProcessor(String basePackage) { super(basePackage); } @Override protected void configureConverters(ConverterRegistry registry) { registry.addConverter(new CustomConverter()); registry.addConverterFactory(new PersistentCollectionConverterFactory()); } }
Any clue?Code:package it.aekidna.wottudu.spring; import java.util.Collections; import java.util.Set; import org.hibernate.Hibernate; import org.hibernate.proxy.HibernateProxy; import org.springframework.core.convert.TypeDescriptor; import org.springframework.flex.core.io.HibernateProxyConverter; public class CustomConverter extends HibernateProxyConverter { //THIS IS NEVER CALLED @Override public Object convert(Object inSource, TypeDescriptor inSourceType, TypeDescriptor inTargetType) { if( inSource != null) { if( inSource instanceof HibernateProxy ) { if( Hibernate.isInitialized( inSource ) ) { return inSource; } else { return null; } } } return inSource; } @Override public Set<ConvertiblePair> getConvertibleTypes() { // TODO Auto-generated method stub return Collections.singleton(new ConvertiblePair(HibernateProxy.class, Object.class)); } }
Thanks!
Using
Spring-flex 1.5.2
Hibernate 3.6.10
Spring 3.0.0
BlazeDS 4.0.0
Tomcat 7


Reply With Quote
