Page tree

Sample Java Scripts

The following scripts provide examples of using custom Java scripting capabilities in a typical Agiloft installation.

package com.enterprisewizard.examples;
/*
 * (c) Copyright 2007, <ac:structured-macro ac:name="companyname" ac:schema-version="1" />, Inc. All Rights Reserved.
 * No part of this document may be stored in a retrievable system,
 * transmitted or reproduced in any way without the prior written
 * permission of EnterpriseWizard.
 */
import com.supportwizard.actions2.interfaces.ExternalScript;
import com.supportwizard.actions2.interfaces.ScriptActionException;
import com.supportwizard.actions2.interfaces.ScriptInput;
import com.supportwizard.actions2.interfaces.ScriptOutput;
import com.supportwizard.dictionary.SWChoiceLine;
import com.supportwizard.dictionary.appendtext.AppendOnlyTextContainer;
import com.supportwizard.dml.SWDataMap;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;
import java.io.IOException;
import java.io.InputStream;
/**
 * The purpose of the "ReplicateTicket" is to automatically replicate
 * Tickets from one server to another via REST call.
 * 
 * This script is run in a script action from a rule invoked on create.
 * 
 */
public class ReplicateTicket implements ExternalScript {
    private final static HttpClient httpClient;
    static {
        MultiThreadedHttpConnectionManager connectionManager =
                new MultiThreadedHttpConnectionManager();
        httpClient = new HttpClient(connectionManager);
    }
    public ScriptOutput runScript(ScriptInput input)
            throws ScriptActionException {
        //newRecord represents the Ticket that just have been created.
        final SWDataMap newRecord = input.getNewRecord();
        //PostMethod is used to invoke REST EWCreate operation
        //on the target server
        PostMethod method =
                new PostMethod("http://server2.supportwizard.com:8080" +
                        "/ewws/EWCreate?$KB=Support&$login=script&" +
                        "$password=example&$lang=en&$table=case");
        String additionalNotes = "";
        //Script uses newRecord to retrieve new Ticket's data
        //to construct POST request.
        final Object o = newRecord.get("engineering_comments");
        if (o != null && o instanceof AppendOnlyTextContainer) {
            additionalNotes = o.toString();
        }
        addParam("Additional_Notes", additionalNotes, method);
        addParam("Build_Number",
                (String) newRecord.get("build_number"), method);
        final Object closingType = newRecord.get("closing_type");
        if (closingType instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) closingType).getText();
            addParam("Closing_Type", text, method);
        }
        addParam("submitter_login",
                (String) newRecord.get("submitter_login"), method);
        addParam("Company_0",
                (String) newRecord.get("submitter_company"), method);
        addParam("customer_phone", (String) newRecord.get("phone"), method);
        addParam("customer_email", (String) newRecord.get("email"), method);
        addParam("end_user_name", (String) newRecord.get("f_name"), method);
        addParam("Fixed_In_Build_No",
                (String) newRecord.get("fixed_in_build_no"), method);
        addParam("For_Product", "EnterpriseWizard", method);
        addParam("Old_Ew_Id", getString(newRecord, "id"), method);
        addParam("Primary_Team",
                (String) newRecord.get("creator_team"), method);
        final Object priority = newRecord.get("priority");
        if (priority instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) priority).getText();
            addParam("Priority", text, method);
        } else {
            addParam("Priority", "Medium", method);
        }
        addParam("Problem_Description",
                (String) newRecord.get("steps_to_duplicate"), method);
        final Object published = newRecord.get("published");
        if (published instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) published).getText();
            addParam("Published", text, method);
        }
        addParam("Solution", (String) newRecord.get("resolution"), method);
        final Object server = newRecord.get("server");
        String serverTxt = null;
        if (server instanceof SWChoiceLine) {
            serverTxt = ((SWChoiceLine) server).getText();
        }
        String loginTxt = "server: " + serverTxt + "\n";
        loginTxt += "knowledgebase: " + newRecord.get("knowledgebase_name")
                + "\n";
        loginTxt += "login: " + newRecord.get("admin_group_login") + "\n";
        loginTxt += "password: " + newRecord.get("admin_password");
        addParam("Staff_Notes", loginTxt, method);
        final Object standardSolution = newRecord.get("standardSolution");
        if (standardSolution instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) standardSolution).getText();
            addParam("Standard_Solution", text, method);
        }
        addParam("Summary", (String) newRecord.get("summary"), method);
        addParam("Type", "case", method);
        final Object category = newRecord.get("category");
        if (category instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) category).getText();
            addParam("Type_Of_Issue", text, method);
        }
        final Object wfstate = newRecord.get("wfstate");
        if (wfstate instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) wfstate).getText();
            addParam("Wfstate", text, method);
        } else {
            addParam("Wfstate", "Open", method);
        }
        //Once all parameters of the request have been filled,
        //script uses standard httpClient.executeMethod(method)
        //to send the request.
        try {
            method.setHttp11(true);
            int i = httpClient.executeMethod(method);
            if (i != HttpStatus.SC_OK) {
                throw new RuntimeException("Error is reported via " +
                        "REST interface. Return code: " + i);
            }
            final InputStream asStream = method.getResponseBodyAsStream();
            byte b[] = new byte[1024];
            try {
                while (asStream.read(b) != -1) {
                }
            } finally {
                asStream.close();
            }
        } catch (IOException e) {
            // This script doesn't make any effort to recover from Exceptions.
            // Exceptions are re-thrown, thus original and
            // child records won't be created.
            throw new RuntimeException("IOException is reported " +
                    "in operation via REST interface.");
        } finally {
            method.releaseConnection();
        }
        //If POST was successfull (HttpStatus.SC_OK),
        //script finishes its work by creating a ScriptOutput
        //object with normal exit code.
        final ScriptOutput output = input.createOutput();
        output.setExitCode(ExternalScript.ACCEPT);
        return output;
    }
    private void addParam(String s, String optionOpen, PostMethod req) {
        if (optionOpen != null) {
            req.addParameter(s.toLowerCase(), optionOpen);
        }
    }
    private String getString(SWDataMap newRecord, final String name) {
        final Object value = newRecord.get(name);
        return value == null ? null : value.toString();
    }
} 

