This document explains how to integrate Java model generated by SAP Automated Analytics from an external Java program.
Code generation is done through SAP Automated Analytics API call below:
generateCode(in string iType, in string iDirectory, in string iFileName);
or
generateCode2(in string iType, in string String iType, String iDirectory, String iFileName, String iTargetName, String iSpaceName, String iKeyName )
where iType
is set to "JAVA
" and iFileName
is the name of the java file to generate ( see "API Reference Guide" for more information).
Code generation can also be done through SAP HANA Automated Predictive Library API call below:
CALL "SAP_PA_APL"."sap.pa.apl.base::EXPORT_APPLY_CODE"(FUNC_HEADER, MODEL, OPERATION_CONFIG, RESULT)
with parameter "APL/CodeType
" set to "JAVA
" ( see SAP HANA Automated Predictive Library Developer Library Guide for more information ).
Code compilation needs KxJRT.jar in the classpath as shown below:
javac -classpath "path-to-KxJRT.jar" ExportedModelInJava.java
where ExportedModelInJava.java is the generated java code. This generates a file named ExportedModelInJava.class
that contains java bytecode.
Then, in order to use the exported model in JAVA code, the KxJRT.IKxJModelInputWithNames
interface must be implemented. This object is passed as argument to the IKxJModel.apply()
method and defines how to retrieve the input data.
This interface has the following methods which must be implemented:
java.lang.String[] getVariables()
: this method returns the variable names of the data source the model is to be applied on.boolean isEmpty( int iVarIdx, java.lang.String iMissingString )
: this method returns whether the current value for variable with index iVarIdx in the array returned by getVariables, is an empty value or not.- as well as plenty of methods (
floatValue()
,intValue()
, ...,dayOfWeek()
) that convert a value into a correct data type. These methods are described in theIKxJModelInput
.
For example, consider an object DataProvider
which is able to provide variable values, is available. Then the following code could be:
...
import KxJRT.*;
...
class KxJModelInput extends DataProvider implements IKxJModelInputWithNames {
...
// _IKxJModelInputWithNames interface_
String[] getVariables()
{
// _use DataProvider to get the list of available variables_
...
}
boolean isEmpty( int iVarIdx, java.lang.String iMissingString )
{
boolean lIsMissing;
// use DataProvider to test if current
// value for variable iVarIdx is missing.
// for example, perfom a "ISNULL" when using a SQL source.
String lStringValue;
// use DataProvider to get, if possible,
// the string representation of the current value.
// when dealing with SQL source, it is not
// available for continuous value._
if( lIsMissing || lStringValue.equals( iMissingString ) )
return true;
else
return false;
}
float floatValue( int iVarIdx )
{
// if current value is continuous, then return its value, else return a default value say 0_.
...
}
//... And so on ...
}
The previous class reads a flat file and converts string values into the desired type.
In order to have a concrete implementation of this class, please refer to KxJRT.KxFileReaderWithNames
for an example code.
At last, the final skeleton code should contain the following lines to execute an exported model in JAVA code:
...
import KxJRT.*;
...
// String containing the model class name. For example ,
// if model.java was generated, then lModelName is "model"_ .
java.lang.String lModelName;
...
// ask the factory to instanciate the class._
IKxJModel mKxModel = [KxJModelFactory](javadoc/KxJRT/KxJModelFactory.html) .getKxJModel( lModelName );
...
// instanciate IKxJInputModelWithNames_
KxJModelInput lInput = new KxJModelInput( ... );
...
// instanciate KxJRT.KxJModelInputMapper ( see [KxJRT.Mapper](javadoc/KxJRT/Mapper.html) class )_
KxJModelInputMapper mMapper = new [KxJModelInputMapper](javadoc/KxJRT/KxJModelInputMapper.html) ( lInput, mKxJModel );
...
// instanciate a data source (it may be already done via lInput)_
DataProvider mDataProvider = new DataProvider( ... );
...
// main loop that reads each data row and applies the model on it_
while( mDataProvider.hasMoreRows() ) {
Object[] lResults = mKxJModel. **apply**( mMapper );
// store or print the results somewhere .
// here print results on standard output_
for( int i=0; i<lResults.length; i++ ) {
System.out.print( lResults[i].toString() );
if( i+1<lResults.length ) System.out.print(",");
}
System.out.println();
}
...
See KxJRT.KxJApplyWithMapWrapper
for example code.
The above code should be compiled with KxJRT.jar in it, and executed with both KxJRT.jar and the directory containing JavaKxModel.java in it.
Please note that the KxJRT.jar itself contains a sample program to read and score flat files.
Command line arguments: [-nonames] [-separator {sep}] [-out {file}] -model {model} -in {file}
-nonames
: don't look for variables names on first line.
-separator
: set field separator (default is comma).
-out
: set output file (default is standard output).
-model
: set Java model.
-in
: set input file to score.
Example:
To apply the sample model JavaKxModel.java
on Census.csv and store results in results.csv.
You should execute the following command lines:
javac -classpath KxJRT.jar ExportedModelInJava.java`
java -jar KxJRT.jar -model ExportedModelInJava -in Census.csv -out results.csv`
Note: The help is obtained by typing the below command:
java -jar KxJRT.jar -usage`