Access to the Studio Customization Toolkit

You can access JPOs through the ENOVIA Studio Customization Toolkit through two invoke methods on a new JPO class.The JPO class has two methods that correspond to serializing an Object into a String, and de-serializing a String back into an Object.

One form of the invoke method returns an int (useful for returning exit codes).

int ret = JPO.invoke(Context context, String className, String[] 
initargs,
    String methodName, String[] methodargs);

The other form returns a Java Object.

Object ret = JPO.invoke(Context context, String className, 
String[] initargs,
    String methodName, String[] methodargs, 
    java.lang.Class retType);

An example of an object method in the emxProject JPO would be:

import matrix.db.*;
public class ${CLASSNAME} {
  public ${CLASSNAME} (Context context, String []args) {
}
public BusinessObjectList query(Context context, String []args) 
{
Query query = new Query(args[0]);
    return query.evaluate(context);
  }
}

called by the following in a .jsp:

String[] init = new String[] {};
String[] args = new String[] { ".finder" };
BusinessObjectList list = 
(BusinessObjectList)JPO.invoke(context, "Project",
    init, "query", args, BusinessObjectList.class);

Use casting because the system only knows to return an object instance. In the example above, the BusinessObjectList is consistently used for declaring the object to hold the return object, for casting, and for the sixth argument that defines the return type.

Working with Java Objects is very powerful as the previous example showed. But what about passing Objects into a JPO method? The JPO class has two methods that correspond to serializing an Object into a String, and de-serializing a String back into an Object. The method names are packArgs and unpackArgs, respectively. Since JPOs only accept strings as arguments, you must use the packArgs/unpackArgs methods to convert Java objects to/from strings when using JPOs.

These methods actually work with a String array of size two, that holds the class in the first slot and the serialized object in the second slot. This allows users of the String array to do proper type casting. One can build up several Objects in a String array by calling packArgs() several times using the proper indexing into the String array. However, it is better to place all arguments in a single compound object (like a hashmap) and then pack just the single compound object into the args array. Keep in mind that any Object needing to be passed as an argument in this way must implement the java.io.Serializable interface.

Most classes are serialized and so may be passed as arguments to JPOs.

The packArgs method has the following signature:

public static String[] packArgs(Object in) throws Exception

The unpackArgs method has the following signature:

public static Object unpackArgs(String[] in) throws Exception

The following packing logic is placed in a bean that is called from a JSP.

    /**
     * Sends an icon mail message to the specified users.
     *
     * @param context the Matrix <code>Context</code> object
     * @param toList the to list of users to notify
     * @param ccList the cc list of users to notify
     * @param bccList the bcc list of users to notify
     * @param subject the notification subject
     * @param message the notification message
     * @param objectIdList the list of objects to send with the notification
     * @throws FrameworkException if the operation fails
     * @since AEF 9.5.0.0
     * @grade 0
     */
     public static void sendMessage(Context context,
                                   StringList toList,
                                   StringList ccList,
                                   StringList bccList,
                                   String subject,
                                   String message,
                                   StringList objectIdList)
        throws FrameworkException
    {
        try
        {
            ContextUtil.pushContext(context);
            // Create the arguments for the notification.
            Map note = new HashMap();
            note.put("toList", toList);
            note.put("ccList", ccList);
            note.put("bccList", bccList);
            note.put("subject", subject);
            note.put("message", message);
            note.put("objectIdList", objectIdList);
            // Pack arguments into string array.
            String[] args = JPO.packArgs(note);
            // Call the jpo to send the message.
            JPO.invoke(context, "emxMailUtil", null, "sendMessage", args);
        }
        catch (Exception e)
        {
            throw (new FrameworkException(e));
        }
        finally
        {
            ContextUtil.popContext(context);
        }
    }

The unpacking logic is then found in the JPO method where it is performed prior to passing the arguments on to the worker method (this design pattern is very useful for hiding the details of packing and unpacking arguments).

    /**
     * Sends an icon mail notification to the specified users.
     *
     * @param context the Matrix <code>Context</code> object
     * @param args contains a Map with the following entries:
     *        toList - the list of users to notify
     *        ccList - the list of users to cc
     *        bccList - the list of users to bcc
     *        subject - the notification subject
     *        message - the notification message
     *        objectIdList - the ids of objects to send with the notification
     * @returns nothing
     * @throws Exception if the operation fails
     * @since AEF 9.5.0.0
     */
    public static int sendMessage(Context context, String[] args)
        throws Exception
    {
        if (args == null || args.length < 1)
        {
            throw (new IllegalArgumentException());
        }
        Map map = (Map) JPO.unpackArgs(args);
        sendMessage(context,
                    (StringList) map.get("toList"),
                    (StringList) map.get("ccList"),
                    (StringList) map.get("bccList"),
                    (String) map.get("subject"),
                    (String) map.get("message"),
                    (StringList) map.get("objectIdList"));
        return 0;
    }