Automating configuration changes using AIR (Flex)


The example below shows how to automatically initiate a stateful transaction, retrieve a list of all Watchpoints, add a Watchpoint based on a new custom field, and commit the operations using AIR (Flex).

Before you begin

  • You must modify the HOST, SERVER, USERNAME, and PASSWORD constants so that they correspond with your application settings.
  • The Security role user must enable the Cross-domain policy file via the web interface.

Note

For more information about enabling the Cross-domain policy file, see the  BMC Real End User Experience Monitoring user guide or contact Customer Support.

Example code

<?xml version="1.0" encoding="utf-8"?>
<!--
(c) 2009-20011 BMC, Inc.
Created on 2009-02-10
This sample application demonstrates the basic capabilities of the product Configuration API by Creating a transaction, getting all Watchpoints, creating a custom field, creating a Watchpoint based on that custom field, committing the transaction, and finally terminating the transaction.
Be sure that crossdomain.xml on your device is enabled.
-->
<mx:WindowedApplication
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical" initialize="initializeURLs()">
<mx:TextArea width="602" height="335" id="output" wordWrap="false"/>
<mx:Button id="performTX"
click="performTransaction()"
label="Perform Transaction"/>
<mx:HTTPService id="httpService"
resultFormat="e4x"
fault="handleFailure(event)"
result="handleResult(event)"/>
<!-- The custom field that we will be adding -->
<mx:XML id="customFieldToAdd">
<customField id="100" active="true"
entity="object" srcEntity="object"
type="string" policy="first-non-null"
grammar="custom_test" export="x-custom-test"
size="255">
<name><![CDATA[Test CF]]></name>
<description><![CDATA[Description for Test CF]]></description>
<extractions>
<defaultExtraction>
<source>
<sourceHost/>
</source>
</defaultExtraction>
</extractions>
</customField>
</mx:XML>
<!-- Watchpoint that we will be adding -->
<mx:XML id="watchpointToAdd">
<watchpoint id="50" type="object" active="true"
active-alarm="false" active-mib="false" filter-selection="all">
<name><![CDATA[Test Wp]]></name>
<description><![CDATA[Description for Test Wp]]></description>
<filter active="true">
<name><![CDATA[Test Wp filter]]></name>
<expression><![CDATA[(custom_test is "test" ignorecase)]]></expression>
</filter>
</watchpoint>
</mx:XML>

