/* * JBoss, Home of Professional Open Source. * Copyright 2008, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.test.jca.ejb; import org.jboss.logging.Logger; import org.jboss.mx.util.MBeanServerLocator; import org.jboss.test.jca.interfaces.HAConnectionSession; import org.jboss.test.jca.adapter.MockedXADataSource; import org.jboss.system.ServiceMBean; import javax.ejb.SessionBean; import javax.ejb.SessionContext; import javax.ejb.EJBException; import javax.ejb.CreateException; import javax.sql.DataSource; import javax.naming.InitialContext; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.InstanceNotFoundException; import javax.management.MBeanException; import javax.management.ReflectionException; import javax.management.AttributeNotFoundException; import java.rmi.RemoteException; import java.sql.Connection; /** * @ejb.bean * name="HAConnectionSession" * view-type="remote" * type="Stateless" * * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a> * @version <tt>$Revision: 81036 $</tt> */ public class HAConnectionSessionBean implements SessionBean { /** The serialVersionUID */ private static final long serialVersionUID = 1L; private static final Logger log = Logger.getLogger(HAConnectionSessionBean.class); private SessionContext ctx; /** * @ejb.interface-method * @ejb.transaction type="NotSupported" */ public void testHaLocalConnection() throws Exception { //String url1 = "jdbc:hsqldb:hsql://localhost:1702"; //String url2 = "jdbc:hsqldb:hsql://localhost:1703"; String port1 = "1702"; String port2 = "1703"; ObjectName db1 = new ObjectName("jboss:service=Hypersonic,database=haLocalDB1"); ObjectName db2 = new ObjectName("jboss:service=Hypersonic,database=haLocalDB2"); MBeanServer server = MBeanServerLocator.locateJBoss(); waitForState(server, db1, ServiceMBean.STARTED); waitForState(server, db2, ServiceMBean.STARTED); DataSource ds = (DataSource)new InitialContext().lookup("java:/TestHADefaultDS"); stopDb(server, db2); String expectedPort = port1; for(int i = 0; i < 10; ++i) { HAConnectionSession me = (HAConnectionSession)ctx.getEJBObject(); String conUrl = me.getHAConnectionURL(ds); log.debug("got connection to: " + conUrl); if(!conUrl.endsWith(expectedPort)) { throw new Exception("Expected " + expectedPort + " but got " + conUrl); } if(conUrl.endsWith(port1)) { stopDb(server, db1); startDb(server, db2); expectedPort = port2; } else if(conUrl.endsWith(port2)) { stopDb(server, db2); startDb(server, db1); expectedPort = port1; } else { throw new Exception("Unexpected connection url: " + conUrl); } } } /** * @ejb.interface-method * @ejb.transaction type="NotSupported" */ public void testHaXaConnection() throws Exception { String[] urls = MockedXADataSource.getUrls(); for(int i = 1; i < urls.length; ++i) { MockedXADataSource.stop(urls[i]); } DataSource ds = (DataSource)new InitialContext().lookup("java:/MockedHaXaDS"); HAConnectionSession facade = (HAConnectionSession)ctx.getEJBObject(); for(int i = 0; i < 3*urls.length; ++i) { String url = facade.getHAConnectionURL(ds); int urlIndex = i % urls.length; if(!url.equals(urls[urlIndex])) { throw new IllegalStateException("Connected to a wrong database: " + url + ", expected " + urls[urlIndex]); } MockedXADataSource.stop(url); urlIndex = (i + 1) % urls.length; MockedXADataSource.start(urls[urlIndex]); } } /** * @ejb.interface-method * @ejb.transaction type="RequiresNew" */ public String getHAConnectionURL(DataSource ds) throws Exception { Connection con = null; try { con = ds.getConnection(); return con.getMetaData().getURL(); } finally { if(con != null) { con.close(); } } } private void startDb(MBeanServer server, ObjectName db2) throws InstanceNotFoundException, MBeanException, ReflectionException, AttributeNotFoundException { server.invoke(db2, "start", null, null); waitForState(server, db2, ServiceMBean.STARTED); } private void stopDb(MBeanServer server, ObjectName db2) throws InstanceNotFoundException, MBeanException, ReflectionException, AttributeNotFoundException { server.invoke(db2, "stop", null, null); waitForState(server, db2, ServiceMBean.STOPPED); } private void waitForState(MBeanServer server, ObjectName db2, int state) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException { Integer stateValue = (Integer)server.getAttribute(db2, "State"); while(stateValue.intValue() != state) { try { Thread.sleep(500); } catch(InterruptedException e) { } stateValue = (Integer)server.getAttribute(db2, "State"); } // The hypersonic MBean is not implementated properly // It goes into state STARTED when in reality there is // a background thread still recovering the server if (stateValue.intValue() == ServiceMBean.STARTED) { try { Thread.sleep(5000); } catch (InterruptedException e) { } } } /** * @throws javax.ejb.CreateException Description of Exception * @ejb.create-method */ public void ejbCreate() throws CreateException { } public void setSessionContext(SessionContext ctx) throws EJBException, RemoteException { this.ctx = ctx; } public void ejbRemove() throws EJBException, RemoteException { } public void ejbActivate() throws EJBException, RemoteException { } public void ejbPassivate() throws EJBException, RemoteException { } }