IBM Streams 4.2

Generated Java operator

The operator spl.utility.JavaOp can generate Java™ source templates for the specific invocation of the operator.

The generated templates include generated interfaces specific to the input and output port schemas. These interfaces include getter and setter methods corresponding to the type and name of each attribute in the port's schema. These templates are generated by the SPL compiler when the JavaOp invocation has the generated parameter set to true.

Start with this example.

stream <int32 id, ustring tag, list<float64> data> CoolStream
   = JavaOp(SENSORS)
{
  param
    generated: true;
    className: "com.acme.streams.CoolOperator";
    classLibrary: "";
}
The class CoolOperator contains the application logic for the operator. Compiling the application generates two Java source files in the directory opt/java/src in the application directory (assumed here to be /streams/app). The abstract operator in this case is AbstractCoolOperator in the package com.acme.streams and, thus, its source file is found in the following location /streams/app/opt/java/src/com/acme/streams/AbstractCoolOperator.java. This file is generated for each compilation and is not to be changed by the developer.

Now look through the key aspects of the generated abstract operator.

First, the abstract class definition.

package com.acme.streams;

// Required imports from Streams API (only one shown)
import com.ibm.streams.operator.AbstractOperator;

public class AbstractCoolOperator extends AbstractOperator

Then, the input ports.

public interface IPort0 {
      public int get_id();
      public long[] get_timestamps();
      public short[][] get_readings();
      public String get_tag();
      public Tuple getTuple();
}
// Tuples for port 0 are delivered to the operator via this method.
protected abstract void process0(IPort0 tuple) throws Exception;
An interface of the form IPortN is created for each input port as an inner-class of the abstract operator. This interface includes getters for the tuple attributes that return the corresponding Java type for the attribute, using a Java primitive where possible. A getTuple method is provided to get the generic tuple representation. An abstract processN method is defined and it requires that a developer implements the corresponding concrete class. This class handles the processing of tuples that arrive on that port. Similarly, a specific interface is created for each output port, along with methods to support the port.
// Interface for output port 0
public interface OPort0 {
      public int get_id();
      public String get_tag();
      public double[] get_data();

      public void set_id(int value);
      public void set_tag(String value);
      public void set_data(double[] value);
      public OutputTuple getOutputTuple();
}
// Method to obtain output description for port 0
public StreamingOutput<OPort0> getOutput0();

// Method to submit tuples to port 0.
public boolean submit0(OPort0 tuple) throws Exception { … }
For each output port, an interface OPortN is created as an inner-class of the abstract operator class. This interface includes getters and setters for the attributes that return the corresponding Java type for each attribute, using Java primitive types where possible. A getOutputTuple method is provided to retrieve the generic output tuple representation. New instances of the OPortN interface are created using the StreamingOutput<OPortN> interface available through the generated method getOutputN. Tuples can then be submitted using the port specific method submitN.

The template for the concrete operator class is created only if the source file does not exist. Here is an example of a generated template, showing two methods that need to be completed (marked with TODO) to provide the required function.

package com.acme.streams;

// Required imports from Streams API (only one shown)
import com.ibm.streams.operator.OperatorContext;

public class CoolOperator extends AbstractCoolOperator {

      @Override
      public void initialize(OperatorContext context) throws Exception {
	          super.initialize(context);
            // TODO Auto-generated method stub
}
      @Override
      protected void process0(IPort0 tuple) throws Exception {
            // TODO Auto-generated method stub
      }
} 
Here is an example of a completed concrete operator using these generated interfaces and methods to submit a tuple that is a function of the incoming tuple.
package com.acme.streams;

import com.ibm.streams.operator.OperatorContext;

public class CoolOperator extends AbstractCoolOperator {

      @Override
      public void initialize(OperatorContext context) throws Exception {
	          super.initialize(context);
      }
      @Override
      protected void process0(IPort0 tuple) throws Exception {
            Oport0 outputTuple = getOutput0().newTuple();

            outputTuple.set_id(tuple.get_id());
            outputTuple.set_tag(tuple.get_tag());

            long[] timestamps = tuple.get_timestamps();
            short[][] readings = tuple.get_readings();

            // calculate data from timestamps & readings
            double[] data = …

            outputTuple.set_data(data);
            submit0(outputTuple);
      } 
Compilation of the SPL program also automatically compiles the abstract and concrete operators using the output directory java/bin in the output directory. The class path that is used for the compilation includes the class path elements in the classLibrary parameter in the operator's definition and automatically includes the IBM® Streams library com.ibm.streams.operator.jar.