Complete Java Example

This section examines a simple but complete Java program that uses SAS Micro Analytic Service to call a simple DS2 package method. Comments within the body of the code explain each step.
The example code performs the following sequence of steps:
  1. Starts SAS Micro Analytic Service
  2. Creates a user context
  3. Creates a module context
  4. Creates a new revision (DS2 package is compiled)
  5. Checks for compiler messages and prints any that are found to the console
  6. Retrieves and prints metadata about the DS2 package
  7. Prepares method arguments
  8. Calls a method
  9. Retrieves and prints results
  10. Prepares a different set of argument values
  11. Calls a different method of the package
  12. Retrieves and prints results of the second call
  13. Shuts down SAS Micro Analytic Service
The console output from running the example follows the source code.
package com.sas.mas.test;

import java.util.ArrayList;

import com.sas.mas.TkLight;
import com.sas.mas.tksfParmdef;
import com.sas.mas.tksfValues;
import com.sas.mas.TkLight.Language;
import com.sas.mas.jni.tksfjni;

public class SimpleDS2Example {

	/*
	   This is a simple DS2 package with two methods.  The code could have
	   been read from a file, but is included here for easy reference.

	   The source code starts with "ds2_options sas" and ends with
	   with "endpackage."  This pattern should be used with all DS2 to be
	   published to SAS Micro Analytic Service.

	   Note: each source code line ends with a line-end character.
	   This best practice facilitates use of the line numbers included in
	   compiler messages, making it easier to locate syntax errors.
	*/
	static String DS2 =
"ds2_options sas;                                                            \n" +
"package simple_example /overwrite=yes;                                      \n" +
"                                                                            \n" +
"   method str2double (char(12) numericString, in_out double number);        \n" +
"      number = put( numericString, 8.0);                                    \n" +
"      /* Include an undeclared variable to illustrate a compiler warning */ \n" +
"      anotherNumber = number;                                               \n" +
"   end;                                                                     \n" +
"                                                                            \n" +
"   method flip_string(varchar(32767) in_string, in_out varchar out_string); \n" +
"      /* Reverse the input string and set in output string */               \n" +
"      out_string=reverse(in_string);                                        \n" +
"   end;                                                                     \n" +
"                                                                            \n" +
"endpackage;                                                                 \n";

