You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by st...@apache.org on 2013/01/20 23:54:03 UTC
svn commit: r1435993 - in /openwebbeans/trunk/webbeans-impl/src:
main/java/org/apache/webbeans/component/
main/java/org/apache/webbeans/intercept/ main/java/org/apache/webbeans/proxy/
test/java/org/apache/webbeans/newtests/contexts/
Author: struberg
Date: Sun Jan 20 22:54:02 2013
New Revision: 1435993
URL: http://svn.apache.org/viewvc?rev=1435993&view=rev
Log:
OWB-344 add serialisation support for NormalScoped bean proxies
Modified:
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractProducerBean.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ManagedBean.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/NormalScopedBeanInterceptorHandler.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java
openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/contexts/SerializationTest.java
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractProducerBean.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractProducerBean.java?rev=1435993&r1=1435992&r2=1435993&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractProducerBean.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/AbstractProducerBean.java Sun Jan 20 22:54:02 2013
@@ -26,6 +26,7 @@ import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.PassivationCapable;
/**
@@ -34,7 +35,7 @@ import javax.enterprise.inject.spi.Bean;
* @version $Rev$ $Date$
* @param <T> bean type info
*/
-public abstract class AbstractProducerBean<T> extends AbstractOwbBean<T> implements IBeanHasParent<T>
+public abstract class AbstractProducerBean<T> extends AbstractOwbBean<T> implements IBeanHasParent<T>, PassivationCapable
{
/** Owner of the producer field component */
protected InjectionTargetBean<?> ownerComponent;
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ManagedBean.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ManagedBean.java?rev=1435993&r1=1435992&r2=1435993&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ManagedBean.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/ManagedBean.java Sun Jan 20 22:54:02 2013
@@ -25,6 +25,7 @@ import java.lang.reflect.Type;
import java.util.Set;
import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.PassivationCapable;
import org.apache.webbeans.config.WebBeansContext;
@@ -33,7 +34,7 @@ import org.apache.webbeans.config.WebBea
*
* @version $Rev$Â $Date$
*/
-public class ManagedBean<T> extends InjectionTargetBean<T> implements InterceptedMarker
+public class ManagedBean<T> extends InjectionTargetBean<T> implements InterceptedMarker, PassivationCapable
{
/** Constructor of the web bean component */
private Constructor<T> constructor;
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/NormalScopedBeanInterceptorHandler.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/NormalScopedBeanInterceptorHandler.java?rev=1435993&r1=1435992&r2=1435993&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/NormalScopedBeanInterceptorHandler.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/intercept/NormalScopedBeanInterceptorHandler.java Sun Jan 20 22:54:02 2013
@@ -23,20 +23,42 @@ import javax.enterprise.context.spi.Crea
import javax.enterprise.inject.UnproxyableResolutionException;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.PassivationCapable;
import javax.inject.Provider;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+
+import org.apache.webbeans.config.WebBeansContext;
/**
- * TODO add serialisation
+ * <p>A Provider which handles all NormalScoped proxying.
+ * It's two main responsibilities are to provide the one active
+ * Contextual Instance, the second is to provide serialisation.</p>
+ *
+ * <p>The generated proxy will writeReplace() with this class and any
+ * NormalScopedBean provider must readResolve() and regenerate the
+ * proxy class from the {@link org.apache.webbeans.proxy.NormalScopeProxyFactory}
+ * again.
+ * </p>
+ * <p>Any subclass should either declare all their fields <code>transient</code>
+ * or handle the serialisation properly!</p>
*/
-public class NormalScopedBeanInterceptorHandler implements Provider
+public class NormalScopedBeanInterceptorHandler implements Provider, Serializable
{
private transient BeanManager beanManager;
protected transient Bean<?> bean;
+ // we just keep this field for serializing it away
+ private String beanPassivationId;
+
public NormalScopedBeanInterceptorHandler(BeanManager beanManager, Bean<?> bean)
{
this.beanManager = beanManager;
this.bean = bean;
+ if (bean instanceof PassivationCapable)
+ {
+ beanPassivationId = ((PassivationCapable) bean).getId();
+ }
}
@Override
@@ -76,4 +98,22 @@ public class NormalScopedBeanInterceptor
return webbeansInstance;
}
+ /**
+ * The following code gets generated into the proxy:
+ *
+ * <pre>
+ * Object writeReplace() throws ObjectStreamException
+ * {
+ * return provider;
+ * }
+ * </pre>
+ */
+ Object readResolve() throws ObjectStreamException
+ {
+ WebBeansContext webBeansContext = WebBeansContext.getInstance();
+ this.beanManager = webBeansContext.getBeanManagerImpl();
+ this.bean = beanManager.getPassivationCapableBean(beanPassivationId);
+
+ return webBeansContext.getNormalScopeProxyFactory().createNormalScopeProxy(bean);
+ }
}
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java?rev=1435993&r1=1435992&r2=1435993&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/AbstractProxyFactory.java Sun Jan 20 22:54:02 2013
@@ -62,6 +62,11 @@ public abstract class AbstractProxyFacto
protected abstract void createInstanceVariables(ClassWriter cw, Class<?> classToProxy, String classFileName);
/**
+ * generate the bytecode for serialization.
+ */
+ protected abstract void createSerialisation(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName);
+
+ /**
* Each of our interceptor/decorator proxies has exactly 1 constructor
* which invokes the super ct + sets the delegation field.
*
@@ -182,6 +187,8 @@ public abstract class AbstractProxyFacto
cw.visitSource(classFileName + ".java", null);
createInstanceVariables(cw, classToProxy, classFileName);
+ createSerialisation(cw, proxyClassFileName, classToProxy, classFileName);
+
// create a static String Field which contains the passivationId of the Bean or null if not PassivationCapable
@@ -205,8 +212,6 @@ public abstract class AbstractProxyFacto
}
-
-
/**
* The 'defineClass' method on the ClassLoader is protected, thus we need to invoke it via reflection.
* @return the Class which got loaded in the classloader
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java?rev=1435993&r1=1435992&r2=1435993&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/InterceptorDecoratorProxyFactory.java Sun Jan 20 22:54:02 2013
@@ -44,7 +44,6 @@ import org.objectweb.asm.Type;
* This factory will create and cache the proxy classes for a given type.
*
*/
-//X TODO: clarify how serialisation works! The proxy classes might need to get created on deserialisation!
public class InterceptorDecoratorProxyFactory extends AbstractProxyFactory
{
@@ -133,6 +132,11 @@ public class InterceptorDecoratorProxyFa
return null;
}
+ @Override
+ protected void createSerialisation(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName)
+ {
+ // nothing to do ;)
+ }
/**
* <p>Create a decorator and interceptor proxy for the given type. A single instance
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java?rev=1435993&r1=1435992&r2=1435993&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/NormalScopeProxyFactory.java Sun Jan 20 22:54:02 2013
@@ -21,12 +21,14 @@ package org.apache.webbeans.proxy;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Provider;
+import java.io.ObjectStreamException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
import org.apache.webbeans.component.OwbBean;
import org.apache.webbeans.config.OpenWebBeansConfiguration;
@@ -50,6 +52,8 @@ public class NormalScopeProxyFactory ext
/** the name of the field which stores the {@link Provider} for the Contextual Instance */
public static final String FIELD_INSTANCE_PROVIDER = "owbContextualInstanceProvider";
+ private ConcurrentHashMap<Bean<?>, Class<?>> cachedProxyClasses = new ConcurrentHashMap<Bean<?>, Class<?>>();
+
public NormalScopeProxyFactory(WebBeansContext webBeansContext)
{
@@ -95,7 +99,14 @@ public class NormalScopeProxyFactory ext
classToProxy = (Class<T>) bean.getBeanClass();
}
- Class<? extends T> proxyClass = createProxyClass(classLoader, classToProxy);
+
+
+ Class<? extends T> proxyClass = (Class<? extends T>) cachedProxyClasses.get(bean);
+
+ if (proxyClass == null)
+ {
+ proxyClass = createProxyClass(bean, classLoader, classToProxy);
+ }
return createProxyInstance(proxyClass, getInstanceProvider(classLoader, bean));
}
@@ -141,15 +152,45 @@ public class NormalScopeProxyFactory ext
return null;
}
+ public synchronized <T> Class<T> createProxyClass(Bean<T> bean, ClassLoader classLoader, Class<T> classToProxy)
+ {
+ Class<T> proxyClass = (Class<T>) cachedProxyClasses.get(bean);
+
+ if (proxyClass == null)
+ {
+ proxyClass = createProxyClass(classLoader, classToProxy);
+ cachedProxyClasses.putIfAbsent(bean, proxyClass);
+ }
+
+ return proxyClass;
+ }
+
+ @Override
+ protected void createSerialisation(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName)
+ {
+ String[] exceptionTypeNames = {Type.getType(ObjectStreamException.class).getInternalName()};
+ MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "writeReplace", "()Ljava/lang/Object;", null, exceptionTypeNames);
+
+ // fill method body
+ mv.visitCode();
+
+ // load the contextual instance Provider
+ mv.visitVarInsn(Opcodes.ALOAD, 0);
+ mv.visitFieldInsn(Opcodes.GETFIELD, proxyClassFileName, FIELD_INSTANCE_PROVIDER, Type.getDescriptor(Provider.class));
+
+ mv.visitInsn(Opcodes.ARETURN);
+
+ mv.visitMaxs(-1, -1);
+ mv.visitEnd();
+ }
/**
* @param classLoader to use for creating the class in
* @param classToProxy the class for which a subclass will get generated
* @param <T>
* @return the proxy class
- * //X TODO for serialisation reasons this probably needs the Bean it serves.
*/
- public synchronized <T> Class<T> createProxyClass(ClassLoader classLoader, Class<T> classToProxy)
+ public <T> Class<T> createProxyClass(ClassLoader classLoader, Class<T> classToProxy)
throws ProxyGenerationException
{
String proxyClassName = getUnusedProxyClassName(classLoader, classToProxy.getName() + "$OwbNormalScopeProxy");
Modified: openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java?rev=1435993&r1=1435992&r2=1435993&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/proxy/SubclassProxyFactory.java Sun Jan 20 22:54:02 2013
@@ -158,6 +158,11 @@ public class SubclassProxyFactory extend
@Override
protected void delegateInterceptedMethods(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, Method[] interceptedMethods) throws ProxyGenerationException
{
+ }
+
+ @Override
+ protected void createSerialisation(ClassWriter cw, String proxyClassFileName, Class<?> classToProxy, String classFileName)
+ {
// nothing to do ;)
}
Modified: openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/contexts/SerializationTest.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/contexts/SerializationTest.java?rev=1435993&r1=1435992&r2=1435993&view=diff
==============================================================================
--- openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/contexts/SerializationTest.java (original)
+++ openwebbeans/trunk/webbeans-impl/src/test/java/org/apache/webbeans/newtests/contexts/SerializationTest.java Sun Jan 20 22:54:02 2013
@@ -32,6 +32,7 @@ import org.apache.webbeans.newtests.inje
import org.apache.webbeans.newtests.injection.circular.beans.CircularConstructorOrProducerMethodParameterBean;
import org.apache.webbeans.newtests.injection.circular.beans.CircularDependentScopedBean;
import org.apache.webbeans.newtests.injection.circular.beans.CircularNormalInConstructor;
+import org.apache.webbeans.proxy.OwbNormalScopeProxy;
import org.apache.webbeans.test.component.CheckWithCheckPayment;
import org.apache.webbeans.test.component.CheckWithMoneyPayment;
import org.apache.webbeans.test.component.IPayment;
@@ -43,10 +44,8 @@ import org.apache.webbeans.util.WebBeans
import junit.framework.Assert;
-import org.junit.Ignore;
import org.junit.Test;
-import javassist.util.proxy.ProxyObject;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.context.spi.Context;
@@ -91,7 +90,6 @@ public class SerializationTest extends A
Assert.assertNotNull(cc2);
}
- @Ignore // TODO Make this work!!! XXX
@Test
public void testPersonalDataBean() throws ClassNotFoundException, IOException
{
@@ -150,8 +148,8 @@ public class SerializationTest extends A
Context sessContext2 = (Context) deSerializeObject(ba);
Assert.assertNotNull(sessContext2);
}
-
- //X TODO this will work after JASSIST-97 got fixed @Test
+
+ @Test
public void testProxySerialization() throws Exception
{
Collection<Class<?>> classes = new ArrayList<Class<?>>();
@@ -173,7 +171,7 @@ public class SerializationTest extends A
SessScopedBean reference = (SessScopedBean) getBeanManager().getReference(bean, SessScopedBean.class, ssbCreational);
Assert.assertNotNull(reference);
- Assert.assertTrue(reference instanceof ProxyObject);
+ Assert.assertTrue(reference instanceof OwbNormalScopeProxy);
reference.getApp().setI(4711);