Leave feedback
  • Calling a java class from a StreamServe script

Write an Article
Tuesday 30 October, 2012
Stefan Cohen Stefan Cohen StreamServe Employee Administrator
12 likes 4195 views

One of the new possibilities in StreamServe 5.6 is that you can now call Java classes directly from within a StreamServe Script. This allows you to extend your StreamServer with all the capabilities of the Java language and also make use of the myriads or libraries and applications that exists out there.

 

Introduction

We introduced the execute() script function in StreamServe 5.5. This allows you to execute any external application (including a jvm) from the StreamServer. The draw-back of launching a jvm this way is that the JVM must be loaded for each invocation of the script. This can have some serious performance implications.

In 5.6, the JVM is loaded by the StreamServe Component Framework (SCF) when the new java functions are being used. This guarantees that the JVM is loaded only once.
The script extensions allows you to either write your own Java classes from scratch or re-use existing classes obtained commercially or as open-source.
There are four script functions available. They are:

  • JavaCreateObject - Instantiates a new Java object of a specific class.
  • JavaDestroyObject - Destroys the Java object identified by strObjHandle.
  • JavaInvokeMethod - Invokes a Java method of the Java object identified by a handle.
  • JavaInvokeStaticMethod - Invokes a static method of a specified Java class.

Let’s examine the functions a bit closer.

JavaCreateObject

Syntax: JavaCreateObject(strObjHandle, strClassName);

  • strObjHandle -Handle to be associated with the created object.
  • strClassName - Name of the java class to instantiate.

Prerequisites: The Java environment of the StreamServe application must be configured, i.e. the compiled Java class must be accessible. See Configuring Java parameters in the Control Center documentation for more information.

Description:  Instantiates a new Java object of a specific class. The class name is provided as an argument to the function call. The caller also provides a handle name (string) to be used in subsequent calls to refer to the created object. The Java object constructor gets called when creating an object.

Returns:  A number indicating whether the object was successfully created.

  • 0 - The object was successfully created.
  • -1 - Failed to create the object. See the log for more detailed information.

 

Example:
$iRetVal = JavaCreateObject("objTestHandle", "streamserve.invokeexternaljava.TestClass");


JavaInvokeMethod

Syntax: JavaInvokeMethod(strObjHandle, strMethodName, [var_1, var_2, ...], [return_var]);

  • strObjHandle: Handle identifying the object to invoke.
  • strMethodName: Name of the Java method to invoke.
  • var_1, var_2, ... : Zero or more variables from StreamServe scripts to be used as arguments in method call.
  • return_var: Optional StreamServe variable that will be set to the return value of the invoked Java method.

Description: Invokes the Java method strMethodName of the Java object identified by strObjHandle. The JavaInvokeMethod function can take zero or more variables as arguments, and zero or one return variable. All the variables must be pre-defined in StreamServe scrips. Explicit values, or return values from other functions can not be passed directly to the JavaInvokeMethod function. The last variable is always the return value, it is therefore not possible to transfer argument variables without having a return variable. All variable values are transferred to Java as java.lang.String values.

Returns: A number indicating whether the method was successfully invoked.

  • 0 - The method was successfully invoked.
  • -1 - Failed to invoke the method. See the log for more detailed information.

Example:
iRetVal = JavaInvokeMethod("objTestHandle", "clearDocStatus");
$iRetVal = JavaInvokeMethod("objTestHandle", "getDocStatus", $retStatus);
$iRetVal = JavaInvokeMethod("objTestHandle", "docProcessed", $job_id, $doc_id, $retStatus);

The corresponding Java methods for the above calls must be:
public void clearDocStatus()
public String getDocStatus()
public String docProcessed(String job_id, String doc_id)


JavaDestroyObject

Syntax: JavaDestroyObject(strObjHandle);

  • strObjHandle - Handle identifying the object to destroy.

Description: Destroys the Java object identified by strObjHandle. It is possible to reuse the same handle to create a new object after successful destruction of the Java object.

Returns: A number indicating whether the object was successfully destroyed.

  • 0 - The object was successfully destroyed.
  • -1 - Failed to destroy the object. See the log for more detailed information.

Example:
$iRetVal = JavaDestroyObject("objTestHandle");



JavaInvokeStaticMethod

Syntax: JavaInvokeStaticMethod(strClassName, strMethodName, [var_1, var_2, ...], [return_var]);

  • strClassName: Name of the Java class to invoke.
  • strMethodName: Name of the Java method to invoke.
  • var_1, var_2, ... : Zero or more variables from StreamServe scripts to be used as arguments in method call.
  • return_var: Optional StreamServe variable that will be set to the return value of the invoked Java method.

Prerequisites: The Java environment must be configured, i.e. the compiled Java class must be accessible. See Configuring Java parameters in the Control Center documentation for more information.
Description: This function directly invokes the specified static method of the specified Java class. The external Java method must be statically defined (it is not necessary to call JavaCreateObject). The JavaInvokeStaticMethod function can take zero or more variables as arguments and zero or one return varible. All the variables must be defined in StreamServe scrips. Explicit values, or return values from other functions can not be passed directly to the JavaInvokeStaticMethod function. The last variable is always the return value, it is therefore not possible to have an argument variable without having a return variable. All variable values are transferred to Java as java.lang.String values.

