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!
