Samples for AIL-Based Application
File bc.properties
PrimaryHost1 = bsgen803julien PrimaryPort1 = 2020 BackupHost1 = bsgen803julien BackupPort1 = 2030 ApplicationName1 = AIL_Client PlaceName1 = Place_5320 UserName = SIP_5320 UserPass = PrimaryHost2 = Suite80GAJulien PrimaryPort2 = 2020 BackupHost2 = Suite80GAJulien BackupPort2 = 2022 ApplicationName2 = AIL_Client PlaceName2 = Place_5320
File BusinessContinuity.java
package com.genesyslab.ail.applicationblocks.businesscontinuity; import java.io.*; import java.util.*; import com.genesyslab.ail.*; import com.genesyslab.ail.event.*; import org.apache.log4j.*; public class BusinessContinuity { Logger mLogger; Properties mProperties; HashMap mSite1; HashMap mSite2; AilLoader mAL; AilFactory mAF; boolean mSwitchingOver; boolean mSwitchoverScheduled; int mSwitchoverDelay = 30; boolean mFirstConnection = true; ServiceListener mServiceListener; Place mPlace; Person mAgent; Dn mDN; DnListener mDnListener; int mCurrentSite = 1; Timer mTimer = new Timer(); static BusinessContinuity mBC; public static void main(String[] s) { mBC = new BusinessContinuity(); } public BusinessContinuity() { mLogger = org.apache.log4j.LogManager.getLoggerRepository().getLogger("BC"); // This sample stores data in a property file as an example mProperties = new Properties(); try { mProperties.load(new FileInputStream("bc.properties")); } catch (Exception e) { mLogger.error("Did not find bc.properties"); System.exit(0); } // Connection parameters read in the file for site 1 mSite1 = new HashMap(); mSite1.put("PrimaryHost", mProperties.getProperty("PrimaryHost1")); mSite1.put("PrimaryPort", new Integer(mProperties.getProperty("PrimaryPort1"))); mSite1.put("BackupHost", mProperties.getProperty("BackupHost1")); mSite1.put("BackupPort", new Integer(mProperties.getProperty("BackupPort1"))); mSite1.put("ApplicationName", mProperties.getProperty("ApplicationName1")); mSite1.put("ApplicationType", AilLoader.ApplicationType.CLIENT); mSite1.put("UserName", mProperties.getProperty("UserName")); mSite1.put("UserPass", ""); mSite1.put("PlaceName", mProperties.getProperty("PlaceName1")); // Connection parameters read in the file for site 2 mSite2 = new HashMap(); mSite2.put("PrimaryHost", mProperties.getProperty("PrimaryHost2")); mSite2.put("PrimaryPort", new Integer(mProperties.getProperty("PrimaryPort2"))); mSite2.put("BackupHost", mProperties.getProperty("BackupHost2")); mSite2.put("BackupPort", new Integer(mProperties.getProperty("BackupPort2"))); mSite2.put("ApplicationName", mProperties.getProperty("ApplicationName2")); mSite2.put("ApplicationType", AilLoader.ApplicationType.CLIENT); mSite2.put("UserName", mProperties.getProperty("UserName")); mSite2.put("UserPass", ""); mSite2.put("PlaceName", mProperties.getProperty("PlaceName2")); // Initiate a logger for traces mLogger = org.apache.log4j.LogManager.getLoggerRepository().getLogger("BC"); // Try and connect to the first site. mCurrentSite = 1; connect(mSite1); } private void connect(Map site) { try { mLogger.info("Connecting to " + site.get("PrimaryHost")); // Builds an AILLoader mAL = new AilLoader((String) site.get("PrimaryHost"), ((Integer) site.get("PrimaryPort")).intValue(), (String) site.get("BackupHost"), ((Integer) site.get("BackupPort")).intValue(), (String) site.get("UserName"), (String) site.get("UserPass"), (String) site.get("ApplicationName"), (AilLoader.ApplicationType) site.get("ApplicationType"), 15, // This is the general timeout for AIl requests 10); // This is the delay AIL waits when trying again to connect to a server // Starts AIL mAF = mAL.getAilFactory(); // At this point, mAF is null if the config server could not be reached for instance if (mAF == null) { mLogger.error(mAL.getInitException()); switchover(); } // The serviceListener will listen and react on services status change mServiceListener = new ServiceListener() { public void serviceStatusChanged(ServiceStatus.Type type, String name, ServiceStatus.Status status) { try { if (status.toInt() == ServiceStatus.Status.OFF_) { switch (type.toInt()) { case ServiceStatus.Type.TELEPHONY_: case ServiceStatus.Type.CONFIG_: case ServiceStatus.Type.STAT_: scheduleSwitchover(); break; } } } catch (Throwable t) { mLogger.error("While processing serviceStatusChanged, ", t); } } }; // Listen to three types of services mAF.addServiceListener(ServiceStatus.Type.CONFIG, mServiceListener); mAF.addServiceListener(ServiceStatus.Type.STAT, mServiceListener); mAF.addServiceListener(ServiceStatus.Type.TELEPHONY, mServiceListener); // In this sample, the UserName UserPassword and PlaceName are stores in the properties file. // You probably want to read them from a login banner. mPlace = mAF.getPlace((String) mProperties.getProperty("PlaceName" + mCurrentSite)); mLogger.info("Place is " + mPlace); mAgent = mAF.getPerson((String) mProperties.getProperty("UserName")); Map annex = mAgent.getAnnex(); try { Map section = (Map) annex.get("agent-desktop"); if (mFirstConnection) { String preferred = (String) section.get("disaster-recovery.preferred-site"); if (!mProperties.getProperty("ApplicationName1").equals(preferred)) { // Switch Site 1 and site 2 in the properties file or wherever you store that info. } mSwitchoverDelay = Integer.parseInt((String) section.get("disaster-recovery.timeout")); mFirstConnection = false; } } catch (Exception e) { mLogger.warn("Agent " + mAgent.getName() + " does not have the expected annex"); } mDN = (Dn) mPlace.getDns().iterator().next(); // Listens to the DN status and initiates a switchover on graceful shutdown. mDnListener = new DnListener() { public void handleDnEvent(DnEvent event) { try { if (event.getStatus().toInt() == Dn.Status.LOGGED_OUT_ || event.getStatus().toInt() == Dn.Status.BUSY_LOGGED_OUT_) { Map tExtensions = event.getTEventExtensions(); if (tExtensions != null) { String reasonCode = (String) tExtensions.get("ReasonCode"); if ("graceful_shutdown_logout".equals(reasonCode)) { switchover(); } } } } catch (Throwable t) { mLogger.error("While processing DNEvent, ", t); } } public void deleted() { } public void contactChanged(InteractionEvent ie) { } public void handleInteractionEvent(InteractionEvent ie) { } }; if (mDN != null) { mDN.addDnListener(mDnListener); } mLogger.info("DN is " + mDN); } catch (Throwable t2) { mLogger.error("While connecting, ", t2); } } // Before actually doing a switchover, we want to give a chance to the server/network to get back in service private void scheduleSwitchover() { if (!mSwitchoverScheduled) { mSwitchoverScheduled = true; mLogger.info("Scheduling switchover"); // Schedule the switchover in a timer task. We don't want to wait in this thread. // We are in a callback thread because this method is called from listeners. mTimer.schedule(new TimerTask() { public void run() { Map services = mAF.getServices(); if (getService(services, ServiceStatus.Type.TELEPHONY).mStatus.toInt() == ServiceStatus.Status.ON_ && getService(services, ServiceStatus.Type.CONFIG).mStatus.toInt() == ServiceStatus.Status.ON_ && getService(services, ServiceStatus.Type.STAT).mStatus.toInt() == ServiceStatus.Status.ON_) { mLogger.info("Services are ON. Switchover cancelled"); // Don't switchover if the services are all ON. mSwitchoverScheduled = false; return; } else { switchover(); mSwitchoverScheduled = false; } } }, mSwitchoverDelay * 1000); } } private ServiceStatus getService(Map services, ServiceStatus.Type type) { for (Iterator it = services.values().iterator() ; it.hasNext() ; ) { ServiceStatus ss = (ServiceStatus) it.next(); if (ss.mType.toInt() == type.toInt()) { return ss; } } return null; } // The switchover procedure itself // It invokes the timer in order to release the thread that calls // because it is probably a callback thread and we don't want to // private void switchover() { try { if (mSwitchingOver) { mLogger.warn("Already switching over"); return; } mSwitchingOver = true; mLogger.info("Switching over. Current site was " + mCurrentSite); if (mDN != null) { mDN.removeDnListener(mDnListener); } if (mAF != null) { mAF.removeServiceListener(ServiceStatus.Type.TELEPHONY, mServiceListener); } // Release all the references to the objects coming from the previous factory mServiceListener = null; mDnListener = null; mPlace = null; mDN = null; mAF = null; // Kill the old AilFactory mAL.killFactory(); if (mCurrentSite == 1) { mCurrentSite = 2; connect(mSite2); } else { mCurrentSite = 1; connect(mSite1); } mLogger.info("Switchover completed. Current site is now " + mCurrentSite); mSwitchingOver = false; } catch (Throwable t) { mLogger.error("While running switchover, ", t); } } }
This page was last edited on June 10, 2013, at 13:54.
Comments or questions about this documentation? Contact us for support!