The purpose of the ReplicateTicket is to automatically replicate Tickets from one server to another via a REST call.

package com.enterprisewizard.examples;
/*
 * (c) Copyright 2007, EnterpriseWizard, Inc. All Rights Reserved.
 * No part of this document may be stored in a retrievable system,
 * transmitted or reproduced in any way without the prior written
 * permission of EnterpriseWizard.
 */

import com.supportwizard.actions2.interfaces.ExternalScript;
import com.supportwizard.actions2.interfaces.ScriptActionException;
import com.supportwizard.actions2.interfaces.ScriptInput;
import com.supportwizard.actions2.interfaces.ScriptOutput;
import com.supportwizard.datetime.convertor.EwDateTimeConvertor;
import com.supportwizard.dictionary.SWChoiceLine;
import com.supportwizard.dictionary.appendtext.AppendOnlyTextContainer;
import com.supportwizard.dml.SWDataMap;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Locale;

/**
 * The purpose of the "CreateInEWSupportScript" is to automatically
 * replicate Tickets from one server to another.
 * 
 * This script is run in a script action from the rule invoked on create.
 * 
 */
public class CreateInEWSupportScript implements ExternalScript {
    private final static HttpClient httpClient;

    static {
        MultiThreadedHttpConnectionManager connectionManager =
                new MultiThreadedHttpConnectionManager();
        httpClient = new HttpClient(connectionManager);
    }



    public ScriptOutput runScript(ScriptInput input)
            throws ScriptActionException {
        final String EMPTY_STRING = "";
        //newRecord represents the Ticket that just have been created.
        final SWDataMap newRecord = input.getNewRecord();

        //PostMethod is used to invoke REST EWCreate operation
        // on the target server
        PostMethod method = new PostMethod(
                "http://server2.supportwizard.com:" +
                        "8080/ewws/EWCreate?$KB=Support&" +
                        "$login=script&$password=example&" +
                        "$lang=en&$table=case");

        String additionalNotes = EMPTY_STRING;

        //Script uses newRecord to retrieve new Ticket's data
        // in order to construct POST request.
        final Object o = newRecord.get("engineering_comments");
        if (o != null && o instanceof AppendOnlyTextContainer) {
            additionalNotes = o.toString();
        }

        addParam("Additional_Notes", additionalNotes, method);
        addParam("Build_Number", (String) newRecord.get("build_number"),
                method);

        final Object closingType = newRecord.get("closing_type");
        if (closingType instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) closingType).getText();
            addParam("Closing_Type", text, method);
        }

        addParam("submitter_login",
                (String) newRecord.get("submitter_login"), method);
        addParam("Company_0", (String) newRecord.get("submitter_company"),
                method);
        addParam("customer_phone", (String) newRecord.get("phone"),
                method);
        addParam("customer_email", (String) newRecord.get("email"),
                method);
        addParam("end_user_name", (String) newRecord.get("f_name"),
                method);
        addParam("Fixed_In_Build_No",
                (String) newRecord.get("fixed_in_build_no"),
                method);
        addParam("For_Product", "EnterpriseWizard", method);
        addParam("Old_Ew_Id", getString(newRecord, "id"), method);
        addParam("Primary_Team", (String) newRecord.get("creator_team"),
                method);

        final Object priority = newRecord.get("priority");
        if (priority instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) priority).getText();
            addParam("Priority", text, method);
        } else {
            addParam("Priority", "Medium", method);
        }
        addParam("Problem_Description",
                (String) newRecord.get("steps_to_duplicate"),
                method);

        final Object published = newRecord.get("published");

        if (published instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) published).getText();
            addParam("Published", text, method);
        }

        addParam("Solution", (String) newRecord.get("resolution"), method);
        final Object server = newRecord.get("server");
        String serverTxt = null;
        if (server instanceof SWChoiceLine) {
            serverTxt = ((SWChoiceLine) server).getText();
        }
        String loginTxt = "server: " + serverTxt + "\n";
        loginTxt += "knowledgebase: " +
                newRecord.get("knowledgebase_name") + "\n";
        loginTxt += "login: " + newRecord.get("admin_group_login") + "\n";
        loginTxt += "password: " + newRecord.get("admin_password");
        addParam("Staff_Notes", loginTxt, method);

        final Object standardSolution = newRecord.get("standardSolution");
        if (standardSolution instanceof SWChoiceLine) {
            final String text =
                    ((SWChoiceLine) standardSolution).getText();
            addParam("Standard_Solution", text, method);
        }

        addParam("Summary", (String) newRecord.get("summary"), method);
        addParam("Type", "case", method);

        final Object category = newRecord.get("category");
        if (category instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) category).getText();
            addParam("Type_Of_Issue", text, method);
        }



        final Object wfstate = newRecord.get("wfstate");
        if (wfstate instanceof SWChoiceLine) {
            final String text = ((SWChoiceLine) wfstate).getText();
            addParam("Wfstate", text, method);
        } else {
            addParam("Wfstate", "Open", method);
        }

        //Once all parameters of the request have been filled,
        // script uses standard httpClient.executeMethod(method)
        // to send the request.
        try {
            method.setHttp11(true);
            int i = httpClient.executeMethod(method);
            if (i != HttpStatus.SC_OK) {
                throw new RuntimeException(
                        "Error is reported via REST interface. " +
                                "Return code: " + i);
            }
            final InputStream asStream = method.getResponseBodyAsStream();
            byte b[] = new byte[1024];
            try {
                while (asStream.read(b) != -1) {
                }
            } finally {
                asStream.close();
            }
        } catch (IOException e) {
            // This script doesn't make any effort to recover from Exceptions.
            // Exceptions are re-thrown, thus original and
            // child records won't be created.
            throw new RuntimeException(
                    "IOException is reported in " +
                            "operation via REST interface.");
        } finally {
            method.releaseConnection();
        }
        //If POST was successfull (HttpStatus.SC_OK),
        // script finishes its work by
        // creating a ScriptOutput object with normal exit code.
        final ScriptOutput output = input.createOutput();
        output.setExitCode(ExternalScript.ACCEPT);
        return output;
    }

    private void addParam(String s, String optionOpen, PostMethod req) {
        if (optionOpen != null) {
            req.addParameter(s.toLowerCase(), optionOpen);
        }
    }

    private String getString(SWDataMap newRecord, final String name) {
        final Object value = newRecord.get(name);
        return value == null ? null : value.toString();
    }



} 

