Recently we ran into a problem impacting many of our REST jobs. The fix recommended by Tricise/Broadcom is to unload all of these objects to a transport case file and then load them back again. Because the AWI offers no way to search for objects by job sub-type, we are left with no straightforward way to quickly move the many hundreds of impacted objects to the transport case. We can generate a list using an SQL query, but there's no built-in way to tell the AE to add a list of objects to the transport case.
I have an old tool that uses SearchObject to find and add objects one at a time, but it is very slow, taking 10–15 seconds per object.
This brings me back to the ITransportable interface. Today I developed a class that implements ITransportable in a quick-and-dirty way to facilitate adding to the transport case a list of objects provided by the user.
public class TransportableObject implements ITransportable {
private final String objectName;
private final String ObjectId;
private final String ObjectType;
private final String FolderId;
// Constructor to initialize with object name
public TransportableObject(Connection aeConnection, String objectName) throws IOException {
this.objectName = objectName;
UC4Object uc4Object = openObject(aeConnection, objectName, true);
this.ObjectId = uc4Object.getIdnr();
this.ObjectType = uc4Object.getType();
this.FolderId = "0";
}
@Override
public String getId() {
return this.ObjectId;
}
@Override
public String getName() {
return objectName;
}
@Override
public String getObjectType() {
return this.ObjectType;
}
@Override
public String getFolderID() {
return this.FolderId;
}
}
This relies on some other classes & methods I've developed, such as the openObject method to open a named object. It obviously also relies on an already-established Connection to the AE server.
This class returns the folder ID 0 in all cases. This is to reduce overhead and save time. If there is a lightweight way to look up an object's folder ID using the Java APIs, I was not able to find it. The folder ID does not seem to be important for my use case.
Here's the method I wrote to use the new TransportableObject class.
public static void transportListOfObjects(Connection aeConnection, String inputFilePath) throws IOException {
boolean aeError;
Integer numObjects = 0;
String pluralSuffix = "";
TransportObject transportObject;
try {
System.out.println(String.format("Reading list of objects from file %s.", inputFilePath));
List<String> objectNames = Files.readAllLines(Paths.get(inputFilePath));
numObjects = objectNames.size();
switch (numObjects) {
case 0:
System.out.println("No objects in list. Nothing to do. Exiting.");
exit();
break;
case 1:
pluralSuffix = "";
break;
default:
pluralSuffix = "s";
break;
}
System.out.println(String.format("%s object%s in list. Preparing to add objects.", numObjects, pluralSuffix));
List<ITransportable> transportableObjectList = new ArrayList<>();
for (String objectName : objectNames) {
if (!objectName.equals("")) {
// Use home-grown TransportableObject class
transportableObjectList.add(new TransportableObject(aeConnection, objectName.toUpperCase()));
}
}
transportObject = new TransportObject(transportableObjectList.iterator());
System.out.println(String.format("Adding object%s to transport case.", pluralSuffix));
aeConnection.sendRequestAndWait(transportObject);
aeError = checkForAeErrors(transportObject);
if (aeError) {
System.out.println(String.format("Error encountered when adding object%s to transport case.", pluralSuffix));
exit();
}
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
This approach seems to work OK, and is much quicker than using SearchObject to find each object. The faked folder IDs do not appear to cause a problem.
Enjoy!