You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwebbeans.apache.org by yi...@apache.org on 2010/08/06 17:50:13 UTC
svn commit: r983030 - in /openwebbeans/trunk:
webbeans-spi/src/main/java/org/apache/webbeans/spi/
webbeans-web/src/main/java/org/apache/webbeans/web/failover/
Author: yingwang
Date: Fri Aug 6 15:50:13 2010
New Revision: 983030
URL: http://svn.apache.org/viewvc?rev=983030&view=rev
Log:
[OWB-385] commit failover part1
Added:
openwebbeans/trunk/webbeans-spi/src/main/java/org/apache/webbeans/spi/FailOverService.java
openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/
openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/DefaultOwbFailOverService.java
openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBag.java
openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBagWrapper.java
Added: openwebbeans/trunk/webbeans-spi/src/main/java/org/apache/webbeans/spi/FailOverService.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-spi/src/main/java/org/apache/webbeans/spi/FailOverService.java?rev=983030&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-spi/src/main/java/org/apache/webbeans/spi/FailOverService.java (added)
+++ openwebbeans/trunk/webbeans-spi/src/main/java/org/apache/webbeans/spi/FailOverService.java Fri Aug 6 15:50:13 2010
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.webbeans.spi;
+
+import javax.servlet.http.HttpSession;
+
+public interface FailOverService
+{
+ /**
+ * Used for tracking the origin of serialized bean instances.
+ *
+ * @return
+ */
+ public String getJVMId();
+
+ /**
+ * The session attribute name used to store the bean instances bag
+ *
+ * @return
+ */
+ public String getFailOverAttributeName();
+
+ public boolean isSupportFailOver();
+
+ public boolean isSupportPassivation();
+
+ public void enableFailOverSupport(boolean flag);
+
+ public void enablePassivationSupport(boolean flag);
+
+ /**
+ * Inform the service that a session is idle. Invoked when we finish
+ * a request.
+ *
+ * @param session
+ */
+ public void sessionIsIdle(HttpSession session);
+
+ /**
+ * Inform the service that a session will be active. Invoked when
+ * a request is received.
+ *
+ * @param session
+ */
+ public void sessionIsInUse(HttpSession session);
+
+ /**
+ * Invoked when we try to restore cdi bean instances. Invoked when
+ * a request is finished.
+ *
+ * @param session
+ */
+ public void restoreBeans(HttpSession session);
+
+ /**
+ * Container is going to actively passivate a session.
+ *
+ * @param session
+ */
+ public void sessionWillPassivate(HttpSession session);
+}
Added: openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/DefaultOwbFailOverService.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/DefaultOwbFailOverService.java?rev=983030&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/DefaultOwbFailOverService.java (added)
+++ openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/DefaultOwbFailOverService.java Fri Aug 6 15:50:13 2010
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.webbeans.web.failover;
+
+import java.util.UUID;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import javax.servlet.http.HttpSession;
+
+import org.apache.webbeans.config.OpenWebBeansConfiguration;
+import org.apache.webbeans.logger.WebBeansLogger;
+import org.apache.webbeans.spi.FailOverService;
+
+public class DefaultOwbFailOverService implements FailOverService
+{
+ /**Logger instance*/
+ private static final WebBeansLogger logger = WebBeansLogger.getLogger(DefaultOwbFailOverService.class);
+
+ private static final String OWB_FAILOVER_JVM_ID =
+ UUID.randomUUID().toString() + "_" +
+ String.valueOf(System.currentTimeMillis());
+
+ private static final String OWB_FAILOVER_PROPERTY_NAME =
+ "org.apache.webbeans.web.failover";
+
+ private static final String OWB_FAILOVER_IS_SUPPORT_FAILOVER =
+ "org.apache.webbeans.web.failover.issupportfailover";
+
+ private static final String OWB_FAILOVER_IS_SUPPORT_PASSIVATE =
+ "org.apache.webbeans.web.failover.issupportpassivation";
+
+ boolean isSupportFailOver;
+
+ boolean isSupportPassivation;
+
+ public DefaultOwbFailOverService ()
+ {
+ String value;
+ value = OpenWebBeansConfiguration.getInstance().
+ getProperty(OWB_FAILOVER_IS_SUPPORT_FAILOVER);
+ if (value != null && value.equalsIgnoreCase("true"))
+ {
+ isSupportFailOver = true;
+ }
+
+ value = OpenWebBeansConfiguration.getInstance().
+ getProperty(OWB_FAILOVER_IS_SUPPORT_PASSIVATE);
+ if (value != null && value.equalsIgnoreCase("true"))
+ {
+ isSupportPassivation = true;
+ }
+ if (logger.wblWillLogDebug())
+ {
+ logger.debug("DefaultOwbFailOverService isSupportFailOver: [{0}]", String.valueOf(isSupportFailOver));
+ logger.debug("DefaultOwbFailOverService isSupportPassivation: [{0}]", String.valueOf(isSupportPassivation));
+ }
+ }
+
+ public String getJVMId()
+ {
+ return OWB_FAILOVER_JVM_ID;
+ }
+
+ public String getFailOverAttributeName()
+ {
+ return OWB_FAILOVER_PROPERTY_NAME;
+ }
+
+ public void sessionIsIdle(HttpSession session)
+ {
+ if (session != null)
+ {
+ FailOverBagWrapper bagWrapper =
+ (FailOverBagWrapper)session.getAttribute(getFailOverAttributeName());
+ if (bagWrapper == null)
+ {
+ bagWrapper = new FailOverBagWrapper(session, this);
+ }
+ else
+ {
+ bagWrapper.updateOwbFailOverBag(session, this);
+ }
+ // store the bag as an attribute of the session. So when the
+ // session is fail over to other jvm or local disk, the attribute
+ // could also be serialized.
+ session.setAttribute(getFailOverAttributeName(), bagWrapper);
+ }
+ }
+
+ public void sessionIsInUse(HttpSession session)
+ {
+ if (session != null)
+ {
+ FailOverBagWrapper bagWrapper =
+ (FailOverBagWrapper)session.getAttribute(getFailOverAttributeName());
+ if (bagWrapper != null)
+ {
+ bagWrapper.sessionIsInUse();
+ }
+ }
+ }
+
+ @Override
+ public void sessionWillPassivate(HttpSession session)
+ {
+ FailOverBagWrapper bagWrapper = new FailOverBagWrapper(session, this);
+ session.setAttribute(getFailOverAttributeName(), bagWrapper);
+ }
+
+ public void restoreBeans(HttpSession session)
+ {
+ FailOverBagWrapper bagWrapper =
+ (FailOverBagWrapper)session.getAttribute(getFailOverAttributeName());
+ if (bagWrapper != null)
+ {
+ logger.debug("DefaultOwbFailOverService restoreBeans for session: [{0}]", session);
+ bagWrapper.restore();
+ session.removeAttribute(getFailOverAttributeName());
+ }
+ }
+
+ @Override
+ public boolean isSupportFailOver()
+ {
+ return isSupportFailOver;
+ }
+
+ @Override
+ public boolean isSupportPassivation()
+ {
+ return isSupportPassivation;
+ }
+
+ @Override
+ public void enableFailOverSupport(boolean flag)
+ {
+ isSupportFailOver = flag;
+ }
+
+ @Override
+ public void enablePassivationSupport(boolean flag)
+ {
+ isSupportPassivation = flag;
+ }
+
+ private static void verifyTest(FailOverBagWrapper bagWrapper)
+ { //test code
+ byte[] bytes = getBytes(bagWrapper);
+ FailOverBagWrapper bagWrapper3 = (FailOverBagWrapper)getObject(bytes);
+ System.out.println(bagWrapper3);
+ }
+
+ private static byte[] getBytes(Object obj)
+ {
+ ByteArrayOutputStream baos = null;
+ ObjectOutputStream oos = null;
+ byte[] buf = new byte[0];
+
+ try
+ {
+ baos = new ByteArrayOutputStream();
+ oos = new ObjectOutputStream(baos);
+ oos.writeObject(obj);
+ buf = baos.toByteArray();
+
+ oos.close();
+ baos.close();
+ }
+ catch (Throwable e)
+ {
+ e.printStackTrace();
+ }
+
+ return buf;
+ }
+
+ private static Object getObject(byte[] buf)
+ {
+ try
+ {
+ ByteArrayInputStream bais = new ByteArrayInputStream(buf);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ Object obj = ois.readObject();
+ ois.close();
+ return obj;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
Added: openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBag.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBag.java?rev=983030&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBag.java (added)
+++ openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBag.java Fri Aug 6 15:50:13 2010
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.webbeans.web.failover;
+
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.Map;
+
+import javassist.util.proxy.ProxyObjectInputStream;
+import javassist.util.proxy.ProxyObjectOutputStream;
+
+import javax.enterprise.context.Conversation;
+import javax.servlet.http.HttpSession;
+
+import org.apache.webbeans.context.ConversationContext;
+import org.apache.webbeans.context.SessionContext;
+import org.apache.webbeans.conversation.ConversationManager;
+import org.apache.webbeans.logger.WebBeansLogger;
+import org.apache.webbeans.spi.FailOverService;
+import org.apache.webbeans.web.context.SessionContextManager;
+
+/**
+ *
+ * The bag that collects all conversation, session owb bean instances.
+ *
+ */
+public class FailOverBag implements Serializable
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6314819837009653189L;
+
+ /**Logger instance*/
+ private static final WebBeansLogger logger = WebBeansLogger.getLogger(DefaultOwbFailOverService.class);
+
+ String sessionId;
+
+ String owbFailoverJVMId;
+
+ SessionContext sessionContext;
+
+ Map<Conversation, ConversationContext> conversationContextMap;
+
+ public FailOverBag()
+ {
+ }
+
+ public FailOverBag(HttpSession session, FailOverService service)
+ {
+ sessionId = session.getId();
+ owbFailoverJVMId = service.getJVMId();
+ updateOwbFailOverBag(session, service);
+ }
+
+ public void updateOwbFailOverBag(HttpSession session, FailOverService service)
+ {
+ // get the session context
+ SessionContextManager sessionManager = SessionContextManager.getInstance();
+ sessionContext = sessionManager.getSessionContextWithSessionId(session.getId());
+
+ // get all conversation contexts
+ ConversationManager conversationManager = ConversationManager.getInstance();
+ conversationContextMap = conversationManager.getConversationMapWithSessionId(session.getId());
+ }
+
+ public void restore()
+ {
+ try
+ {
+ if (sessionContext != null)
+ {
+ SessionContextManager sessionManager = SessionContextManager.getInstance();
+ sessionManager.addNewSessionContext(sessionId, sessionContext);
+ sessionContext.setActive(true);
+ }
+ if (conversationContextMap != null && !conversationContextMap.isEmpty())
+ {
+ ConversationManager conversationManager = ConversationManager.getInstance();
+ java.util.Iterator<Conversation> it = conversationContextMap.keySet().iterator();
+ while(it.hasNext())
+ {
+ Conversation c = it.next();
+ ConversationContext cc = conversationContextMap.get(c);
+ conversationManager.addConversationContext(c, cc);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+
+ }
+ }
+
+ public String getSessionId()
+ {
+ return this.sessionId;
+ }
+
+ public String getJVMId()
+ {
+ return this.owbFailoverJVMId;
+ }
+
+ public static Object testSerializable(Object obj0)
+ {
+ byte[] buf = getBytes(obj0);
+ Object obj1 = getObject(buf);
+ return obj1;
+ }
+
+ /**
+ * Method getBytes
+ * This method accepts an object and converts it to a byte array.
+ *
+ * @param obj Object instance
+ * @return byte[]
+ */
+ private static byte[] getBytes(Object obj)
+ {
+
+ ByteArrayOutputStream baos = null;
+ ObjectOutputStream oos = null;
+ byte[] buf = new byte[0];
+
+ try
+ {
+ baos = new ByteArrayOutputStream();
+ oos = new ProxyObjectOutputStream(baos);
+ oos.writeObject(obj);
+ buf = baos.toByteArray();
+
+ oos.close();
+ baos.close();
+ }
+ catch (Throwable e)
+ {
+ e.printStackTrace();
+ }
+
+ return buf;
+ }
+
+ private static Object getObject(byte[] buf)
+ {
+ try
+ {
+ ByteArrayInputStream bais = new ByteArrayInputStream(buf);
+ ObjectInputStream ois = new ProxyObjectInputStream(bais);
+ Object obj = ois.readObject();
+ ois.close();
+ return obj;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
Added: openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBagWrapper.java
URL: http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBagWrapper.java?rev=983030&view=auto
==============================================================================
--- openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBagWrapper.java (added)
+++ openwebbeans/trunk/webbeans-web/src/main/java/org/apache/webbeans/web/failover/FailOverBagWrapper.java Fri Aug 6 15:50:13 2010
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.webbeans.web.failover;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.InputStream;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionActivationListener;
+import javax.servlet.http.HttpSessionEvent;
+
+import org.apache.webbeans.corespi.ServiceLoader;
+import org.apache.webbeans.logger.WebBeansLogger;
+import org.apache.webbeans.spi.FailOverService;
+
+import javassist.util.proxy.ProxyObjectInputStream;
+import javassist.util.proxy.ProxyObjectOutputStream;
+
+/**
+ * Use javassist Proxy streams to serialize and restore failover bean bag.
+ *
+ */
+public class FailOverBagWrapper implements HttpSessionActivationListener,
+ Serializable, Externalizable
+{
+ /**Logger instance*/
+ private static final WebBeansLogger logger =
+ WebBeansLogger.getLogger(FailOverBagWrapper.class);
+
+ private transient FailOverService failoverService;
+
+ FailOverBag bag;
+
+ String sessionId;
+
+ boolean isSessionInUse;
+
+ //do not remove, used by serialization.
+ public FailOverBagWrapper()
+ {
+ failoverService = (FailOverService)ServiceLoader.getService(FailOverService.class);
+
+ }
+
+ public FailOverBagWrapper(HttpSession session, FailOverService service)
+ {
+ isSessionInUse = false;
+ sessionId = session.getId();
+ bag = new FailOverBag(session, service);
+ }
+
+ public void updateOwbFailOverBag(HttpSession session, FailOverService service)
+ {
+ isSessionInUse = false;
+ bag.updateOwbFailOverBag(session, service);
+ }
+
+ public void restore()
+ {
+ if (!isSessionInUse)
+ {
+ bag.restore();
+ if (logger.wblWillLogDebug())
+ {
+ logger.debug(sessionId + " from " + bag.getJVMId()
+ + "is restored successfully." );
+ }
+ }
+ else
+ {
+ if (logger.wblWillLogDebug())
+ {
+ logger.debug("restore is skipped because isSessionInUse is true for session " + sessionId);
+ }
+ }
+ }
+
+ public synchronized void sessionIsInUse()
+ {
+ isSessionInUse = true;
+ }
+
+ @Override
+ public void readExternal(ObjectInput in) throws IOException,
+ ClassNotFoundException
+ {
+ isSessionInUse = in.readBoolean();
+ sessionId = (String)in.readObject();
+ if (!isSessionInUse)
+ {
+ byte[] buf = (byte[])in.readObject();
+ ByteArrayInputStream bais = new ByteArrayInputStream(buf);
+ ObjectInputStream ois = new OwbProxyObjectInputStream(bais);
+ bag = (FailOverBag) ois.readObject();
+ ois.close();
+ }
+ }
+
+ @Override
+ public synchronized void writeExternal(ObjectOutput out) throws IOException
+ {
+ out.writeBoolean(isSessionInUse);
+ out.writeObject(sessionId);
+ if (isSessionInUse)
+ {
+ if (logger.wblWillLogDebug())
+ {
+ logger.debug("writeExternal skip writing because session is in use for sessionid" +
+ sessionId);
+ }
+ return;
+ }
+
+ // We could not directly use java object stream since we are
+ // using javassist. Serialize the bag by use javassist object
+ // stream.
+ ByteArrayOutputStream baos = null;
+ ObjectOutputStream oos = null;
+ byte[] buf = null;
+ try
+ {
+ baos = new ByteArrayOutputStream();
+ oos = new ProxyObjectOutputStream(baos);
+ oos.writeObject(bag);
+ oos.flush();
+ buf = baos.toByteArray();
+ oos.close();
+ baos.close();
+ out.writeObject(buf);
+ }
+ catch (Throwable e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * A little wrapper class to correct the class loader.
+ */
+ public static class OwbProxyObjectInputStream extends ProxyObjectInputStream
+ {
+ public OwbProxyObjectInputStream(InputStream in) throws IOException
+ {
+ super(in);
+ }
+
+ protected Class<?> resolveClass(ObjectStreamClass desc)
+ throws IOException, ClassNotFoundException
+ {
+ String name = desc.getName();
+ try
+ {
+ return Class.forName(name, false,
+ Thread.currentThread().getContextClassLoader());
+ }
+ catch (ClassNotFoundException ex)
+ {
+ return super.resolveClass(desc);
+ }
+ }
+ }
+
+ @Override
+ public void sessionWillPassivate(HttpSessionEvent event)
+ {
+ if (failoverService != null &&
+ failoverService.isSupportPassivation())
+ {
+ HttpSession session = event.getSession();
+ failoverService.sessionWillPassivate(session);
+ }
+
+ }
+
+ @Override
+ public void sessionDidActivate(HttpSessionEvent event)
+ {
+ if (failoverService.isSupportFailOver() ||
+ failoverService.isSupportPassivation())
+ {
+ HttpSession session = event.getSession();
+ failoverService.restoreBeans(session);
+ }
+ }
+}