The purpose of the CreateInEWSupportScript is to automatically replicate Tickets from one server to another.

package com.enterprisewizard.examples;
/*
 * (c) Copyright 2008, EnterpriseWizard, Inc. All Rights Reserved.
 * No part of this document may be stored in a retrievable system,
 * transmitted or reproduced in any way without the prior written
 * permission of EnterpriseWizard.
 */
import com.enterprisewizard.ws.client.demo.*;
import java.net.URL;
/**
 * The purpose of the "QueryAsset" is to demonstrate the current way of
 * working with EnterpriseWizard SOAP Web Services.
 * 
 * In particular the interface is generic - exposing and accepting parent
 * object to allow one to use the same web service with different tables.
 * Methods are low level - one has to combine several calls to achieve
 * required. This is also a stateful version of the interface that relies
 * on the underlying protocol support for stateful communication via
 * cookies.
 * 
 * This script is run from the commandline, accepts host, port, kbName,
 * user, password and searchValue parameters.
 * 
 * The script performs search by SQL on Asset_Table object of the
 * knowledgebase, parses the returned object tree and prints results to the
 * standard output.
 */
public class QueryAsset {
    public static long[] queryAssets(
            final CondeSoapBindingStub ewServiceAPI,
            final String ipAddress) throws Exception {
        // Runs SQL query and returns identifiers of records found
        // Never returns null
        final long[] ids = ewServiceAPI.EWSelectFromTable("asset_table",
                "ip_address_snmp = '" + ipAddress + "'");
        if (ids.length != 1)
            throw new RuntimeException("unexpected result");
        // Read the data by identifier
        final WSAsset_Table asset =
                (WSAsset_Table) ewServiceAPI.EWRead("asset_table", ids[0]);
        // Building, Floor and Location are parts of the Linked Fields set
        final WSAsset_TableLocation_Dao3_Link11 location =
                asset.getDAO_Dao3_Link11();
        System.out.println("Building = " + location.getNew_Building());
        System.out.println("Floor = " + location.getFloor0());
        System.out.println("Location = " + location.getNew_City());
        // Asset (Device) type is a part of another Linked Fields set
        final WSAsset_TableAsset_Definition_Dao3_Link5 assetDefinition =
                asset.getDAO_Dao3_Link5();
        System.out.println(
                "Device Type = " + assetDefinition.getAsset_Type());
        // Busines Unit is a part of another Linked Field set
        final WSAsset_TableProject_Dao3_Link10 build =
                asset.getDAO_Dao3_Link10();
        System.out.println("BU = " + build.getBuild_Business_Unit_());
        // Primary contact is a part of a Linked Field set as well
        final WSAsset_TableContacts_Dao3_Link9 escalationContact =
                asset.getDAO_Dao3_Link9();
        System.out.println("PrimaryContact = " +
                escalationContact.getEscalation_Contact());
        // The following fields are available in the Asset_Table directly
        System.out.println(
                "Manufacturer = " + assetDefinition.getManufacturer());
        System.out.println("Service = " + asset.getService());
        System.out.println("Function = " + asset.getF_Function());
        System.out.println("Maintenance = " + asset.getWfstate());
        return ids;
    }
    private static CondeSoapBindingStub getSOAPBinding(String host,
                                                       String kb,
                                                       final String port)
            throws Exception {
        // in order to gain access to non-standard maintain 
        // session parameters one has to upcast the returned
        // object to the WS-stack specific SOAP Stub type.
        final CondeSoapBindingStub ewServiceAPI =
                (CondeSoapBindingStub) new EWServiceAPIServiceLocator()
                        .getconde(new URL("http://" + host + ":" + port +
                                "/" + kb + "/EWServiceAPI"));
        ewServiceAPI.setMaintainSession(
                true); // enables HTTP session maintainance via cookies
        return ewServiceAPI;
    }
    public static void main(String[] args) throws Exception {
        final String host = args[0];
        final String port = args[1];
        final String kbName = args[2];
        final String user = args[3];
        final String password = args[4];
        final String searchValue = args[5];
        final String lang = "en";
        final CondeSoapBindingStub stub =
                getSOAPBinding(host, kbName, port);
        stub.EWLogin(kbName, user, password, lang); // We need to log in
        try {
            queryAssets(stub, searchValue);
        } finally {
            stub.EWLogout(); // And logout
        }
    }
}