Returns: A number indicating whether the method was successfully invoked.

  • 0 - The method was successfully invoked.
  • -1 - Failed to invoke the method. See the log for more detailed information.

Example:
$iRetVal = JavaInvokeStaticMethod("streamserve.invokeexternaljava.StatusService", "initialize");
$iRetVal = JavaInvokeStaticMethod("streamserve.invokeexternaljava.StatusService", "getStatus", $retStatus);
$iRetVal = JavaInvokeStaticMethod("streamserve.invokeexternaljava.StatusService", "docProcessed", $job_id, $doc_id, $retStatus);

The corresponding Java methods for the above calls must be:
public static void initialize()
public static String getStatus()
public static String docProcessed(String job_id, String doc_id)


A simple example

Let’s take a look at a very simple example. Let us ignore the fact that the StreamServe script language already has built-in functions for making strings all upper case. If we now want to implement a java class to do this for us instead, we can use the toUpperCase() method from the java.lang.String class to do the work for us.

A simple java class to return the input string as all upper case.
package streamserve.script;
public class Case {
  public static String ToUpper(String input)
  {
   return input.toUpperCase();
  }
}

Compile this class to a .jar file using your tool of choice. Now you need to put this jar in the servers classpath. There are two main locations to be aware of (relative to the working directory of your applicaiton): ./java and ../data/java;

For testing, I find it convenient to create folder named “java” in the working directory and place the .jar there. This folder is automatically included in the classpath of the application.
 For production usage, simply import the .jar into your project’s resource set as the resource type “Java”. This will guarantee that the class is included in future re-deployments of the application and it will follow the project if you move it to another machine. When the project is deployed, the .jar resources will be exported to the data/java folder one step up relative to the working directory.
 
Next, configure the java parameters for your application.  Right-click on your application in ControlCenter and select “Configure Java”. In the vendor parameter, simply select SUN or IBM depending on what JVM you use.
 

To call the class, we will have to create a script in our project. Here’s an example:

$input ="Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
$returnvalue = JavaInvokeStaticMethod("streamserve.script.Case", "ToUpper", $input, $result);
if (num($returnvalue) == 0) {
  Log(0, "Successfully invoked static method");
  Log(0, "Result: " + $result);
}
else {
  Log(0, "Invoke of static method Failed!");
}


Since the ToUpper method is declared as static and we don’t need to keep the object alive for more than just this call, we can use the JavaInvokeStaticMethod function. This is pretty straight-forward as we don’t need to first create the object, call the method and then destroy the object. We can simply call the function and that’s it.
Here’s a sample log of the execution:
1026 045442 (1726) 2 Collect Event:E < directoryscanner=Input
1026 045442 (1155) 0 Successfully invoked static method
1026 045442 (1155) 0 Result: LOREM IPSUM DOLOR SIT AMET, CONSECTETUR ADIPISCING ELIT.



Log interface

The script interface to java provides a log interface that allows you to write to the StreamServe log directly from our class.
To use this interface, we will need to reference a file called jstrs.jar and add it to our build path. This file is located in: “<InstallPath>\Applications\StreamServer\5.6.0\Server\bin\javaclasses\streamserver”
Once added, we can modify our example to something like this:


package streamserve.script;

import streamserve.context.Context;
import streamserve.context.LogService;
import streamserve.context.LogData;

public class Case {

  public static String ToUpper(String input)
  {
   Context context = streamserve.context.ContextFactory.acquireContext(streamserve.context.ContextFactory.ScriptContextType);

   try
   {
    LogService logService = context.getInterface( LogService.class );
    LogData logData = new streamserve.context.LogDataImpl("Attempting to convert string to uppercase", streamserve.context.LogLevel.info);

    logService.log("streamserve.script.Case", logData );
    return input.toUpperCase();
   }
   catch (Throwable e)
   {
    throw new RuntimeException(e);
   }
   finally
   {
    if (context != null)
   {
    streamserve.context.ContextFactory.releaseContext(context);

   }
  }
}
}

Here's a sample log output from executing the script:

1026 060602 (0000) 3 Attempting to convert string to uppercase
1026 060602 (1155) 0 Successfully invoked static method
1026 060602 (1155) 0 Result: LOREM IPSUM DOLOR SIT AMET, CONSECTETUR ADIPISCING ELIT.

There is also a metadata interface available but that will be covered in a later article.

Object Scope Limitations

In this first release, we have decided to limit the object scope (the context in witch java objects live in the StreamServer) to the script context from where the script functions are called. This means that you will be able to create an object and use it within a script scope (for example "Before Process") but the object will be automatically destroyed as soon as you go out of the script scope. This means that you for example will not be able to create an object in a "retrieved script" context, call a method on the object in a "Before Process" script and then destroy it "After Process". This may change in later releases.
Other know limitations is that it is not possible to pass or recieve arrays to or from the script functions.

Comments (2)

  • Great stuff, Stefan. This will be useful. 

    Mats

    Saturday 17 November, 2012 by Mats Pursche
  • Hello Stephan

    With theses new java features in 5.6, is it possible to insert javascript (one line) in ouput file pdf composed with StreamServer ?

    For example : /S /JavaScript /JS (this.command1\(false\);\rthis.command2\(true\);)

    Philippe

    Friday 22 March, 2013 by Philippe Grapperon

   


Post comment