Community deutschsprachiger SAS-Anwender und -Programmierer

Antworten
Dies ist eine offene Gruppe. Melden Sie sich an und klicken Sie auf die Schaltfläche „Gruppe beitreten“, um Mitglied zu werden und damit zu beginnen, Beiträge in dieser Gruppe zu veröffentlichen.
Highlighted
Contributor
Beiträge: 26
Aufruf von Java aus SAS/SCL und SAS Macro geht nicht? Geht doch!

Hallo,

bei Xing entdeckt:

https://www.xing.com/communities/posts/aufruf-von-java-aus-sas-strich-scl-und-sas-macro-geht-nicht-g...

Der Xing-Beitrag enthält aber auch nur diesen Link:

https://www.bde-gmbh.de/tipps-tricks/sas/call-java-methods-from-sasscl-sasmacro-and-of-course-from-a...

 

Es sah interessant aus, vielleicht ist es für den ein oder die andere nützlich.

 

Viele Grüße

Hans

Contributor
Beiträge: 21
Re: Aufruf von Java aus SAS/SCL und SAS Macro geht nicht? Geht doch!

Hallo Hans,

 

in SAS 9.4 gibt es die Funktion dusobul(), die es ermöglicht, SAS Base-Code in einem zweiten Thread auszuführen. Mit dieser Methode können Makro-Methoden (als Wrapper) geschrieben werden, die einerseits Base-Code abschicken, andererseits aber einen Rückgabewert haben. So kann sowohl aus der Makro-Sprache als auch aus der SCL indirekt auf Java-Objekte zugegriffen werden.

 

Hier ein Beispiel mit einer ganz einfachen Java-Klasse:

 

public class Test001 {

  public String lastName = "#no lastname given#";
  public String firstName = "#no firstname given#";
  public int    age = 0;

  public String toString() {
    return ("this is " + firstName + " " + lastName + ", age of " + age);
  }

  public static void main (String[] args) {
    Test001 obj = new Test001();
    obj.lastName  = "TestLastName";
    obj.firstName = "TestFirstName";
    obj.age       = 999;
    System.out.println(obj);
  }
}

Die Klasse muss kompiliert und der CLASSPATH entsprechend gesetzt werden, damit SAS die Klasse finden kann.

 

 

Im folgenden Makro wird ein String mit dem eigentlichen Data Step gebildet: Das Java Objekt wird instantiiert und die Methode aufgerufen. Der Rückgabewert der Methode wird in eine lokale Makro-Variable geschrieben. Dann wird das Programm mit %Sysfunc(dosubl()) ausgeführt und das Ergebnis wird als Rückgabewert der Makro-Funktion in den Input-Stack zurückgeschrieben.

Der Aufruf erfolgt dann direkt im %Put-Statement, so dass der Rückgabewert in das LOG geschrieben wird.

 

 

%Macro java(class,method,type=String);
  %Local pgm rc result;
  %Let pgm=%Str(
  Data _Null_;
    Length string $256;
    Declare javaObj obj1("Test001");
    rc = obj1.call&type.Method("&method",string);
    obj1.delete();
    Call Symput("result",string);
  Run;
  );
  %Let rc = %Sysfunc(dosubl(&pgm));
  &result
%Mend; %Put NOTE: Using java in a macro: %java(Test001,toString,type=String);

Ergebnis ist:

479  %Put NOTE: Using java in a macro: %java(Test001,toString,type=String);
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


NOTE: Using java in a macro: this is #no firstname given# #no lastname given#, age of 0

 

In der SCL kann der Data Step natürlich in einem Submit-Block direkt aufgerufen werden, hier ist aber auch dosubl() möglich oder der Zugriff auf das schon vorhandene Makro mit Hilfe von resolve(). Hier Beispiele für die beiden letzteren Varianten:

Init:                                                                                                                                   
  Dcl char(1024) pgm string, num rc;                                                                                                    
                                                                                                                                        
  pgm = '%java(Test001,toString,type=String)';                                                                                           
                                                                                                                                        
  string = resolve(pgm);                                                                                                                 
                                                                                                                                        
  put "NOTE: SCL Aufruf des Makros mit resolve() " string;                                                                                                                                                                                                          
                                                                                                                                        
  pgm = cats("Data _Null_;",                                                                                                            
             "Length string $256;",                                                                                                     
             "Declare javaObj obj1(""Test001"");",                                                                                      
             "rc = obj1.callStringMethod(""toString"",string);",                                                                        
             "obj1.delete();",                                                                                                          
             "Call Symput(""result"",string);",                                                                                         
             "Run;");                                                                                                                   
                                                                                                                                        
  Call Symput("result","-1");                                                                                                           
  rc = dosubl(pgm);                                                                                                                     
                                                                                                                                        
  string = symget("result");                                                                                                            
                                                                                                                                        
  Put "NOTE: SCL direkter Aufruf von dosubl() " string;                                                                                 
                                                                                                                                        
  Call Symdel("result");                                                                                                                
                                                                                                                                        
Return;

 

Auch hier die Ergebnise:

 

NOTE: Compiling TEST.SCL.
NOTE: Code generated for TEST.SCL. Code size=1440.

NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


NOTE: SCL Aufruf des Makros mit resolve()  this is #no firstname given# #no lastname given#, age of 0
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


NOTE: SCL direkter Aufruf von dosubl()  this is #no firstname given# #no lastname given#, age of

Eine andere Frage ist allerdings, ob das ganze performant ist, denn für jeden Methodenaufruf muss die Java-Klasse neu instantiiert werden, und für Methoden mit Parametern muss dann auch entsprechender Aufwand betrieben werden.

 

Vielleicht ist an dieser Stelle die ebenfalls neue Prozedur Proc Lua interessant, die eine direkte Schnittstelle zu der hochperformanten Programmiersprache LUA anbietet (Wikipedia, SGF 2015 Paper). hier geht SAS den umgekehrten Weg und stellt in Proc Lua die SAS-Funktionen direkt zur Verfügung.

 

Wie immer bietet SAS also eine Vielzahl von Möglichkeiten - und mit jeder neuen (Sub-) Version kommen neue hinzu  ;-)

 

Viele Grüße,

 

Grischa