The purpose of the QueryAsset is to demonstrate the current way of working with Agiloft SOAP Web Services. In particular the interface is generic - exposing and accepting parent object to allow one to use the same web service with different tables. Methods are low level - one has to combine several calls to achieve required. This is also a stateful version of the interface that relies on the underlying protocol support for stateful communication via cookies. This script is run from the commandline, accepts host, port, kbName, user, password and searchValue parameters. The script performs search by SQL on Asset_Table object of the knowledgebase, parses the returned object tree and prints results to the standard output.

package com.enterprisewizard.examples;
/*
 * (c) Copyright 2008, EnterpriseWizard, Inc. All Rights Reserved.
 * No part of this document may be stored in a retrievable system,
 * transmitted or reproduced in any way without the prior written
 * permission of EnterpriseWizard.
 */
import com.enterprisewizard.ws.client.demo.*;
import com.enterprisewizard.ws.client.ewsupport.WSAsset_Table;
import com.enterprisewizard.ws.api.EWServiceAPI;
import java.net.URL;
/**
 * The purpose of the "QueryAssetNew" is to demonstrate the upcoming changes
 * in EntepriseWizard Web Services interfaces, in particular "Single Method
 * Operations", "Immediate Read", "Web Service Per Table" concepts.
 * 
 * This script is run from the commandline, accepts host, port, kbName,
 * user, password and searchValue parameters.
 * 
 * The script performs search by SQL on Asset_Table object of the
 * knowledgebase, parses the returned object tree and prints results to the
 * standard output.
 */
public class QueryAssetNew {
    public static void queryAssets(final EWServiceAPI ewServiceAPI,
                                   final String ipAddress,
                                   final String kbName, final String user,
                                   final String password,
                                   final String lang) throws Exception {
        // A Single Method variant of EWSelect
        // Immedeate Read variant of EWSelect
        // Never returns null
        final WSAsset_Table asset = ewServiceAPI.EWSelectAndRead(kbName,
                user, password, lang, "asset_table",
                "ip_address_snmp = '" + ipAddress + "' limit 1");
        // Instead one has to check for the id being not null.
        // Most likely will change in the final version of the  EW WS SOAP API.
        if (asset.getId() != null) {
            // Building, Floor and Location are parts of the Linked Fields set
            final WSAsset_TableLocation_Dao3_Link11 location =
                    asset.getDAO_Dao3_Link11();
            System.out.println("Building = " + location.getNew_Building());
            System.out.println("Floor = " + location.getFloor0());
            System.out.println("Location = " + location.getNew_City());
            // Asset (Device) type is a part of another Linked Fields set
            final WSAsset_TableAsset_Definition_Dao3_Link5 assetDefinition =
                    asset.getDAO_Dao3_Link5();
            System.out.println(
                    "Device Type = " + assetDefinition.getAsset_Type());
            // Busines Unit is a part of another Linked Field set
            final WSAsset_TableProject_Dao3_Link10 build =
                    asset.getDAO_Dao3_Link10();
            System.out.println("BU = " + build.getBuild_Business_Unit_());
            // Primary contact is a part of a Linked Field set as well
            final WSAsset_TableContacts_Dao3_Link9 escalationContact =
                    asset.getDAO_Dao3_Link9();
            System.out.println("PrimaryContact = " +
                    escalationContact.getEscalation_Contact());
            // The following fields are available in the Asset_Table directly
            System.out.println(
                    "Manufacturer = " + assetDefinition.getManufacturer());
            System.out.println("Service = " + asset.getService());
            System.out.println("Function = " + asset.getF_Function());
            System.out.println("Maintenance = " + asset.getWfstate());
        }
    }
    private static EWServiceAPI getSOAPBinding(String host, String kb,
                                               final String port)
            throws Exception {
        // The web service used is specific for Asset_Table
        return new EWServiceAPIServiceLocator()
                .getconde(new URL(
                        "http://" + host + ":" + port + "/" + kb +
                                "/EWServiceAPI.Asset_Table"));
    }
    public static void main(String[] args) throws Exception {
        final String host = args[0];
        final String port = args[1];
        final String kbName = args[2];
        final String user = args[3];
        final String password = args[4];
        final String searchValue = args[5];
        final String lang = "en";
        final EWServiceAPI stub = getSOAPBinding(host, kbName, port);
        queryAssets(stub, searchValue, kbName, user, password, lang);
    }
} 

The purpose of the QueryAssetNew is to demonstrate the upcoming changes in EntepriseWizard Web Services interfaces, in particular "Single Method Operations", "Immediate Read", "Web Service Per Table" concepts.

package com.enterprisewizard.examples;
/*
 * (c) Copyright 2008, EnterpriseWizard, Inc. All Rights Reserved.
 * No part of this document may be stored in a retrievable system,
 * transmitted or reproduced in any way without the prior written
 * permission of EnterpriseWizard.
 */
import com.enterprisewizard.ws.client.demo.*;
import java.net.URL;
/**
 * The purpose of the "CreateCaseCurrent" is to demonstrate the current way
 * of working with <span class="product1">EnterpriseWizard</span> SOAP Web Services.
 * 
 * In particular the interface is generic - exposing and accepting parent
 * object to allow one to use the same web service with different tables.
 * This is also a stateful version of the interface that relies on the
 * underlying protocol support for stateful communication via cookies.
 * 
 * This script is run from the commandline, accepts host, port, kbName,
 * user, password and several specific field parameters.
 * 
 * The script invokes EWCreate from SOAP API to create a Case in EW.
 */
