Translating AML to Server-Side Code

In previous blog posts, we've covered how to query the Aras Innovator server using AML requests sent via an external service like Nash or InnovatorAdmin. In this blog post, we'll be covering how to query the server with C# Item objects defined in the standard Aras IOM.dll. 

Using the IOM

To begin, we'll cover some of the basic operations of the IOM. You can also check out the documentation page on the Aras website for a full reference of the IOM.

Innovator

If you've worked with server-side code inside of Aras Innovator before, you've probably noticed a line like this at the start of almost every method.

Innovator inn = this.getInnovator();

The Innovator object defined in the IOM provides a number of useful functions for querying the server, the most notable one being the ability to create a new Item object with newItem. Many of the examples in this blog post will be using this Innovator object, so to keep the samples shorter, we'll be assuming that this line of code that defines the Innovator object will come before all of our samples.

Item

Most of your the AML queries you'll ever write will start with two pieces of information: the ItemType you want to query on and the type of query you want to perform. Below you can see an example of a simple query in AML and it's IOM equivalent. 

AML

<Item type="Part" action="get" />

IOM

Item part = inn.newItem("Part", "get");

Items can also contain a number of attributes to modify the query. newItem allows you to define at most the type and action attributes., and additional attributes can be set through the IOM by using setAttribute like the example below.

AML

<Item type="Part" action="get" select="item_number,name" where="[part].item_number like 'MP%'" serverEvents="0" />

IOM

Item part = inn.newItem("Part", "get");
part.setAttribute("select", "item_number,name");
part.setAttribute("where", "[part].item_number like 'MP%'");
part.setAttribute("serverEvents", "0");

Some of the most commonly used attributes also have special functions that can be used to set them specifically. These functions can be seen in the example below.

AML

<Item type="Part" action="get" id="EFFD9B3E5A9A4F328892DFBBDAE6ED7B/>

IOM

Item part = inn.newItem();
part.setType("Part");
part.setAction("get");
part.setID("EFFD9B3E5A9A4F328892DFBBDAE6ED7B");

Properties

While Item objects alone can be used for a number of useful queries, you'll typically also want to define some properties on your AML queries. The IOM allows for this in a similar way to setting attributes on the item.

AML

<Item type="Part" action="get">
  <make_buy>Make</make_buy>

</Item>

IOM

Item part = inn.newItem("Part", "get");
part.setProperty("make_buy", "Make");

If the property does not already exist on the Item when you call setProperty, it will be created. Otherwise, the value of the property will be overwritten with the new value you pass in. The IOM also supports the easy definition of more complex property queries such as those using a condition or those using Item properties. You can see an example of these in the code snippets below.

AML

<Item type="Part" action="get">
  <make_buy>Make</make_buy>

  <item_number condition="like">MP%</item_number>
  <created_by_id>
    <Item type="User" action="get">
      <keyed_name>Chris Gillis</keyed_name>
    </Item>
  </created_by_id>
</Item>

IOM

Item part = inn.newItem("Part", "get");
part.setProperty("make_buy", "Make");
part.setProperty("item_number", "MP%");
part.setPropertyAttribute("item_number", "condition", "like");

// Option 1 for setting an item property
Item partCreatedBy = part.createPropertyItem("created_by_id", "User", "get");
partCreatedBy.setProperty("keyed_name", "Chris Gillis");
// Option 2 for setting an item property
Item partCreatedBy = inn.newItem("User", "get");
partCreatedBy.setProperty("keyed_name", "Chris Gillis");
part.setPropertyItem("created_by_id", partCreatedBy);

Notice that in this code snippet, we can set the sub-query of our created_by_id property in two different ways. Option 1 creates the item directly from the created_by_id property using createPropertyItem. Option 2 first creates the item and then appends it to the property using setPropertyItem. If you're following along with these samples in the Aras method editor, you can look at the right-side of the window to find a reference pane that you can use for quick lookups of IOM classes and functions. You can even double-click on a function in the reference pane to automatically paste it into your method code!

  1. The reference pane containing the names of the objects and methods available in the IOM
  2. The help pane that will be populated with a more detailed explanation of an object or method that you have selected

Relationships

The last piece of the IOM that we'll cover is how to add relationships to your query. You can see an example of querying on a relationship using AML and the same query using the IOM below.

AML

<Item type="Part" action="get">
  <Relationships>
    <Item type="Part BOM" action="get">

      <related_id>
        <Item type="Part" action="get" where="[part].classification = 'Software'" />
      </related_id>
    </Item>
  </Relationships>
</Item>

IOM

Item part = inn.newItem("Part", "get");
Item partBoms = part.createRelationship("Part BOM", "get");

// Option 1 for creating a related item
Item childPart = partBoms.createRelatedItem("Part", "get");
// Option 2 for creating a related item
Item childPart = partBoms.createPropertyItem("related_id", "Part", "get");

childPart.setAttribute("where", "[part].classification = 'Software'");

In our IOM sample, we use the method createRelatedItem. This is a special method available from Relationship items that functions identically to calling createPropertyItem on the related_id.

Executing Your Query

You can execute your query by simply calling the apply function of your Item. This will always return an Item though you may wish to do some validation such as checking whether the Item is an error or that it has returned the number of items you were expecting.

Item part = inn.newItem("Part", "get");
Item res = part.apply();

if (res.isError() || res.getItemCount() !== 1) {
    // Handle your exceptions 
}

One thing to keep in mind when using apply is that it will trigger a call to the server for the data requested. Server calls tend to be the most time consuming part of methods, so it's good practice to try and limit the amount of applies in your methods.

Using AML with the IOM

While it's recommended that you use the IOM inside of a server method, there are some occasions when you'll need to process raw AML. In these cases, you have a couple options.

Apply the AML Directly

The Innovator object supports a function to send AML directly to the Innovator Server similar to how Nash works. Just like the standard Item.apply function, this special apply will also return an Item object containing the result of the query. One caveat of this approach is that the AML must be wrapped in <AML> tags just like any query you would send through Nash.

string aml = "<AML><Item type="Part" action="get"/></AML>";
Item res = inn.applyAML(aml);

Convert the AML to an Item

The other way of handling AML is by first loading it into an Item object. There are two major benefits to this approach. The first is that the AML may or may not contain <AML> tags, and it will still be loaded into the item. It even supports additional formats such as AML wrapped in a SOAP envelope. The second benefit is that this allows the AML to be easily modified through the IOM before it is applied to the server such as in the example below.

string aml = "<Item type="Part" action="get"/>";
Item part = inn.newItem();
part.loadAML(aml);
// Manipulate the Item as needed before applying
part.setProperty("item_number", "MP0101");
part.apply();

Conclusion

The IOM provides useful functions both for creating queries to the server as well as handling the data that gets returned by your queries. If you've been following along with our previous AML blog posts, beginning to write server-side code shouldn't be too much of a leap. If you're already writing server-side code and want some additional tips, check out our Best Practices for Server-Side Code.


Anonymous