<mx:Script>
<![CDATA[

import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.messaging.messages.HTTPRequestMessage;
import mx.collections.ArrayCollection;

//Server name and authentication credentials.
private static const SERVER : String = "<HOST>";
private static const USER : String = "<USERNAME>";
private static const PASSWORD : String = "<PASSWORD>";

private var txURL : String;
private var wpURL : String;
private var wpsURL : String;
private var cfURL : String;
private var transactionId : Number;

/**
* This function initializes the URLs necessary to
* carry out the operation:
*
* - Create transaction
* - Get all Watchpoints
* - Create a custom field
* - Create a Watchpoint based on that custom field
* - Commit the transaction
* - Terminate the transaction
*
*
**/

private function initializeURLs() : void
{
/////////////////Transaction URL///////////////////////////////
txURL = "https://" + <SERVER>;
txURL += "/rest/configurationapi";
txURL += "/transactionapi/1.0/transaction";

//Since Flex cannot read the body of any response that is not 200,
//we will override the response status so that code 200 is always
//returned
txURL += "?forceHttpStatus=200";
txURL += "&usr=" + <USERNAME>;
txURL += "&pwd=" + <PASSWORD>;

///////////////////Watchpoint URL//////////////////////////////
wpURL = "https://" + <SERVER>;
wpURL += "/rest/configurationapi";
wpURL += "/watchpointapi/1.0/watchpoint";

//Since Flex cannot read the body of any response that is not 200,
//we will override the response status so that code 200 is always
//returned
wpURL += "?forceHttpStatus=200";
wpURL += "&usr=" + <USERNAME>;
wpURL += "&pwd=" + <PASSWORD>;

//////////////////Watchpoints URL//////////////////////////////
wpsURL = "https://" + <SERVER>;
wpsURL += "/rest/configurationapi";
wpsURL += "/watchpointapi/1.0/watchpoints";

//Since Flex cannot read the body of any response that is not 200,
//we will override the response status so that code 200 is always
//returned
wpsURL += "?forceHttpStatus=200";
wpsURL += "&usr=" + <USERNAME>;
wpsURL += "&pwd=" + <PASSWORD>;

///////////////////////Custom Field URL////////////////////////
cfURL = "https://" + <SERVER>;
cfURL += "/rest/configurationapi";
cfURL += "/customfieldapi/1.0/customfield";

//Since Flex cannot read the body of any response that is not 200,
//we will override the response status so that code 200 is always
//returned
cfURL += "?forceHttpStatus=200";
cfURL += "&usr=" + <USERNAME>;
cfURL += "&pwd=" + <PASSWORD>;
}

/**
* Function that is executed when the user clicks the
* 'Perform Transaction' button.
* The flow of operation is a chain-like process.
*
* The chain is as follows :
*
* Create a transaction
* Make a request to get all Watchpoints
* Make a request to create a custom field
* Make a request to create a Watchpoint
* Make a request to commit the transaction
* Make a request to delete the Transaction
*
*
**/

private function performTransaction() : void {
//Set the transaction timeout to 30 seconds
httpService.url = txURL + "&tto=30";

//Transaction Creation requires a post
httpService.method = HTTPRequestMessage.POST_METHOD;

//We will set the content type to text/xml since, by default,
//the content type is application/x-www-form-urlencoded, which expects
//POST parameters which we WILL NOT be passing.
httpService.contentType = "text/xml";
output.text += "\nConfig API operation: " + httpService.method + " ";
output.text += httpService.url;
var token : AsyncToken = httpService.send();
//The next operation after creating the transaction is to get all Watchpoints
token.nextOperation = getAllWps;
}

/**
* This function will execute the request to get all Watchpoints
*
* @param response - The XML response of the previous request. In this
* case it is the response from a Transaction Create.
* This is passed in case there was anything required
* from the previous request to build this new request.
**/

private function getAllWps(response : XML) : void
{
//We need to set the transaction id
this.transactionId = response.result.tid;

//We will now execute the request to get all Watchpoints
httpService.url = wpsURL + "&tid=" + transactionId;
httpService.method = HTTPRequestMessage.GET_METHOD;
httpService.contentType = "text/plain";
output.text += "\nConfig API operation: " + httpService.method + " ";
output.text += httpService.url;
var token : AsyncToken = httpService.send();

//The next operation will be to create a custom field
token.nextOperation = createCustomField;
}

/**
* This function will make a request to create a custom field
*
* @param response - The XML output response from the previous request
* which was getting all Watchpoints. This is passed in
* case there was anything required from the previous
* request to build this new request.
*
**/

private function createCustomField(response : XML) : void
{

//We will now execute the request to add a Watchpoint
httpService.url = cfURL + "&tid=" + this.transactionId;
httpService.method = HTTPRequestMessage.POST_METHOD;

//We are sending XML, so we need to set the content type to text/xml
httpService.contentType = "text/xml";

output.text += "\nConfig API operation: " + httpService.method + " ";
output.text += httpService.url;
output.text += "\nRequest Body:\n\n";
output.text += customFieldToAdd.toString() + "\n";

var token : AsyncToken = httpService.send(customFieldToAdd);

//The next operation will be to create a Watchpoint
token.nextOperation = createWatchpoint;
}

/**
* This operation will make a request to create a Watchpoint
* based on the custom field we just created.
*
* @param response - The XML output response from the previous request
* which was creating a custom field. This is passed in
* case there was anything required from the previous
* request to build this new request.
*
**/

private function createWatchpoint(response : XML) : void
{

//We will now execute the request to add a Watchpoint
httpService.url = wpURL + "&tid=" + this.transactionId;
httpService.method = HTTPRequestMessage.POST_METHOD;

//We are sending XML so we need to set the content type to text/xml
httpService.contentType = "text/xml";
output.text += "\nConfig API operation: " + httpService.method + " ";
output.text += httpService.url;
output.text += "\nRequest Body:\n\n";
output.text += watchpointToAdd.toString() + "\n";
var token : AsyncToken = httpService.send(watchpointToAdd);

//The next operation will be to commit the transaction
token.nextOperation = commitTransaction;
}
/**
* This operation will make a request to commit the transaction
*
* @param response - The XML output response from the previous request
* which was creating a Watchpoint. This is passed in
* case there was anything required from the previous
* request to build this new request.
*
**/

private function commitTransaction(response : XML) : void
{
//We will now execute the request to commit the transaction

//Set the transaction ID.
httpService.url = txURL + "&id=" + this.transactionId;

//VERY IMPORTANT : FLEX does not support PUT Method without using Live
//Cycle Data Services. Therefore we must use the override parameter for
//the REST request and set the method parameter to PUT (method=PUT)
httpService.url += "&method=" + HTTPRequestMessage.PUT_METHOD;

//Since FLEX does not support PUT we will set the method as POST and
//and use the override parameter (method=PUT).
httpService.method = HTTPRequestMessage.POST_METHOD;

//For PUT it is VERY important to set the content type to text/xml
//otherwise the response will be an empty string.
httpService.contentType = "text/xml";
output.text += "\nConfig API operation: " + httpService.method + " ";
output.text += httpService.url;
var token : AsyncToken = httpService.send();

//The next operation will be to delete the transaction
token.nextOperation = deleteTransaction;
}

/**
* This operation will make a request to delete the transaction
*
* @param response - The XML output response from the previous request
* which was committing the transaction.
* This is passed in case there was anything required
* from the previous request to build this new request.
*
**/

private function deleteTransaction(response : XML) : void
{

//We will now execute the request to delete the transaction
httpService.url = txURL + "&id=" + this.transactionId;

//VERY IMPORTANT : FLEX does not support DELETE Method without using
//Live Cycle Data Services. Therefore we must use the override
//parameter for the REST request and set the method parameter to DELETE
//(method=DELETE)
httpService.url += "&method=" + HTTPRequestMessage.DELETE_METHOD;

//Since FLEX does not support DELETE we will set the method as POST and
//and use the override parameter method=DELETE.
httpService.method = HTTPRequestMessage.POST_METHOD;

//Since we are not posting a form, we will set the content-type to
//text/plain.
httpService.contentType = "text/plain";
output.text += "\nConfig API operation: " + httpService.method + " ";
output.text += httpService.url;
var token : AsyncToken = httpService.send();

//No operations to execute next so we will set the next operation to
//null
token.nextOperation = null;
}

/**
* Event handler function to handle all requests.
* This function is called when the httpService dispatches the
* ResultEvent.
*
* Since the response of all requests are similar, this function will
* perform the common tasks of determining the status of the request
* "success" or "failure" and output the response XML.
* If the request returned a status of "success",
* this function will then execute a 'nextOperation' function that was
* injected into the AsyncToken object accessible through the
* ResultEvent. The 'nextOperation' execute code necessary in perform
* the next operation (Get Wps, Add CF, Add Wp, Commit Tx, Delete Tx).
*
* @param event
*
**/

private function handleResult(event : ResultEvent) : void
{
var xmlResult : XML = event.target.lastResult;
var isSuccess : Boolean = false;
output.text += "\nResponse Body : \n\n";
output.text += xmlResult.toString();
output.text += "\n---------------------------------------------";
try
{
//Determine the status of the request "success" or "failure"
isSuccess = determineStatus(xmlResult);
}
catch (e : Error)
{
//If we could not parse the status, log the message and return.
output.text += "\nError : " + e.message;
output.text += "\n---------------------------------------------";
return;
}
if (isSuccess)
{
//We are using function injection to execute the next operation
if (event.token.nextOperation != null)
{
//After calling httpService.send(), we added a nextOperation
//property containing the next request to execute
//(Get Wps, Add CF, Add Wp, Commit Tx, TerminateTx).
event.token.nextOperation(xmlResult);
}
}
}
/**
* Handles any HTTP errors associated with any of the requests we make.
* This method is called automatically by the HTTPService if it
* dispatches a FaultEvent
*
* @param event
**/

private function handleFailure(event : FaultEvent) : void
{
output.text += "\nFault " + event.fault.message;
output.text += "\n---------------------------------------------";
}

/**
* This function will determine the status of a request.
* It will return true if the response was "success" or false if
* it was "failure"
*
* @param response - The response XML from the HTTP response.
*
* @return - true if the request was a success false if it was a failure
*
* @throws Error - Thrown if the response could not be understood or
* if the status was anything other than "success" or
* "failure"
*
**/

private function determineStatus(response : XML) : Boolean {
if (response == null)
{
throw new ("Could not understand response");
}
if (response.status != null && response.status.@result != null)
{
if (response.status.@result == "success")
{
return true;
}
else if (response.status.@result == "failure" )
{
return false;
}
else
{
throw new Error("Could not understand status ");
}
}
else
{
throw new Error("Could not understand response");
}
}
]]>
</mx:Script>
</mx:WindowedApplication>

back to top

 

Tip: For faster searching, add an asterisk to the end of your partial query. Example: cert*