	/**
	 * @param parms
	 */
	public static void main(String[] parms) {
		int		 rc;
		String   stringToReverse    = new String("This is a test...");
		String   stringToConvert	= new String("0.9997");
		long     userCtx			= -1;
		long     moduleCtx			= -1;

		// Start SAS Micro Analtyic Service with four threads and
		// no logging configuration file location (null second argument)
		int threads = 4;
		TkLight tk = new tksfjni(threads, null);

		System.out.println("*** Simple example of using SAS Micro Analytic Service ***");

		// Create a user context.
		userCtx = tk.newUserContext("A user context");
		if (userCtx <= 0) {
			System.out.println("   User context creation failed.");
			return;
		}
		else {
			System.out.println("   User context created at " +
					tk.getUserContextCreationDateTime(userCtx) + ".");
		}

		/* Create a module context.
			This module context is owned by the user context just created.
			The language is specified as DS2. Therefore, all revisions
         of the module must be DS2.
			The module is named for the DS2 package it represents, or
			 "simple_example" in this case.
			Pass null for the last argument, which specifies the default options.
		 */
		moduleCtx = tk.newModuleContext(userCtx,
										Language.DS2,
										"simple_example",
										null);
		if (moduleCtx <= 0) {
			System.out.println("   Module context creation failed.");
			tk.term();
			return;
		}
		else {
			System.out.println("   Module context created at " +
					tk.getModuleContextCreationDateTime(moduleCtx) + ".");
		}

		/* Publish the DS2 to SAS Micro Analytic Service by calling newRevision().
			Pass in the module context ID, the source code String, and an
			optional description.
			Pass null for the fouth argument, a list of entry points, which
			is only used for C modules.
			Pass null for the last argument, which specifies default options.
		 */
		int revision = tk.newRevision(moduleCtx, DS2,
				"A simple DS2 example to illustrate SAS Micro Analytic Service usage.",
				null, null);
		if (revision <= 0) {
			System.out.println("   Compilation failed");
			String[] messages = tk.getCompilationMessages(moduleCtx);
			if (messages.length > 0) {
				System.out.println("   Compiler messages:");
				for (String msg : messages) {
					System.out.println("         " + msg);
				}
			}
			System.out.println("   Revision creation failed.");
			tk.term();
			return;
		}
		else {
			System.out.println("   Revision " + revision + " created at " +
						tk.getRevisionCreationDateTime(moduleCtx, revision) 
+ ".");
		}

		System.out.println("   DS2 Package: " +
							tk.getModuleContextDisplayName(moduleCtx));

		/* Even successful compilations can produce warning messages from the compiler.
		   The undeclared variable included in the source code generates such a
		   warning. However, it will not prevent the code from publishing and executing
		   properly.
		 */
		String[] messages = tk.getCompilationMessages(moduleCtx);
		if (messages.length > 0) {
			System.out.println("      Compiler messages:");
			for (String msg : messages) {
				System.out.println("         " + msg);
			}
		}

		/* Once published, SAS Micro Analtic Service can be queried for information
        about the revision. Here you are asked for the inputs to the str2double
        method. Parameter metadata is represented by class tksfParmdef.
		 */
		ArrayList<tksfParmdef> inputs = tk.getStepInputs(moduleCtx,
														 revision,
														 "str2double");
		System.out.println("   Input arguments to method 'str2double':");
		for (tksfParmdef p : inputs) {
			System.out.println("   Input name: '" + p.name + "' type: " + 
      p.getType());
		}

		/* Setup arguments to call method "str2double", which has one String input and
		   one double output.
        Note: Setters are being used with implicit indices.
		 */
		int        numArgs   = 2;
		int        numInputs = 1;
		tksfValues args = new tksfValues(numArgs, numInputs); // DS2 method arguments
		args.setString(stringToConvert);
		args.setOutDouble();
		String methodName = "str2double";

		// Execute the DS2 package method "str2double"
		rc = tk.execute(userCtx, moduleCtx, revision, methodName, args);
		if (rc != 0) {
			System.out.println("   Bad return code from execute:" + rc);
			if (rc == 29) {
				System.out.println("   Exception occurred during execution of " +
						      methodName + " in the TK environment.");
			}
			tk.term();
			return;
		}
		else {
			// Print results (Getters are being used with explicit indices.)
			System.out.println("   Results of calling str2double:");
			System.out.println("      Input String:            " + args.getString(0));
			System.out.println("      Output double (rounded): " + args.getDouble(1));
		}

		// Setup arguments to call the method "flip_string", which has one String input
		// and one double output. Setters are being used with implicit indices.
		numArgs   = 2;
		numInputs = 1;
		args = new tksfValues(numArgs, numInputs);		// DS2 method arguments
		args.setString(stringToReverse);
		args.setOutString();
		methodName = "flip_string";

		// Execute the DS2 package method "flip_string"
		rc = tk.execute(userCtx, moduleCtx, revision, methodName, args);
		if (rc != 0) {
			System.out.println("   Bad return code from execute:" + rc);
			if (rc == 29) {
				System.out.println("   Exception occurred during execution of " +
						      methodName + " in the TK environment.");
			}
			tk.term();
			return;
		}
		else {
			// Print results (Getters are being used with explicit indices.)
			System.out.println("   Results of calling flip_string:");
			System.out.println("      Input String:  " + args.getString(0));
			System.out.println("      Output String: " + args.getString(1));
		}
		System.out.println("*** Simple DS2 example complete ***\n");
		// Shutdown
		tk.term();
	}
}
Here is the console output from running the example code above:
*** Simple example of using SAS Micro Analytic Service ***
   User context created at Tue Apr 07 17:50:28 EDT 2015.
   Module context created at Tue Apr 07 17:50:28 EDT 2015.
   Revision 1 created at Tue Apr 07 17:50:28 EDT 2015.
   DS2 Package: simple_example
      Compiler messages:
         Line 6: No DECLARE for assigned-to variable anothernumber;
         creating it as a global variable of type double.
   Input arguments to method 'str2double':
   Input name: 'numericString' type: string_t
   Results of calling str2double:
      Input String:                                         0.9997
      Output double (should round to nearest whole number): 1.0
   Results of calling flip_string:
      Input String:  This is a test...
      Output String: ...tset a si sihT
*** Simple DS2 example complete ***