Extending ArcScript with Custom Operations


ArcScript’s built-in set of Operations can be extended to make use of pre-written code, specialized use cases, and familiar development environments. ArcScript supports custom Operations developed in C# and Java through a straightforward process of wrapping the desired functionality in a simple interface. Additionally, ArcScript can easily invoke existing code like commands, batch files, and compiled binaries (.exe’s and .jar’s).

This page will walk through the process of developing & calling a custom Operation and provide an example of invoking external code from within an ArcScript context.


Creating a Custom Operation

The core principle of developing a custom operation is simple: implement a two-method interface called RSBOperation.

This interface is explained in detail below, but first it is useful to review how input is provided to an Operation and how output is returned from an Operation.

Operation Input and Output

Input is provided to an Operation through an input Item, and output is returned from an Operation through an output Item. In ArcScript, Items are simple collections of attributes (i.e. variables).

Input Items

When calling an Operation, a specific Item may be provided as input using the in keyword, like the following:

<arc:set attr="myItem.file" value="C:\\temp\\file.txt" />
<arc:call op="fileRead" in="myItem" />

An Operation should define the Attribute parameters it expects from an input Item. For example, the fileRead Operation referenced above defines file as the only required input parameter.

If no Item is specified via the in keyword, an implicit default Item is used, like the following:

<arc:set attr="file" value="C:\\temp\\file.txt" />
<arc:call op="fileRead" />

Output Items

When calling an Operation, an output Item is specified with the out keyword, like the following:

<arc:set attr="myItem.file" value="C:\\temp\\file.txt" />
<arc:call op="fileRead" in="myItem" out="outItem">
  <arc:set attr="myItem.file_length" value="[outItem.file:data | getlength()]" />
</arc:call>

An Operation should define the Attribute parameters it provides as output. For example, the fileRead Operation defines file:data as the only output parameter.

RSBOperation Interface

Any C#/.NET or Java class that implements the RSBOperation interface can be invoked through the same arc:call keyword used with built-in Operations. Understanding this interface is equivalent to understanding how to turn C# and Java code into an ArcScript Operation.

RSBOperation defines two methods:

  • string Info()
  • void Exec(RSBContext ctx)

Info()

The Info() method returns a simple string that describes the Operation as well as the expected input parameters and output parameters. The format of this String is the following XML structure:

<arc:info desc="A description of the operation">
  <input name="myInputAttr" desc="A description of this input attribute" required=true />
  <input name="anotherInputAttr" desc="A description of this input attribute" />
  <output name="myOutputAttr" desc="A description of this output attribute" />
  <output name="anotherOutputAttr" desc="A description of this output attribute" />
</arc:info>

For example, here is the full Info() method for the fileRead Operation referenced in the previous section:

public String info() {
    return "<arc:info desc='Reads a text file and pushes the data out.'>" +
    "<input name=file desc='The name of the file to read.' required=true/>" +
    "<input name=encoding desc='The encoding of the file.' default='UTF-8' />" +
    "<output name=data desc='The file data.'/>" + 
    "</arc:info>";
  }

Exec(RSBContext ctx)

The Exec() method performs the work of the Operation. The RSBContext object (i.e. ‘ctx’) provides access to the input and output Attributes of the Operation. The Exec() method should be used to wrap the intended functionality of the custom operation and to include some simple code for reading input and writing output.

The RSBContext methods relevant for the Exec() method are the following:

  • GetInput(string attrName) — returns the value for the ‘attrName’ Attribute passed in to the Operation
  • SetOutput(string attrName, string value) — sets the value for the ‘attrName’ Attribute pushed out of the Operation
  • PushItem() — pushes out the output Item; without PushItem, the Operation will not provide any output

To help clarify the role of the Exec() method, imagine a custom class written in C# called myMagicParser. This class performs a sophisticated parsing procedure on a raw input string and is written such that a single method abstracts away the details of the parsing procedure, e.g. Parse(string rawInput). The Exec() method could wrap the functionality of this class like the following:

public void Exec(RSBContext ctx) {
  string rawInput = ctx.GetInput("raw");
  ctx.SetOutput("parsed", Parse(rawInput));
  ctx.PushItem();
}

For this example Operation, the Info() method should advertise raw as an input parameter and parsed as an output parameter.

Since the Info() method is a simple description of the inputs and outputs, and since the Exec() method is merely a wrapper for the functional logic, modifying an existing class to implement the RSBOperation interface should require minimal development time.

Referencing RSBOperation

In order to implement the interface in code, the project must reference RSSBus.dll (Windows) or rssbus.jar (Java). For Windows, the .dll to include is located here:

C:\Program Files\CData\Arc\www\bin\RSSBus.dll

In Java, the .jar file to include is located in the WEB-INF/lib folder for the server hosting the application; for example when using the embedded Jetty server, the file is located here:

/opt/arc/webapp/WEB-INF/lib/rssbus.jar

This path to the WEB-INF/lib folder may differ when hosting Arc on an external servlet like Tomcat.

Making a Custom Operation Visible

After modifying a C# or Java class to implement the RSBOperation interface, the custom class (Operation) should be compiled into a .dll or .jar. The resulting binary file needs to be made visible to Arc by copying it into the appropriate location.

The .dll or .jar containing the custom Operation should be placed in the same directory where the RSSBus.dll or rssbus.jar file was referenced in the previous section. After placing the compiled file in the appropriate folder, the server must be restarted.

Calling a Custom Operation in ArcScript

Since custom Operations implement the same RSBOperation interface as all of the built-in Operations, the same arc:call syntax can be used to invoke them. The op attribute of the arc:call statement should use the following syntax:

myFileName.myOpName

For example, if the custom class is called myMagicParser and is compiled into customOp.dll, then the following syntax would be used:

<arc:call op="customOp.myMagicParser" in="myInputItem" out="myOutputItem">

Given the example implementation of myMagicParser provided in the Exec(RSBContext ctx) section of the RSBOperation Interface section, where the expected input Attribute is ‘raw’ and the output attribute is ‘parsed,’ here is a full ArcScript snippet for invoking that Operation:

<arc:set attr="myString.raw" value="some example string to parse" />
<arc:call op="customOp.myMagicParser" in="myString" out="tempOut">
  <arc:set attr="myString.parsed" value="[tempOut.parsed]" />
</arc:call>
<!-- [myString.parsed] can be used to reference the parsed string -->

Invoking an External Process

In addition to creating custom Operations, ArcScript supports invoking pre-compiled executables without needing to modify the source code to implement RSBOperation. This allows Arc to integrate with pre-existing programs, commands, or batch scripts that accomplish a critical aspect of business logic, without the need to re-implement this logic in the application.

ArcScript includes the built-in Operation sysExecute to call external code, pass arguments as parameters, and access the standard output from the process. As a simple example, the whoami command can be run within an ArcScript context by using sysExecute with the whoami.exe executable:

<arc:set attr="executable.name" value="C:\\Windows\System32\\whoami.exe" />
<!-- arc:set attr="executable.arguments" value="some example command line arguments" -->
<arc:call op="sysExecute" in="executable" out="tempOut">
  <arc:set attr="out.data" value="[tempOut.sys:output]" />
</arc:call>

sysExecute can run any program that could be run directly through a command prompt.




Ready to get started?

Use Arc's free 30-day trial to start building your own custom workflows today:

Download Now