Author: dallen6
Date: 2010-05-03 09:40:20 -0400 (Mon, 03 May 2010)
New Revision: 6211
Added:
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/SwitchableCLProxyServices.java
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java
core/trunk/impl/src/main/java/org/jboss/weld/bean/proxy/util/SerializableProxy.java
core/trunk/impl/src/main/java/org/jboss/weld/logging/messages/BeanMessage.java
core/trunk/impl/src/main/resources/org/jboss/weld/messages/bean_en.properties
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/AbstractClusterTest.java
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/SwitchableMockEELifecycle.java
Log:
Added separate class loaders for cluster test to use with proxies and fixed discovered
problems with proxy deserialization
Modified: core/trunk/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java
===================================================================
--- core/trunk/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java 2010-05-03
08:22:14 UTC (rev 6210)
+++ core/trunk/impl/src/main/java/org/jboss/weld/bean/proxy/ProxyFactory.java 2010-05-03
13:40:20 UTC (rev 6211)
@@ -22,6 +22,8 @@
import static
org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_BEAN_ACCESS_FAILED;
import static org.jboss.weld.logging.messages.BeanMessage.PROXY_INSTANTIATION_FAILED;
+import java.io.IOException;
+import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.reflect.Modifier;
@@ -324,13 +326,21 @@
CtClass objectClass = classPool.get(Object.class.getName());
String writeReplaceBody = "{ " +
" if (firstSerializationPhaseComplete) {" +
- " firstSerializationPhaseComplete = true; " +
+ " firstSerializationPhaseComplete = false; " +
" return $0; " +
" } else {" +
" firstSerializationPhaseComplete = true; " +
" return
((org.jboss.weld.serialization.spi.ProxyServices)org.jboss.weld.Container.instance().services().get(org.jboss.weld.serialization.spi.ProxyServices.class)).wrapForSerialization($0);"
+
" } }";
proxyClassType.addMethod(CtNewMethod.make(objectClass, "writeReplace",
null, new CtClass[] { exception }, writeReplaceBody, proxyClassType));
+
+ // Also add a static method that can be used to deserialize a proxy object.
+ // This causes the OO input stream to use the class loader from this class.
+ CtClass objectInputStreamClass =
classPool.get(ObjectInputStream.class.getName());
+ CtClass cnfe = classPool.get(ClassNotFoundException.class.getName());
+ CtClass ioe = classPool.get(IOException.class.getName());
+ String deserializeProxyBody = "{ return $1.readObject(); }";
+ proxyClassType.addMethod(CtNewMethod.make(Modifier.STATIC | Modifier.PUBLIC,
objectClass, "deserializeProxy", new CtClass[]{objectInputStreamClass}, new
CtClass[]{cnfe, ioe}, deserializeProxyBody, proxyClassType));
}
catch (Exception e)
{
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/bean/proxy/util/SerializableProxy.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/bean/proxy/util/SerializableProxy.java 2010-05-03
08:22:14 UTC (rev 6210)
+++
core/trunk/impl/src/main/java/org/jboss/weld/bean/proxy/util/SerializableProxy.java 2010-05-03
13:40:20 UTC (rev 6211)
@@ -17,6 +17,9 @@
package org.jboss.weld.bean.proxy.util;
+import static org.jboss.weld.logging.messages.BeanMessage.PROXY_DESERIALIZATION_FAILURE;
+import static org.jboss.weld.logging.messages.BeanMessage.PROXY_REQUIRED;
+
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -26,15 +29,15 @@
import org.jboss.weld.Container;
import org.jboss.weld.bean.proxy.ProxyFactory;
import org.jboss.weld.exceptions.ForbiddenStateException;
-import org.jboss.weld.logging.messages.BeanMessage;
+import org.jboss.weld.exceptions.WeldException;
import org.jboss.weld.serialization.spi.ProxyServices;
/**
- * A wrapper mostly for client proxies which provides header information
- * useful to generate the client proxy class in a VM before the proxy
- * object is deserialized. Only client proxies really need this
- * extra step for serialization and deserialization since the other
- * proxy classes are generated during bean archive deployment.
+ * A wrapper mostly for client proxies which provides header information useful
+ * to generate the client proxy class in a VM before the proxy object is
+ * deserialized. Only client proxies really need this extra step for
+ * serialization and deserialization since the other proxy classes are generated
+ * during bean archive deployment.
*
* @author David Allen
*/
@@ -44,17 +47,17 @@
private static final long serialVersionUID = -7682006876407447753L;
// Information required to generate client proxy classes
- private final String proxyClassName;
- private final String proxySuperClassName;
+ private final String proxyClassName;
+ private final String proxySuperClassName;
// The wrapped proxy object not serialized by default actions
- private transient Object proxyObject;
+ private transient Object proxyObject;
public SerializableProxy(Object proxyObject)
{
if (!ProxyFactory.isProxy(proxyObject))
{
- throw new ForbiddenStateException(BeanMessage.PROXY_REQUIRED);
+ throw new ForbiddenStateException(PROXY_REQUIRED);
}
this.proxyClassName = proxyObject.getClass().getName();
this.proxySuperClassName = proxyObject.getClass().getSuperclass().getName();
@@ -62,9 +65,9 @@
}
/**
- * Writes this object to the stream and also appends the serialization of
- * the proxy object afterwards. This allows this wrapper to later recover
- * the proxy class before trying to deserialize the proxy object.
+ * Writes this object to the stream and also appends the serialization of the
+ * proxy object afterwards. This allows this wrapper to later recover the
+ * proxy class before trying to deserialize the proxy object.
*
* @param out the output stream of objects
* @throws IOException
@@ -91,11 +94,24 @@
// Must use another OO stream per writeObject() above
ObjectInputStream in2 = new ObjectInputStream(in);
Class<?> proxyBeanType =
Container.instance().services().get(ProxyServices.class).loadProxySuperClass(proxySuperClassName);
+ Class<?> proxyClass = null;
if (proxyClassName.endsWith(ProxyFactory.PROXY_SUFFIX))
{
- generateClientProxyClass(proxyBeanType);
+ proxyClass = generateClientProxyClass(proxyBeanType);
}
- proxyObject = in2.readObject();
+ else
+ {
+ // All other proxy classes always exist where a Weld container was deployed
+ proxyClass =
Container.instance().services().get(ProxyServices.class).getClassLoader(proxyBeanType).loadClass(proxyClassName);
+ }
+ try
+ {
+ proxyObject = proxyClass.getDeclaredMethod("deserializeProxy",
ObjectInputStream.class).invoke(null, in2);
+ }
+ catch (Exception e)
+ {
+ throw new WeldException(PROXY_DESERIALIZATION_FAILURE, e);
+ }
}
/**
@@ -108,9 +124,9 @@
{
return proxyObject;
}
-
- private <T> void generateClientProxyClass(Class<T> beanType)
+
+ private <T> Class<?> generateClientProxyClass(Class<T> beanType)
{
- new ProxyFactory<T>(beanType).getProxyClass();
+ return new ProxyFactory<T>(beanType).getProxyClass();
}
}
Modified: core/trunk/impl/src/main/java/org/jboss/weld/logging/messages/BeanMessage.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/logging/messages/BeanMessage.java 2010-05-03
08:22:14 UTC (rev 6210)
+++
core/trunk/impl/src/main/java/org/jboss/weld/logging/messages/BeanMessage.java 2010-05-03
13:40:20 UTC (rev 6211)
@@ -30,6 +30,7 @@
* Log messages for Beans.
*
* Message IDs: 000000 - 000099
+ * 001500 - 001599
*
*/
public enum BeanMessage
@@ -133,6 +134,7 @@
@MessageId("000096") PRODUCER_FIELD_ON_SESSION_BEAN_MUST_BE_STATIC,
@MessageId("000097")
PRODUCER_METHOD_WITH_TYPE_VARIABLE_RETURN_TYPE_MUST_BE_DEPENDENT,
@MessageId("000098")
PRODUCER_METHOD_WITH_WILDCARD_RETURN_TYPE_MUST_BE_DEPENDENT,
- @MessageId("000099") CANNOT_LOAD_CLASS;
+ @MessageId("000099") CANNOT_LOAD_CLASS,
+ @MessageId("001500") PROXY_DESERIALIZATION_FAILURE;
}
Modified: core/trunk/impl/src/main/resources/org/jboss/weld/messages/bean_en.properties
===================================================================
---
core/trunk/impl/src/main/resources/org/jboss/weld/messages/bean_en.properties 2010-05-03
08:22:14 UTC (rev 6210)
+++
core/trunk/impl/src/main/resources/org/jboss/weld/messages/bean_en.properties 2010-05-03
13:40:20 UTC (rev 6211)
@@ -98,3 +98,4 @@
PRODUCER_METHOD_WITH_TYPE_VARIABLE_RETURN_TYPE_MUST_BE_DEPENDENT=A producer method with a
parameterized return type with a type variable must be declared @Dependent scoped. Method
{0}
PRODUCER_METHOD_WITH_WILDCARD_RETURN_TYPE_MUST_BE_DEPENDENT=A producer method with a
parameterized return type with a wildcard must be declared @Dependent scoped. Method {0}
CANNOT_LOAD_CLASS=Cannot load class {0} during deserialization of proxy
+PROXY_DESERIALIZATION_FAILURE=Failed to deserialize proxy object
Modified:
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/AbstractClusterTest.java
===================================================================
---
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/AbstractClusterTest.java 2010-05-03
08:22:14 UTC (rev 6210)
+++
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/AbstractClusterTest.java 2010-05-03
13:40:20 UTC (rev 6211)
@@ -24,11 +24,8 @@
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import javax.enterprise.inject.spi.PassivationCapable;
-
import org.jboss.weld.Container;
import org.jboss.weld.bootstrap.api.Singleton;
import org.jboss.weld.context.ContextLifecycle;
@@ -36,9 +33,8 @@
import org.jboss.weld.context.api.ContextualInstance;
import org.jboss.weld.context.beanstore.HashMapBeanStore;
import org.jboss.weld.manager.BeanManagerImpl;
-import org.jboss.weld.mock.MockEELifecycle;
import org.jboss.weld.mock.TestContainer;
-import org.jboss.weld.serialization.spi.helpers.SerializableContextual;
+import org.jboss.weld.serialization.spi.ProxyServices;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@@ -47,6 +43,7 @@
private Singleton<Container> singleton;
+ @SuppressWarnings("unchecked")
@BeforeClass
public void beforeClass() throws Exception
{
@@ -72,7 +69,7 @@
// Bootstrap container
SwitchableSingletonProvider.use(id);
- TestContainer container = new TestContainer(new MockEELifecycle(), classes, null);
+ TestContainer container = new TestContainer(new SwitchableMockEELifecycle(),
classes, null);
container.startContainer();
container.ensureRequestActive();
@@ -131,4 +128,8 @@
return in.readObject();
}
+ protected void useNewClassLoader(ClassLoader parentClassLoader)
+ {
+
((SwitchableCLProxyServices)Container.instance().services().get(ProxyServices.class)).useNewClassLoader(parentClassLoader);
+ }
}
\ No newline at end of file
Added:
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/SwitchableCLProxyServices.java
===================================================================
---
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/SwitchableCLProxyServices.java
(rev 0)
+++
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/SwitchableCLProxyServices.java 2010-05-03
13:40:20 UTC (rev 6211)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat, Inc. and/or its affiliates, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jboss.weld.mock.cluster;
+
+import org.jboss.weld.bean.proxy.util.SimpleProxyServices;
+import org.jboss.weld.exceptions.WeldException;
+
+/**
+ * Uses a special CL to hold the proxies and allows a test to switch to a new
+ * CL. This is useful for testing cluster environments where the VMs are
+ * different and thus the CL would also be different between serialization and
+ * deserialization.
+ *
+ * @author David Allen
+ */
+public class SwitchableCLProxyServices extends SimpleProxyServices
+{
+ private ClassLoader currentClassLoader;
+
+ @Override
+ public ClassLoader getClassLoader(Class<?> type)
+ {
+ if (currentClassLoader == null)
+ {
+ ClassLoader baseClassLoader = super.getClassLoader(type);
+ useNewClassLoader(baseClassLoader);
+ }
+ return currentClassLoader;
+ }
+
+ @Override
+ public Class<?> loadProxySuperClass(String className)
+ {
+ try
+ {
+ return currentClassLoader.loadClass(className);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new WeldException(e);
+ }
+ }
+
+ public void useNewClassLoader(ClassLoader parentClassLoader)
+ {
+ currentClassLoader = new ClusterClassLoader(parentClassLoader);
+ }
+}
Modified:
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/SwitchableMockEELifecycle.java
===================================================================
---
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/SwitchableMockEELifecycle.java 2010-05-03
08:22:14 UTC (rev 6210)
+++
core/trunk/tests/src/main/java/org/jboss/weld/mock/cluster/SwitchableMockEELifecycle.java 2010-05-03
13:40:20 UTC (rev 6211)
@@ -16,49 +16,17 @@
*/
package org.jboss.weld.mock.cluster;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.jboss.weld.context.api.BeanStore;
import org.jboss.weld.mock.MockEELifecycle;
+import org.jboss.weld.serialization.spi.ProxyServices;
public class SwitchableMockEELifecycle extends MockEELifecycle
{
+ private SwitchableCLProxyServices proxyServices;
- private final Map<Integer, BeanStore> requestBeanStores;
- private final Map<Integer, BeanStore> sessionBeanStores;
- private final Map<Integer, BeanStore> applicationBeanStores;
-
- private int id = 1;
-
public SwitchableMockEELifecycle()
{
- this.requestBeanStores = new HashMap<Integer, BeanStore>();
- this.sessionBeanStores = new HashMap<Integer, BeanStore>();
- this.applicationBeanStores = new HashMap<Integer, BeanStore>();
+ proxyServices = new SwitchableCLProxyServices();
+ getDeployment().getServices().add(ProxyServices.class, proxyServices);
}
- @Override
- protected BeanStore getRequestBeanStore()
- {
- return requestBeanStores.get(id);
- }
-
- @Override
- protected BeanStore getSessionBeanStore()
- {
- return sessionBeanStores.get(id);
- }
-
- @Override
- protected BeanStore getApplicationBeanStore()
- {
- return applicationBeanStores.get(id);
- }
-
- public void use(int id)
- {
- this.id = id;
- }
-
}