public class CreateCaseCurrent {
    public static long createTicket(final String assetDeviceName,
                                    final int severity,
                                    final String summary,
                                    final Integer serverSerial,
                                    final String agent,
                                    final String ownerUID,
                                    final CondeSoapBindingStub ewServiceAPI)
            throws Exception {
        WSCase wscase = new WSCase(); // creates an instance of Case object
        // Device name is a part of a Linked Fields set, requires an
        // instance of a link-class to be constructed
        WSCaseAsset_Table_Dao3_Link11 asset =
                new WSCaseAsset_Table_Dao3_Link11();
        asset.setAsset_Device_Name(assetDeviceName);
        wscase.setDAO_Dao3_Link11(asset);
        wscase.setPriority(
                convert(severity)); // Severity numeric values have to be
        // converted into WS enums
        wscase.setProblem_Description(summary);
        // Customer login and Customer email are part
        // of the Linked Field set
        final WSCaseContacts_Dao3_Link5 reportedBy =
                new WSCaseContacts_Dao3_Link5();
        reportedBy.setCustomer_Login(ownerUID);
        reportedBy.setCustomer_Email(null);
        wscase.setDAO_Dao3_Link5(reportedBy);
        wscase.setNetcool_Event_Id(serverSerial);
        wscase.setSummary(agent);
        wscase.setTicket_Category(
                WSChoice_Ticketparentchild.OPTION_UNIQUE);
        // Choice values 
        // are set as WS enums
        wscase.setType_Of_Issue(
                WSChoice_Ticket_New_Type.OPTION_NETCOOL_ALARM);
        wscase.setRelated_To(WSChoice_Ticket_Related_To.OPTION_ASSET);
        // Setting up Query-by-Example, this will search for IOC Team among
        // the teams and if found - forge a link and
        // import values for fields imported into the Case table as part of
        // this Linked Fields realtionship
        WSCaseTeams_Dao3_Link3 assignedTeam = new WSCaseTeams_Dao3_Link3();
        assignedTeam.setAssigned_Team_("IOC Team");
        wscase.setDAO_Dao3_Link3(assignedTeam);
        // Sets subtype of the record to be created via generic interface.
        // Matches the table name for top-level types, but will be
        // different for true subtypes.
        wscase.setType("case");
        return ewServiceAPI.EWCreate("case", wscase);
    }
    private static CondeSoapBindingStub getSOAPBinding(String host,
                                                       String kb,
                                                       final String port)
            throws Exception {
        // in order to gain access to non-standard maintain session
        // parameters one has to upcast the returned
        // object to the WS-stack specific SOAP Stub type.
        final CondeSoapBindingStub ewServiceAPI =
                (CondeSoapBindingStub) new EWServiceAPIServiceLocator()
                        .getconde(new URL("http://" + host + ":" + port +
                                "/" + kb + "/EWServiceAPI"));
        ewServiceAPI.setMaintainSession(
                true); // enables HTTP session maintainance via cookies
        return ewServiceAPI;
    }
    private static WSChoice_Priority convert(int severity) {
        if (severity <= 2) return WSChoice_Priority.OPTION_LOW;
        if (severity == 3) return WSChoice_Priority.OPTION_MEDIUM;
        if (severity == 4) return WSChoice_Priority.OPTION_HIGH;
        if (severity == 5) return WSChoice_Priority.OPTION_CRITICAL;
        return WSChoice_Priority.OPTION_CRITICAL;
    }
    public static void main(String[] args) throws Exception {
        final String host = args[0];
        final String port = args[1];
        final String kbName = args[2];
        final String user = args[3];
        final String password = args[4];
        final int serverity = Integer.parseInt(args[5]);
        final String summary = args[6];
        final int serverSerial = Integer.parseInt(args[7]);
        final String agent = args[8];
        final String ownerUID = args[9];
        final String assetDeviceName = args[10];
        final String lang = "en";
        final CondeSoapBindingStub stub =
                getSOAPBinding(host, kbName, port);
        stub.EWLogin(kbName, user, password, lang);
        try {
            createTicket(assetDeviceName, serverity, summary, serverSerial,
                    agent, ownerUID, stub);
        } finally {
            stub.EWLogout();
        }
    }
} 

The purpose of the CreateCaseCurrent is to demonstrate the current way of working with Agiloft SOAP Web Services. In particular the interface is generic - exposing and accepting parent object to allow one to use the same web service with different tables. This is also a stateful version of the interface that relies on the underlying protocol support for stateful communication via cookies. This script is run from the commandline, accepts host, port, kbName, user, password and several specific field parameters. The script invokes EWCreate from SOAP API to create a Case in Agiloft.

package com.enterprisewizard.examples;
/*
 * (c) Copyright 2008, EnterpriseWizard, Inc. All Rights Reserved.
 * No part of this document may be stored in a retrievable system,
 * transmitted or reproduced in any way without the prior written
 * permission of EnterpriseWizard.
 */
import com.enterprisewizard.ws.client.demoonecall.EWServiceAPI;
import com.enterprisewizard.ws.client.demoonecall.EWServiceAPIServiceLocator;
import com.enterprisewizard.ws.client.demoonecall.WSCase;
import java.net.URL;
/**
 * The purpose of the "CloneTicketNew" is to demonstrate the way to pass
 * results of one WS method to another and challenges associated with
 * this.
 * The script uses "Single Method Operations", "Immediate Read" calls that
 * will be available in upcoming release of <span class="product1">EnterpriseWizard</span> Web Services.
 * This script is run from the commandline, accepts host, port, kbName,
 * user, password and searchValue parameters.
 * The script performs search by SQL on Case object of the knowledgebase
 * and submits the returned object right back in to create a clone.
 */
public class CloneTicketNew {
    private static EWServiceAPI getSOAPBinding(String host, String kb,
                                               final String port)
            throws Exception {
        // This script uses generic version of the service, but since
        // we do Single Method Operations and Immediate Read
        // no upcasting and manipulations with parameters of the low
        // level protocol is required.
        return new EWServiceAPIServiceLocator()
                .getDemo(new URL("http://" + host + ":" + port + "/" + kb +
                        "/EWServiceAPI"));
    }
    public static void main(String[] args) throws Exception {
        final String host = args[0];
        final String port = args[1];
        final String kbName = args[2];
        final String user = args[3];
        final String password = args[4];
        final String searchValue = args[5];
        final String lang = "en";
        final EWServiceAPI stub = getSOAPBinding(host, kbName, port);
        // Finds a Case with the summary matching searchValue
        final WSCase original = (WSCase) stub.EWSelectAndRead(kbName, user,
                password, lang, "case", "summary='" + searchValue + "'");
        if (original.getId() != null) {
            System.out.println("e = " + original.getId());
            System.out.println("e = " + original.getSummary());
            original.setSummary("Absolutely new ticket clone");
            // These values are configured to either be filled with
            // defaults or have not write access for anyone, to
            // avoid exceptions they are set to null,
            // i.e. will not be transmitted.
            original.setDate_Closed(null);
            original.setFaq_Feedback(null);
            original.setDate_Assigned(null);
            original.setTime_Created(null);
            original.setDate_Created(null);
            original.setId(null);
            original.setDAO_Dao3_Link2(null);
            original.setSumof_Billable_Hours_11957_(null);
            original.setSumof_Non_Billable_Hours_11958_(null);
            original.setDate_Updated(null);
            // creates a clone case
            final WSCase clone = (WSCase) stub.EWCreateAndRead(kbName,
                    user, password, lang, "case", original);
            System.out.println("e = " + clone.getId());
            System.out.println("e = " + clone.getSummary());
        }
    }
} 

The purpose of the CloneTicketNew is to demonstrate the way to pass results of one WS method to another and challenges associated with this. The script uses Single Method Operations, Immediate Read calls that will be available in upcoming release of Agiloft Web Services. This script is run from the commandline, accepts host, port, kbName, user, password and searchValue parameters. The script performs search by SQL on Case object of the knowledgebase and submits the returned object right back in to create a clone.

package com.enterprisewizard.examples;
/*
 * (c) Copyright 2007, EnterpriseWizard, Inc. All Rights Reserved.
 * No part of this document may be stored in a retrievable system,
 * transmitted or reproduced in any way without the prior written
 * permission of EnterpriseWizard.
 */
import com.enterprisewizard.ws.api.EWWSBaseUserObjectMap;
import com.enterprisewizard.ws.impl.EWSimpleImplHelperWrapper;
import com.enterprisewizard.ws.utils.LogHelper;
import com.supportwizard.actions2.interfaces.ExternalScript;
import com.supportwizard.actions2.interfaces.ScriptActionException;
import com.supportwizard.actions2.interfaces.ScriptInput;
import com.supportwizard.actions2.interfaces.ScriptOutput;
import com.supportwizard.dml.SWDataMap;
import com.supportwizard.dml.SWRecordPK;
import com.supportwizard.seance.Seance;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.InputStream;
/**
 * The purpose of the "POSTPush" is to submit the result of modification of
 * a record in  <span class="product1">EW</span> to an external host via HTTP POST.
 * This script is run in a script action from the rule invoked on update.
 * The script re-uses parts of WS/REST internal code to convert internal
 * datatypes into POST parameters.
 */
public class POSTPush implements ExternalScript {
    private final static HttpClient httpClient;
    public static final Logger log = Logger.getLogger(POSTPush.class);
    private static final String FAILURE_MESSAGE =
            "REST Push: Failed ot push the change to the remote server";
    static {
        MultiThreadedHttpConnectionManager connectionManager =
                new MultiThreadedHttpConnectionManager();
        httpClient = new HttpClient(connectionManager);
    }
    public ScriptOutput runScript(ScriptInput input)
            throws ScriptActionException {
        // Script gets two copies of the current record - one before change
        // (or null in case of creation) and one
        // after change
        final SWDataMap newRecord = input.getNewRecord();
        // Obtain identification values for the purpose of logging
        final Seance seance = input.getUserSeance();
        final SWRecordPK swRecordPK = newRecord.getSWRecordPK(seance);
        final Long id = swRecordPK.getID();
        final Object type = newRecord.get("type");
        // helper method to aid logging
        final LogHelper logHelper = LogHelper.create("REST Push",
                new String[]{"type", "id"}, new Object[]{type, id});
        final ScriptOutput output = input.createOutput();
        try {
            logHelper.logAttempt(log);
            final EWSimpleImplHelperWrapper implHelperWrapper =
                    new EWSimpleImplHelperWrapper();
            // converts internal datastructures to WS/REST object map.
            final EWWSBaseUserObjectMap objectMap = implHelperWrapper
                    .convertSWDataMap(seance, newRecord, logHelper, log);
            log.info(POSTPush.class.getSimpleName() +
                    " invoked for type " + type + " id " + id);
            int i = -1;
            PostMethod method = new PostMethod(
                    "http://externalhost/urithatacceptsthedata");
            method.setHttp11(true);
            try {
                objectMap.forEachEntry(new PostProcedure(
                        method)); // convert the object map into POST params
                i = httpClient.executeMethod(method); // perform POST
                try {
                    final InputStream asStream =
                            method.getResponseBodyAsStream(); // read result
                    byte b[] = new byte[1024];
                    try {
                        while (asStream.read(b) != -1) {
                        }
                    } finally {
                        asStream.close();
                    }
                } catch (IOException e) {
                    // do nothing, ignore
                }
            } finally {
                method.releaseConnection();
            }
            // report success or failure to EnterpriseWizard
            if (i != HttpStatus.SC_OK) {
                logHelper.logExpectedFailure(log,
                        new Exception(FAILURE_MESSAGE));
                return blockedScriptOutput(output, FAILURE_MESSAGE,
                        newRecord, seance);
            } else {
                output.setExitCode(ExternalScript.ACCEPT);
                logHelper.logSuccess(log);
            }
            return output;
        } catch (Throwable e) {
            // Anything that goes wrong is considered unrecoverable
            logHelper.logUnexpectedFailure(log, e);
            return blockedScriptOutput(output, FAILURE_MESSAGE, newRecord,
                    seance);
        }
    }
    // Conversion of an entry to a POST parameter
    public static class PostProcedure
            implements gnu.trove.TObjectObjectProcedure {
        private PostMethod postMethod;
        public PostProcedure(PostMethod postMethod) {
            this.postMethod = postMethod;
        }
        public boolean execute(Object o, Object o1) {
            String name = (String) o;
            if (o1 instanceof EWWSBaseUserObjectMap) {
            } else if (o1 instanceof EWWSBaseUserObjectMap[]) {
            } else if (o1 instanceof String[]) {
                String[] strings = (String[]) o1;
                for (int i = 0; i < strings.length; i++) {
                    String s = strings[i];
                    postMethod.addParameter(new NameValuePair(name, s));
                }
            } else if (o1 != null) {
                postMethod.addParameter(
                        new NameValuePair(name, o1.toString()));
            }
            return true;
        }
    }
    //Signal to  EW that execution was not successful,
    // give the user a chance to correct the data
    private ScriptOutput blockedScriptOutput(ScriptOutput output, String s,
                                             SWDataMap newRecord,
                                             Seance seance) {
        output.setExitCode(ExternalScript.BLOCK);
        output.setMessage(
                s + " ID:" + newRecord.getSWRecordPK(seance).getID());
        return output;
    }
} 

The purpose of the "POSTPush" is to submit the result of modification of a record in Agiloft to an external host via HTTP POST. This script is run in a script action from the rule invoked on update. The script re-uses parts of WS/REST internal code to convert internal datatypes into POST parameters.

package com.enterprisewizard.examples;
/*
 * (c) Copyright 2008, EnterpriseWizard, Inc. All Rights Reserved.
 * No part of this document may be stored in a retrievable system,
 * transmitted or reproduced in any way without the prior written
 * permission of EnterpriseWizard.
 */
import com.enterprisewizard.ws.utils.LogHelper;
import com.enterprisewizard.scriptactions.conde.TicketUpdateScript;
import com.micromuse.response.server.soapserver.*;
import com.supportwizard.actions2.interfaces.ExternalScript;
import com.supportwizard.actions2.interfaces.ScriptActionException;
import com.supportwizard.actions2.interfaces.ScriptInput;
import com.supportwizard.actions2.interfaces.ScriptOutput;
import com.supportwizard.dml.SWDataMap;
import com.supportwizard.dml.SWRecordPK;
import com.supportwizard.seance.Seance;
import org.apache.log4j.Logger;
import java.net.URL;
/**
 * The purpose of the "NetcoolTicketUpdateScript" is to invoke a policy in
 * IBM Tivoli Netcool when a ticket is closed in EnterpiseWizard.
 * A policy can be invoked by calling a "Listener" Web Service provided
 * with each instance of Netcool.
 * This script is run in a script action from the rule invoked on update
 * and also periodically every 5 minutes. The purpose of the periodic run
 * is to pick up those tickets for which for some reason the information
 * was not transmitted successfully i.e. retry if some failure has
 * occured.
 * The script uses an integer field "submitted_to_netcool" to indicate that
 * the invocation was successful. To avoid cluttering history by recording
 * the success on the very first run the the suggested pattern is to have
 * the field set to 1 (success) by default and set value to 0 only when it
 * fails.
 * The script will only update the field if a change is required.
 * To attempt a resend such records can be isolated later by a rule run
 * periodically with an IF/THEN condition based on Advanced Filter - the
 * field changed value from 1 to 0 in the last X minutes.
 */
