From: <mol...@us...> - 2007-10-16 11:00:27
|
Revision: 466 http://openutils.svn.sourceforge.net/openutils/?rev=466&view=rev Author: molaschi Date: 2007-10-16 04:00:26 -0700 (Tue, 16 Oct 2007) Log Message: ----------- Adding module for rmi hibernate lazy loading in spring context Modified Paths: -------------- trunk/pom.xml Added Paths: ----------- trunk/openutils-spring-rmibernate/ trunk/openutils-spring-rmibernate/.checkstyle trunk/openutils-spring-rmibernate/.classpath trunk/openutils-spring-rmibernate/.project trunk/openutils-spring-rmibernate/.settings/ trunk/openutils-spring-rmibernate/.settings/org.eclipse.jdt.core.prefs trunk/openutils-spring-rmibernate/.settings/org.eclipse.wst.common.component trunk/openutils-spring-rmibernate/.settings/org.eclipse.wst.common.project.facet.core.xml trunk/openutils-spring-rmibernate/pom.xml trunk/openutils-spring-rmibernate/src/ trunk/openutils-spring-rmibernate/src/main/ trunk/openutils-spring-rmibernate/src/main/java/ trunk/openutils-spring-rmibernate/src/main/java/it/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/HibernateRmiProxyFactoryBean.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/aspects/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/aspects/HibernateLazyLoaderAspect.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/pagination/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/pagination/Paginator.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/HibernateLazyRmiInterceptor.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/LazyReferenceAspect.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/SerializationInterceptor.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/util/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/util/EntitySerializer.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/exporter/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/exporter/HibernateRmiServiceExporter.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/managers/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/managers/HibernateLazyServiceImpl.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/LazyReference.java trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/managers/ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/managers/HibernateLazyService.java trunk/openutils-spring-rmibernate/src/test/ trunk/openutils-spring-rmibernate/src/test/java/ Added: trunk/openutils-spring-rmibernate/.checkstyle =================================================================== --- trunk/openutils-spring-rmibernate/.checkstyle (rev 0) +++ trunk/openutils-spring-rmibernate/.checkstyle 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,6 @@ +<fileset-config file-format-version="1.2.0" simple-config="true"> + <fileset name="all" enabled="true" check-config-name="project" local="false"> + <file-match-pattern match-pattern="." include-pattern="true" /> + </fileset> + <filter name="NonSrcDirs" enabled="true" /> +</fileset-config> \ No newline at end of file Added: trunk/openutils-spring-rmibernate/.classpath =================================================================== --- trunk/openutils-spring-rmibernate/.classpath (rev 0) +++ trunk/openutils-spring-rmibernate/.classpath 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src/main/java"/> + <classpathentry kind="src" output="target/test-classes" path="src/test/java"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="var" path="M2_REPO/dom4j/dom4j/1.6.1/dom4j-1.6.1.jar" sourcepath="M2_REPO/dom4j/dom4j/1.6.1/dom4j-1.6.1-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/asm/asm/2.2.3/asm-2.2.3.jar" sourcepath="M2_REPO/asm/asm/2.2.3/asm-2.2.3-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.13/log4j-1.2.13.jar" sourcepath="M2_REPO/log4j/log4j/1.2.13/log4j-1.2.13-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-beans/2.0.6/spring-beans-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/aopalliance/aopalliance/1.0/aopalliance-1.0.jar" sourcepath="M2_REPO/aopalliance/aopalliance/1.0/aopalliance-1.0-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/commons-collections/commons-collections/3.1/commons-collections-3.1.jar" sourcepath="M2_REPO/commons-collections/commons-collections/3.1/commons-collections-3.1-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-dao/2.0.6/spring-dao-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-aop/2.0.6/spring-aop-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-remoting/2.0.6/spring-remoting-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar" sourcepath="M2_REPO/junit/junit/3.8.1/junit-3.8.1-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-web/2.0.6/spring-web-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.4.1/slf4j-api-1.4.1.jar" sourcepath="M2_REPO/org/slf4j/slf4j-api/1.4.1/slf4j-api-1.4.1-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/antlr/antlr/2.7.6/antlr-2.7.6.jar" sourcepath="M2_REPO/antlr/antlr/2.7.6/antlr-2.7.6-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.jar" sourcepath="M2_REPO/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-hibernate3/2.0.6/spring-hibernate3-2.0.6.jar" sourcepath="/M2_REPO/org/springframework/spring-hibernate3/2.0.1/spring-hibernate3-2.0.1-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/javax/transaction/jta/1.0.1B/jta-1.0.1B.jar" sourcepath="M2_REPO/javax/transaction/jta/1.0.1B/jta-1.0.1B-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/hibernate/hibernate/3.2.4.ga/hibernate-3.2.4.ga.jar" sourcepath="M2_REPO/org/hibernate/hibernate/3.2.4.ga/hibernate-3.2.4.ga-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar" sourcepath="M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-jdbc/2.0.6/spring-jdbc-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/net/sf/ehcache/ehcache/1.2.3/ehcache-1.2.3.jar" sourcepath="M2_REPO/net/sf/ehcache/ehcache/1.2.3/ehcache-1.2.3-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-core/2.0.6/spring-core-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/commons-lang/commons-lang/2.3/commons-lang-2.3.jar" sourcepath="M2_REPO/commons-lang/commons-lang/2.3/commons-lang-2.3-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/slf4j/jcl104-over-slf4j/1.4.1/jcl104-over-slf4j-1.4.1.jar" sourcepath="M2_REPO/org/slf4j/jcl104-over-slf4j/1.4.1/jcl104-over-slf4j-1.4.1-sources.jar"/> + <classpathentry kind="var" path="M2_REPO/org/springframework/spring-context/2.0.6/spring-context-2.0.6.jar"/> + <classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-log4j12/1.4.1/slf4j-log4j12-1.4.1.jar" sourcepath="M2_REPO/org/slf4j/slf4j-log4j12/1.4.1/slf4j-log4j12-1.4.1-sources.jar"/> + <classpathentry kind="output" path="target/classes"/> +</classpath> Added: trunk/openutils-spring-rmibernate/.project =================================================================== --- trunk/openutils-spring-rmibernate/.project (rev 0) +++ trunk/openutils-spring-rmibernate/.project 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,26 @@ +<projectDescription> + <name>openutils-spring-rmibernate</name> + <comment>openutils base Spring-Hibernate RMI remote lazy loading support</comment> + <projects/> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + </buildCommand> + <buildCommand> + <name>org.eclipse.wst.common.project.facet.core.builder</name> + </buildCommand> + <buildCommand> + <name>org.eclipse.wst.validation.validationbuilder</name> + </buildCommand> + <buildCommand> + <name>com.atlassw.tools.eclipse.checkstyle.CheckstyleBuilder</name> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.wst.common.project.facet.core.nature</nature> + <nature>org.eclipse.jdt.core.javanature</nature> + <nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature> + <nature>org.eclipse.jem.workbench.JavaEMFNature</nature> + <nature>com.atlassw.tools.eclipse.checkstyle.CheckstyleNature</nature> + </natures> +</projectDescription> \ No newline at end of file Added: trunk/openutils-spring-rmibernate/.settings/org.eclipse.jdt.core.prefs =================================================================== --- trunk/openutils-spring-rmibernate/.settings/org.eclipse.jdt.core.prefs (rev 0) +++ trunk/openutils-spring-rmibernate/.settings/org.eclipse.jdt.core.prefs 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,5 @@ +#Tue Oct 16 10:42:53 CEST 2007 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 Added: trunk/openutils-spring-rmibernate/.settings/org.eclipse.wst.common.component =================================================================== --- trunk/openutils-spring-rmibernate/.settings/org.eclipse.wst.common.component (rev 0) +++ trunk/openutils-spring-rmibernate/.settings/org.eclipse.wst.common.component 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,5 @@ +<project-modules id="moduleCoreId" project-version="1.5.0"> + <wb-module deploy-name="openutils-spring-rmibernate"> + <wb-resource deploy-path="/" source-path="src/main/java"/> + </wb-module> +</project-modules> \ No newline at end of file Added: trunk/openutils-spring-rmibernate/.settings/org.eclipse.wst.common.project.facet.core.xml =================================================================== --- trunk/openutils-spring-rmibernate/.settings/org.eclipse.wst.common.project.facet.core.xml (rev 0) +++ trunk/openutils-spring-rmibernate/.settings/org.eclipse.wst.common.project.facet.core.xml 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,6 @@ +<faceted-project> + <fixed facet="jst.java"/> + <fixed facet="jst.utility"/> + <installed facet="jst.utility" version="1.0"/> + <installed facet="jst.java" version="5.0"/> +</faceted-project> \ No newline at end of file Added: trunk/openutils-spring-rmibernate/pom.xml =================================================================== --- trunk/openutils-spring-rmibernate/pom.xml (rev 0) +++ trunk/openutils-spring-rmibernate/pom.xml 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,122 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.sourceforge.openutils</groupId> + <artifactId>openutils</artifactId> + <version>3</version> + <relativePath>..</relativePath> + </parent> + <artifactId>openutils-spring-rmibernate</artifactId> + <name>openutils base Spring-Hibernate RMI remote lazy loading support</name> + <version>1.0.0-SNAPSHOT</version> + <description>openutils base Spring-Hibernate RMI remote lazy loading support</description> + <properties> + <spring.version>2.0.6</spring.version> + </properties> + <dependencies> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>1.4.1</version> + </dependency> + <dependency> + <!-- replaces commons-logging --> + <groupId>org.slf4j</groupId> + <artifactId>jcl104-over-slf4j</artifactId> + <version>1.4.1</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-hibernate3</artifactId> + <version>${spring.version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-remoting</artifactId> + <version>${spring.version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + <version>${spring.version}</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate</artifactId> + <version>3.2.4.ga</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + <exclusion> + <groupId>cglib</groupId> + <artifactId>cglib</artifactId> + </exclusion> + <exclusion> + <groupId>asm</groupId> + <artifactId>asm</artifactId> + </exclusion> + <exclusion> + <groupId>asm</groupId> + <artifactId>asm-attrs</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>commons-beanutils</groupId> + <artifactId>commons-beanutils</artifactId> + <version>1.7.0</version> + <exclusions> + <exclusion> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.3</version> + </dependency> + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + <version>3.1</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>3.8.1</version> + <optional>true</optional> + </dependency> + <dependency> + <groupId>cglib</groupId> + <artifactId>cglib-nodep</artifactId> + <version>2.1_3</version> + </dependency> + <dependency> + <groupId>asm</groupId> + <artifactId>asm</artifactId> + <version>2.2.3</version> + </dependency> + </dependencies> +</project> \ No newline at end of file Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/HibernateRmiProxyFactoryBean.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/HibernateRmiProxyFactoryBean.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/HibernateRmiProxyFactoryBean.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,54 @@ +package it.openutils.spring.rmibernate.client; + +import it.openutils.spring.rmibernate.shared.managers.HibernateLazyService; + +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.remoting.rmi.RmiProxyFactoryBean; + + +/** + * ProxyFactoryBean for automatic injection of remote lazy loading proxies + * @author mmolaschi + * @version $Id: $ + */ +public class HibernateRmiProxyFactoryBean extends RmiProxyFactoryBean +{ + + /** + * Store the hibernate lazy service to be used by remote lazy loading + */ + public static ThreadLocal<HibernateLazyService> hibernateLazyServiceTL = new ThreadLocal<HibernateLazyService>(); + + private HibernateLazyService hibernateLazyService; + + /** + * {@inheritDoc} + */ + @Override + public Object invoke(MethodInvocation invocation) throws Throwable + { + // store the lazy service for this thread + if (hibernateLazyService == null) + { + // if hibernateLazyService is null this means that this service IS hibernateLazyService + hibernateLazyServiceTL.set((HibernateLazyService)this.getObject()); + } + else + { + hibernateLazyServiceTL.set(hibernateLazyService); + } + + // proceed with rmi call + return super.invoke(invocation); + } + + /** + * Sets the hibernateLazyService. + * @param hibernateLazyService the hibernateLazyService to set + */ + public void setHibernateLazyService(HibernateLazyService hibernateLazyService) + { + this.hibernateLazyService = hibernateLazyService; + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/aspects/HibernateLazyLoaderAspect.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/aspects/HibernateLazyLoaderAspect.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/aspects/HibernateLazyLoaderAspect.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,75 @@ +package it.openutils.spring.rmibernate.client.aspects; + +import it.openutils.spring.rmibernate.client.HibernateRmiProxyFactoryBean; +import it.openutils.spring.rmibernate.client.pagination.Paginator; +import it.openutils.spring.rmibernate.shared.managers.HibernateLazyService; + +import java.io.Serializable; + +import net.sf.cglib.proxy.LazyLoader; + + +/** + * Aspect that does remote lazy loading on cglib proxy + * @author mmolaschi + * @version $Id: $ + */ +public class HibernateLazyLoaderAspect implements LazyLoader, Serializable +{ + + private static ThreadLocal<Paginator> paginator = new ThreadLocal<Paginator>(); + + private String className; + + private String fieldName; + + private Serializable id; + + /** + * Constructor + * @param className parent class name + * @param fieldName field to be lazy loaded + * @param id id of current entity + */ + public HibernateLazyLoaderAspect(String className, String fieldName, Serializable id) + { + this.className = className; + this.fieldName = fieldName; + this.id = id; + } + + /** + * Set pagination for next calls in current thread + * @param from starting row number + * @param size max number of rows + */ + public static void setPagination(int from, int size) + { + paginator.set(new Paginator(from, size)); + } + + /** + * Disable pagination for next calls in current thread + */ + public static void resetPagination() + { + paginator.set(null); + } + + /** + * {@inheritDoc} + */ + public Object loadObject() throws Exception + { + // Load from remote + HibernateLazyService hls = HibernateRmiProxyFactoryBean.hibernateLazyServiceTL.get(); + + if (paginator.get() != null) + { + return hls.invoke(className, fieldName, id, paginator.get().getFrom(), paginator.get().getSize()); + } + + return hls.invoke(className, fieldName, id); + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/pagination/Paginator.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/pagination/Paginator.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/client/pagination/Paginator.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,68 @@ +package it.openutils.spring.rmibernate.client.pagination; + +/** + * @author mmolaschi + * @version $Id: $ + */ +public class Paginator +{ + + private int from; + + private int size; + + /** + * + */ + public Paginator() + { + + } + + /** + * @param from starting row number + * @param size max rows + */ + public Paginator(int from, int size) + { + this.from = from; + this.size = size; + } + + /** + * Get starting row number + * @return starting row number + */ + public int getFrom() + { + return from; + } + + /** + * Set starting row number + * @param from starting row number + */ + public void setFrom(int from) + { + this.from = from; + } + + /** + * Get max number of rows + * @return max number of rows + */ + public int getSize() + { + return size; + } + + /** + * Set max number of rows + * @param size max number of rows + */ + public void setSize(int size) + { + this.size = size; + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/HibernateLazyRmiInterceptor.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/HibernateLazyRmiInterceptor.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/HibernateLazyRmiInterceptor.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,57 @@ +package it.openutils.spring.rmibernate.server.aspects; + +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; +import org.hibernate.SessionFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Main server interceptor on rmi calls + * @author mmolaschi + * @version $Id: $ + */ +public class HibernateLazyRmiInterceptor implements MethodInterceptor +{ + + /** + * log + */ + protected static final Logger logger = LoggerFactory.getLogger(HibernateLazyRmiInterceptor.class); + + private SessionFactory sessionFactory; + + /** + * Contructor + * @param sessionFactory hibernate session factory + */ + public HibernateLazyRmiInterceptor(SessionFactory sessionFactory) + { + this.sessionFactory = sessionFactory; + } + + /** + * {@inheritDoc} + */ + public Object invoke(MethodInvocation invocation) throws Throwable + { + try + { + Object retVal = invocation.proceed(); + + // Proxy class for serialization work + return SerializationInterceptor.getEnhancedObject(retVal, sessionFactory); + } + catch (Throwable ex) + { + if (logger.isInfoEnabled()) + { + logger.info("Processing of " + " remote call resulted in exception: ", ex); + } + + throw ex; + } + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/LazyReferenceAspect.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/LazyReferenceAspect.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/LazyReferenceAspect.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,41 @@ +package it.openutils.spring.rmibernate.server.aspects; + +import it.openutils.spring.rmibernate.shared.LazyReference; + +import java.lang.reflect.Method; + +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + + +/** + * Aspect on lazy fields to intercept writeReplace + * @author mmolaschi + * @version $Id: $ + */ +public class LazyReferenceAspect implements MethodInterceptor +{ + + private LazyReference lazyReference; + + public LazyReference getLazyReference() + { + return lazyReference; + } + + + public void setLazyReference(LazyReference lazyReference) + { + this.lazyReference = lazyReference; + } + + /** + * {@inheritDoc} + */ + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable + { + // TODO Auto-generated method stub + return lazyReference; + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/SerializationInterceptor.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/SerializationInterceptor.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/SerializationInterceptor.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,292 @@ +package it.openutils.spring.rmibernate.server.aspects; + +import it.openutils.spring.rmibernate.server.aspects.util.EntitySerializer; +import it.openutils.spring.rmibernate.shared.LazyReference; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import net.sf.cglib.proxy.Callback; +import net.sf.cglib.proxy.CallbackFilter; +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; +import net.sf.cglib.proxy.NoOp; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.collections.SetUtils; +import org.apache.commons.collections.Transformer; +import org.hibernate.EntityMode; +import org.hibernate.SessionFactory; +import org.hibernate.collection.PersistentCollection; +import org.hibernate.proxy.HibernateProxy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ReflectionUtils; + + +/** + * Proxy object with {@link EntitySerializer} and Intercept writeReplace calls + * @author mmolaschi + * @version $Id: $ + */ +public class SerializationInterceptor implements MethodInterceptor +{ + + /** + * log + */ + private static Logger log = LoggerFactory.getLogger(SerializationInterceptor.class); + + /** + * non proxied object + */ + private Object original; + + /** + * hibernate sessionfactory + */ + private SessionFactory sessionFactory; + + /** + * Constructor + * @param o object to be proxied + * @param sessionFactory hibernate sessionfactory + */ + private SerializationInterceptor(Object o, SessionFactory sessionFactory) + { + this.original = o; + this.sessionFactory = sessionFactory; + } + + /** + * Get proxy object intercepting writeReplace calls + * @param o object to be proxied + * @param sessionFactory hibernate sessionfactory + * @return proxied object + */ + public static Object getEnhancedObject(Object o, SessionFactory sessionFactory) + { + return getEnhancedObject(o, sessionFactory, null); + } + + /** + * Get proxy object intercepting writeReplace calls + * @param o object to be proxied + * @param sessionFactory hibernate sessionfactory + * @param lazyRef reference to a lazy field + * @return proxied object + */ + public static Object getEnhancedObject(Object o, SessionFactory sessionFactory, LazyReference lazyRef) + { + if (o == null) + { + return null; + } + + // check if there is an empty constructor + try + { + o.getClass().getConstructor(new Class[]{}); + } + catch (NoSuchMethodException ex) + { + return o; + } + + // check if object can be subclassed + if (Modifier.isFinal(o.getClass().getModifiers())) + { + return o; + } + + try + { + // get class + Class clazz = o.getClass(); + + // if it is an hibernateproxy get superclass + if (o instanceof HibernateProxy) + { + clazz = o.getClass().getSuperclass(); + if (clazz == null) + { + clazz = o.getClass().getInterfaces()[0]; + } + } + + Callback callback = null; + + // if this is a lazy field user lazyreferenceaspect + if (lazyRef != null) + { + LazyReferenceAspect lra = new LazyReferenceAspect(); + lra.setLazyReference(lazyRef); + callback = lra; + } + else + { + // user default interceptor + callback = new SerializationInterceptor(o, sessionFactory); + } + + // create proxy to listen on writeReplace method calls + return Enhancer.create(clazz, new Class[]{EntitySerializer.class }, new CallbackFilter() + { + + public int accept(Method method) + { + if (method.getName().equals("writeReplace")) + { + return 0; + } + else + { + return 1; + } + } + + }, new Callback[]{callback, NoOp.INSTANCE }); + } + catch (Throwable t) + { + log.warn(t.getMessage(), t); + return o; + } + } + + /** + * + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable + { + + try + { + if (original == null) + { + return null; + } + else if (original.getClass().isPrimitive()) + { + return original; + } + else if (original.getClass().isArray()) + { + // replace array entries with proxied ones + Object[] array = (Object[]) original; + for (int i = 0; i < array.length; i++) + { + array[i] = SerializationInterceptor.getEnhancedObject(array[i], sessionFactory); + } + return array; + } + else if (original instanceof Collection) + { + // replace collection entries with proxied ones + Collection collection = (Collection) original; + CollectionUtils.transform(collection, transformer(sessionFactory)); + return collection; + } + else if (original instanceof Map) + { + // replace map entries with proxied ones + Map map = (Map) original; + MapUtils.transformedMap(map, transformer(sessionFactory), transformer(sessionFactory)); + return map; + } + else if (original instanceof Set) + { + // replace set entries with proxied ones + Set set = (Set) original; + SetUtils.transformedSet(set, transformer(sessionFactory)); + return set; + } + else + { + // cycle on bean fields + ReflectionUtils.doWithFields(original.getClass(), new ReflectionUtils.FieldCallback() + { + /** + * + * {@inheritDoc} + */ + public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException + { + // set field accessible + field.setAccessible(true); + + // get original value + Object oldValue = field.get(original); + + // get new value + Object newValue = null; + + if ((oldValue instanceof HibernateProxy && ((HibernateProxy) oldValue) + .getHibernateLazyInitializer() + .isUninitialized()) + || oldValue instanceof PersistentCollection) + { + // if this field is a hibernate proxy or a persistent collection store reference + LazyReference lazyRef = new LazyReference(); + lazyRef.setFieldClassName(field.getType().getName()); + lazyRef.setClassName(original.getClass().getName()); + lazyRef.setFieldName(field.getName()); + // load id + lazyRef.setId(sessionFactory.getClassMetadata(original.getClass()).getIdentifier(original, EntityMode.POJO)); + + // get proxy for lazy + newValue = SerializationInterceptor.getEnhancedObject(oldValue, sessionFactory, lazyRef); + } + else + { + // get default proxy + newValue = SerializationInterceptor.getEnhancedObject(oldValue, sessionFactory); + } + + // if there is a variation store it + if (newValue != oldValue) + { + field.set(original, newValue); + } + } + + }); + } + + return original; + + } + catch (Throwable t) + { + log.error(t.getMessage(), t); + return original; + } + } + + /** + * Get transformer for collection, map or set injection of proxied objects + * @param factory hibernate session factory + * @return transformer + */ + private Transformer transformer(SessionFactory factory) + { + return new Transformer() + { + + public Object transform(Object input) + { + return SerializationInterceptor.getEnhancedObject(input, sessionFactory); + } + + }; + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/util/EntitySerializer.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/util/EntitySerializer.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/aspects/util/EntitySerializer.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,19 @@ +package it.openutils.spring.rmibernate.server.aspects.util; + +import java.io.ObjectStreamException; + +/** + * Interface for intercepting writeReplace method calls + * @author mmolaschi + * @version $Id: $ + */ +public interface EntitySerializer +{ + /** + * Write alternative object on serialization + * @return alternative object + * @throws ObjectStreamException error writing + */ + Object writeReplace() throws ObjectStreamException; + +} \ No newline at end of file Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/exporter/HibernateRmiServiceExporter.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/exporter/HibernateRmiServiceExporter.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/exporter/HibernateRmiServiceExporter.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,54 @@ +package it.openutils.spring.rmibernate.server.exporter; + +import it.openutils.spring.rmibernate.server.aspects.HibernateLazyRmiInterceptor; + +import org.hibernate.SessionFactory; +import org.springframework.aop.framework.ProxyFactory; +import org.springframework.remoting.rmi.RmiServiceExporter; +import org.springframework.remoting.support.RemoteInvocationTraceInterceptor; +import org.springframework.util.ClassUtils; + + +/** + * Rmi exporter that checks laziness of bean fields in all object graph + * @author mmolaschi + * @version $Id: $ + */ +public class HibernateRmiServiceExporter extends RmiServiceExporter +{ + + /** + * hibernate sessionfactory + */ + private SessionFactory sessionFactory; + + /** + * {@inheritDoc} + */ + @Override + protected Object getProxyForService() + { + checkService(); + checkServiceInterface(); + ProxyFactory proxyFactory = new ProxyFactory(); + proxyFactory.addInterface(getServiceInterface()); + if (isRegisterTraceInterceptor()) + { + proxyFactory.addAdvice(new RemoteInvocationTraceInterceptor(getExporterName())); + } + // add interceptor for lazy work + proxyFactory.addAdvice(new HibernateLazyRmiInterceptor(sessionFactory)); + proxyFactory.setTarget(getService()); + return proxyFactory.getProxy(ClassUtils.getDefaultClassLoader()); + } + + /** + * Set hibernate session factory + * @param sessionFactory hibernate sessionfactory + */ + public void setSessionFactory(SessionFactory sessionFactory) + { + this.sessionFactory = sessionFactory; + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/managers/HibernateLazyServiceImpl.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/managers/HibernateLazyServiceImpl.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/server/managers/HibernateLazyServiceImpl.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,287 @@ +package it.openutils.spring.rmibernate.server.managers; + +import it.openutils.spring.rmibernate.shared.managers.HibernateLazyService; + +import java.io.Serializable; +import java.rmi.RemoteException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; + +import org.apache.commons.beanutils.PropertyUtils; +import org.apache.commons.lang.StringUtils; +import org.hibernate.Hibernate; +import org.hibernate.HibernateException; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.collection.PersistentCollection; +import org.hibernate.collection.PersistentSortedMap; +import org.hibernate.collection.PersistentSortedSet; +import org.hibernate.proxy.HibernateProxy; +import org.springframework.orm.hibernate3.HibernateCallback; +import org.springframework.orm.hibernate3.HibernateTemplate; + + +/** + * Server side implementation of remote lazy loading calls + * @author mmolaschi + * @version $Id: $ + */ +public class HibernateLazyServiceImpl implements HibernateLazyService +{ + + /** + * hibernate sessionfactory + */ + private SessionFactory sessionFactory; + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Object invoke(final String className, final String methodName, final Serializable id) throws RemoteException + { + try + { + HibernateTemplate ht = new HibernateTemplate(sessionFactory); + return ht.execute(new HibernateCallback() + { + + public Object doInHibernate(Session session) throws HibernateException, SQLException + { + try + { + Object entity = sessionFactory.getCurrentSession().load(Class.forName(className), id); + Object retVal = PropertyUtils.getProperty(entity, methodName); + Hibernate.initialize(retVal); + return retVal; + } + catch (Exception ex) + { + throw new HibernateException(ex); + } + } + + }); + } + catch (HibernateException ex) + { + throw new RemoteException(ex.getMessage(), ex); + } + } + + /** + * {@inheritDoc} + */ + @SuppressWarnings("unchecked") + public Object invoke(final String className, final String propertyName, final Serializable id, final int from, + final int size) throws RemoteException + { + try + { + // get lazy prop + final Object lazy = invoke(className, propertyName, id); + + if (lazy == null) + { + return null; + } + + // get class + Class fClass = lazy.getClass(); + + // if is a single object proxy + if (fClass.isAssignableFrom(HibernateProxy.class)) + { + return lazy; + } + else + { + // it's a list + + // calculate list size + long count = this.count(className, propertyName, id); + + // no row at desired rownum + if (from > count) + { + return null; + } + + // the list is already right and can be processed + if (from <= 0 && size <= count) + { + // could be clean and returned + if (lazy instanceof List) + { + return new ArrayList((List) lazy); + } + if (lazy instanceof SortedSet) + { + PersistentSortedSet pss = (PersistentSortedSet) lazy; + SortedSet ss = new TreeSet(pss.comparator()); + ss.addAll((Collection) lazy); + return ss; + } + if (lazy instanceof Set) + { + return new HashSet((Collection) lazy); + } + if (lazy instanceof SortedMap) + { + PersistentSortedMap psm = (PersistentSortedMap) lazy; + SortedMap sm = new TreeMap(psm.comparator()); + sm.putAll((Map) lazy); + return sm; + } + if (lazy instanceof Map) + { + return new HashMap((Map) lazy); + } + + // it should never reach this line... + return null; + } + } + + // filter collection + HibernateTemplate ht = new HibernateTemplate(sessionFactory); + List list = ht.executeFind(new HibernateCallback() + { + + public Object doInHibernate(Session session) throws HibernateException, SQLException + { + Query q = session.createFilter(lazy, ""); + q.setMaxResults(size); + q.setFirstResult(from); + + return q.list(); + } + + }); + + // process list + if (list == null || list.size() == 0) + { + return null; + } + + if (fClass.isAssignableFrom(PersistentCollection.class)) + { + if (fClass.isAssignableFrom(List.class)) + { + return list; + } + if (fClass.isAssignableFrom(SortedSet.class)) + { + PersistentSortedSet pss = (PersistentSortedSet) invoke(className, propertyName, id); + SortedSet ss = new TreeSet(pss.comparator()); + ss.addAll(list); + return ss; + } + if (fClass.isAssignableFrom(Set.class)) + { + return new HashSet(list); + } + if (fClass.isAssignableFrom(SortedMap.class)) + { + PersistentSortedMap psm = (PersistentSortedMap) invoke(className, propertyName, id); + SortedMap sm = new TreeMap(psm.comparator()); + for (Object o : list) + { + Object[] array = (Object[]) o; + sm.put(array[0], array[1]); + } + return sm; + } + if (fClass.isAssignableFrom(Map.class)) + { + Map m = new HashMap(); + for (Object o : list) + { + Object[] array = (Object[]) o; + m.put(array[0], array[1]); + } + return m; + } + } + + // it should never reach this point ?!?! + return null; + } + catch (Exception ex) + { + throw new RemoteException("Error lazy loading", ex); + } + } + + /** + * {@inheritDoc} + */ + public long count(final String className, final String propertyName, final Serializable id) throws RemoteException + { + HibernateTemplate ht = new HibernateTemplate(sessionFactory); + return ((Number) ht.execute(new HibernateCallback() + { + + public Object doInHibernate(Session session) throws HibernateException, SQLException + { + StringBuilder query = getBaseQuery(className, propertyName, true); + Query q = session.createQuery(query.toString()); + q.setParameter(0, id); + + return q.uniqueResult(); + } + + })).longValue(); + } + + private StringBuilder getBaseQuery(String className, String propertyName, boolean count) + { + String entityName = StringUtils.substringAfterLast(className, "."); + + String propertyId = sessionFactory.getClassMetadata(className).getIdentifierPropertyName(); + + StringBuilder query = new StringBuilder("select "); + if (count) + { + query.append("count("); + } + query.append("el"); + if (count) + { + query.append(")"); + } + query + .append(" from ") + .append(entityName) + .append(" cl inner join cl.") + .append(propertyName) + .append(" el ") + .append(" where cl.") + .append(propertyId) + .append(" = ?"); + + return query; + } + + /** + * Sets the factory. + * @param factory the factory to set + */ + public void setSessionFactory(SessionFactory factory) + { + this.sessionFactory = factory; + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/LazyReference.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/LazyReference.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/LazyReference.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,117 @@ +package it.openutils.spring.rmibernate.shared; + +import it.openutils.spring.rmibernate.client.aspects.HibernateLazyLoaderAspect; + +import java.io.ObjectStreamException; +import java.io.Serializable; + +import net.sf.cglib.proxy.Enhancer; + + +/** + * Store lazy reference + * @author mmolaschi + * @version $Id: $ + */ +public class LazyReference implements Serializable +{ + + private Serializable id; + + private String fieldName; + + private String className; + + private String fieldClassName; + + /** + * default constructor + */ + public LazyReference() + { + + } + + /** + * Constructor + * @param className className + * @param fieldName fieldName + * @param fieldClassName fieldClassName + * @param id id of current entity + */ + public LazyReference(String className, String fieldName, String fieldClassName, Serializable id) + { + this.className = className; + this.fieldName = fieldName; + this.fieldClassName = fieldClassName; + this.id = id; + } + + /** + * Called on deserialization, creates proxy for remote lazy loading + * @return proxy for remote lazy loading + * @throws ObjectStreamException exception reading + * @throws ClassNotFoundException class not found + */ + @SuppressWarnings("unchecked") + Object readResolve() throws ObjectStreamException, ClassNotFoundException + { + // get proxy superclass + Class superclass = Class.forName(fieldClassName); + Class[] interfaces = null; + // if superclass is an interface add it to interfaces + if (superclass.isInterface()) + { + interfaces = new Class[]{superclass}; + } + // return proxy + return Enhancer.create( + superclass, + interfaces, + new HibernateLazyLoaderAspect(className, fieldName, id)); + + } + + public String getClassName() + { + return className; + } + + public void setClassName(String className) + { + this.className = className; + } + + public Serializable getId() + { + return id; + } + + public void setId(Serializable id) + { + this.id = id; + } + + public String getFieldName() + { + return fieldName; + } + + public void setFieldName(String fieldName) + { + this.fieldName = fieldName; + } + + + public String getFieldClassName() + { + return fieldClassName; + } + + + public void setFieldClassName(String fieldClassName) + { + this.fieldClassName = fieldClassName; + } + +} Added: trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/managers/HibernateLazyService.java =================================================================== --- trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/managers/HibernateLazyService.java (rev 0) +++ trunk/openutils-spring-rmibernate/src/main/java/it/openutils/spring/rmibernate/shared/managers/HibernateLazyService.java 2007-10-16 11:00:26 UTC (rev 466) @@ -0,0 +1,45 @@ +package it.openutils.spring.rmibernate.shared.managers; + +import java.io.Serializable; +import java.rmi.RemoteException; + + +/** + * Interface for server-side remote lazy loading calls + * @author mmolaschi + * @version $Id: $ + */ +public interface HibernateLazyService +{ + /** + * Invoke remote lazy loading + * @param className name of parent class + * @param propertyName name of property to load + * @param id current entity id + * @return loaded object / collection + * @throws RemoteException error + */ + Object invoke(String className, String propertyName, Serializable id) throws RemoteException; + + /** + * Invoke remote lazy loading + * @param className name of parent class + * @param propertyName name of property to load + * @param id current entity id + * @param from starting row number + * @param size max rows to return + * @return loaded object / collection + * @throws RemoteException error + */ + Object invoke(String className, String propertyName, Serializable id, int from, int size) throws RemoteException; + + /** + * Get collection size + * @param className name of parent class + * @param propertyName name of property to load + * @param id current entity id + * @return loaded object / collection + * @throws RemoteException error + */ + long count(String className, String propertyName, Serializable id) throws RemoteException; +} Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2007-10-11 22:39:15 UTC (rev 465) +++ trunk/pom.xml 2007-10-16 11:00:26 UTC (rev 466) @@ -214,5 +214,6 @@ <module>openutils-hibernate-security</module> <module>openutils-mgnlspring</module> <module>openutils-mgnlstripes</module> + <module>openutils-spring-rmibernate</module> </modules> </project> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |