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);
+        }
+    }
+}