/*
* 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
{
}
}