public class NetcoolTicketUpdateScript implements ExternalScript {
    public static final Logger log =
            Logger.getLogger(NetcoolTicketUpdateScript.class);
    public static final String USER_ID = "NetcoolUser";
    public static final String USER_PASSWORD = "NetcoolPassword";
    private static final String POLICY_NAME = "NetcoolPolicyName";
    private static final String ENDPOINT_URL =
            "http://NetcoolHost:NetcoolPort/" +
                    "NETCOOL_CLUSTER_NAME_jaxrpc/impact/" +
                    "ImpactWebServiceListenerDLIfc";
    private static final String FLAG_FIELD = "submitted_to_netcool";
    public ScriptOutput runScript(ScriptInput input)
            throws ScriptActionException {
        ScriptOutput output = input.createOutput();
        try {
            // Script gets two copies of the current record -
            // one before change (or null in case of creation) and one
            // after change
            SWDataMap newRecord = input.getNewRecord();
            // Obtain EnterpriseWizard ticket id
            Seance userSeance = input.getUserSeance();
            final SWRecordPK swRecordPK =
                    newRecord.getSWRecordPK(userSeance);
            Long ewTicketId = swRecordPK.getID();
            //Obtain the id of the Netcool event that correponds
            // to the EnterpriseWizard record
            Integer netcoolEventId =
                    (Integer) newRecord.get("netcool_event_id");
            boolean success;
            if (netcoolEventId != null) {
                URL url = new URL(ENDPOINT_URL);
                //Obain SOAP stub
                ImpactWebServiceListenerDLIfc listener =
                        (new ImpactWebServiceListenerDLLocator())
                                .getImpactWebServiceListenerDLIfcPort(url);
                WSListenerId lid = null;
                //Internal  EW class to assist with logging
                final LogHelper logHelper1 = LogHelper.create(
                        "ImpactWebServiceListenerDLIfc.login",
                        new String[]{"userId", "password"},
                        new Object[]{USER_ID, "*hidden*"});
                try {
                    logHelper1.logAttempt(log);
                    //Perform Login to Netcool via WS call
                    lid = listener.login(USER_ID, USER_PASSWORD);
                    if (log.isDebugEnabled()) log.debug("Object id is " +
                            lid.getClientId() + ":" + lid.getObjectId());
                    logHelper1.logSuccess(log);
                    success = true;
                } catch (Throwable e) {
                    log.error("Unexpected exception", e);
                    logHelper1.logUnexpectedFailure(log, e);
                    // we want to finish the script run without failure,
                    // to let user go and retry the process later
                    success = false;
                }
                if (success) {
                    final LogHelper logHelper2 = LogHelper.create(
                            "ImpactWebServiceListenerDLIfc.runPolicy",
                            new String[]{"PolicyName", "netcool_event_id"},
                            new Object[]{POLICY_NAME, netcoolEventId});
                    // In the following piece of code, we will execute
                    // a policy called WSListenerTestPolicy.
                    // To this policy we send one parameter with name
                    // "TicketID" and value of Netcool event id as String.
                    // The result of executing this policy
                    // will be in the captured and logged.
                    WSPolicyUserParameter[] wParams =
                            new WSPolicyUserParameter[1];
                    WSPolicyUserParameter thisParam =
                            new WSPolicyUserParameter();
                    thisParam.setName("TicketID");
                    thisParam.setValue(netcoolEventId.toString());
                    thisParam.setFormat("String");
                    wParams[0] = thisParam;
                    PolicyExecutionResult[] results;
                    try {
                        logHelper2.logAttempt(log);
                        //Invoke the policy via WS call
                        results = listener.runPolicy(lid, POLICY_NAME,
                                wParams, true);
                        logHelper2.logSuccess(log);
                        if (log.isDebugEnabled()) { // log the results
                            for (int i = 0; i < results.length; ++i) {
                                log.debug("name " + i + ": " +
                                        results[i].getName() + " value: " +
                                        results[i].getValue());
                            }
                        }
                    } catch (Throwable e) {
                        log.error("Unexpected exception", e);
                        logHelper2.logUnexpectedFailure(log, e);
                        success = false;
                    }
                }
            } else {
                log.warn("IGNORING. No Netcool event id in the record. " +
                        ewTicketId);
                success = true;
            }
            // Set the flag field to 0 or 1 depending on
            // the results and the previos value
            int synced = 0;
            final Object o =
                    newRecord.get(FLAG_FIELD);  // obtain the current value
            if (o instanceof Integer) {
                synced = (Integer) o;
            }
            if (!success && synced != 0 || success &&
                    synced == 0) { // only if the change is required
                final Long tableID = newRecord.getTableID();
                SWDataMap changeRecord = new SWDataMap(tableID);
                changeRecord.put(FLAG_FIELD, synced == 0 ? 1 : 0);
                output.setRecord(changeRecord);
            }
            // signal to  EW that script execution was successful
            output.setExitCode(ExternalScript.ACCEPT);
            return output;
        } catch (Throwable e) {
            // Anything that goes wrong is considered unrecoverable
            log.error("Unexpected exception", e);
            return blockedScriptOutput(output,
                    "Unexpected exception." + e.getMessage());
        }
    }
    //Signal to  EW that execution was not successful,
    //give the user a chance to correct the data
    private ScriptOutput blockedScriptOutput(ScriptOutput output,
                                             String s) {
        output.setExitCode(ExternalScript.BLOCK);
        output.setMessage(s);
        return output;
    }
} 

The purpose of the NetcoolTicketUpdateScript is to invoke a policy in IBM Tivoli Netcool when a ticket is closed in EnterpiseWizard. A policy can be invoked by calling a Listener web service provided with each instance of Netcool. This script is run in a script action from the rule invoked on update and also periodically every 5 minutes. The purpose of the periodic run is to pick up those tickets for which for some reason the information was not transmitted successfully i.e. retry if some failure has occurred. The script uses an integer field submitted_to_netcool to indicate that the invocation was successful. To avoid cluttering history by recording the success on the very first run the the suggested pattern is to have the field set to 1 - success - by default and set value to 0 only when it fails. The script will only update the field if a change is required. To attempt a resend such records can be isolated later by a rule run periodically with an IF/THEN condition based on Advanced Filter - the field changed value from 1 to 0 in the last X minutes.

CONTENTS