PDA

View Full Version : Java-Programm aus RPG aufrufen



Seiten : [1] 2

Ottersberg
09-06-10, 08:56
Moin,

Ziel des ganzen soll später mal ein RPG-Programm sein, in dem der Mitarbeiter bestimmte Dokumente auswählen kann und die er dann als Anhang einer E-Mail zugesendet bekommt und weiterleiten kann.
Zuerst wollte ich das per SNDDST machen, aber da kann man ja nur eine Datei im Anhang schicken. Dann wollte ich die Dateien zippen und dann per SNDDST verschicken.
Beim Suchen bin ich dann auf JavaMail gestoßen und hielt das für eine bessere Alternative. Aus dem RPG-Programm soll jetzt mein Java-Programm aufgerufen werden, dass dann die Erstellung und das Versenden der Mail übernimmt.

Inzwischen habe ich ein Test-Programm so weit runtergeschraubt, dass es erstmal eine E-Mail ohne Anhang schickt. Beim Aufruf des Programms kommt dann allerdings ein Fehler.
Wenn ich die main-Methode aktiviere und das Java-Programm über qsh aufrufe funktioniert es.

Sofern die Anweisung 80 im Fehler auf die Zeile im Java-Code verweist, ist das der Aufruf der Methode sendMail.

Kann mir jemand helfen?

Fehler:


Nachricht . . . : Anwendungsfehler. CEE9901 nicht überwacht durch QRNXUTIL
bei Anweisung 0000000080, Instruktion X'0000'.
Ursache . . . . : Die Anwendung wurde abnormal beendet, da eine Ausnahme
aufgetreten ist, die nicht behandelt wurde. Der Name des Programms, an das
die nicht behandelte Ausnahme gesendet wurde, ist QRNXUTIL QRNXJNI
chk_jni_excp. Das Programm wurde bei der/den HLL-Anweisung/en mit der/den
Nummer/n 0000000080 gestoppt, als die Nachricht gesendet wurde. Wird mehr
als eine Anweisungsnummer angezeigt, handelt es sich bei dem Programm um ein
optimiertes ILE-Programm. Durch die Optimierung kann keine einzelne
Anweisungsnummer festgelegt werden. Wird *N als Wert angezeigt, bedeutet
dies, dass ein reeller Wert nicht verfügbar war.

Joblog sagt:


Speicher-Offset X'00000000' oder X'00000000FFFFFFF0' liegt außerhalb der
aktuellen Grenze für Objekt P0258_859BOTTERSBERG704879.

Java-Code:


package javaMail;

import java.io.File;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class JavaMail {

// public static void main(String[] args) {
// JavaMail mail = new JavaMail();
// String[] dateien = new String[2];
// dateien[0]="C:\\fpRedmon.log";
// dateien[1]="C:\\PC.ini";
// mail.sendMail(
// "absender@test.local", "empfaenger@test.local",
// "Test", "Datei-Test");
//// mail.sendMailMitAnhang(
// "absender@test.local", "empfaenger@test.local",
// "Test", "Datei-Test", dateien);
// }

public JavaMail() {
super();

}

public void sendMailMitAnhang(
String absender, String empfaenger, String betreff,
String nachricht, String[] dateien)
{

}

public void sendMail(
String absender, String empfaenger,
String betreff, String nachricht)
{
try {
Properties props=new Properties();
Authenticator auth=new MailAuthenticator();
props.put("mail.smtp.host","IP-Adresse");
props.put("mail.smtp.auth","true");
Session session = Session.getDefaultInstance(props, auth);
Message message=new MimeMessage(session);
message.setFrom(new InternetAddress(absender));
message.setRecipient(
Message.RecipientType.TO,
new InternetAddress(empfaenger));
message.setSubject(betreff);
Multipart multipart = new MimeMultipart();
BodyPart body = new MimeBodyPart();
body.setText(nachricht);
multipart.addBodyPart(body);
message.setContent(multipart);
Transport.send(message);
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}

}

class MailAuthenticator extends Authenticator
{
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication("Benutzer","Passwort");
}
}



}


RPG-Code:


H main(Main)
H dftactgrp(*no)
H actgrp(*new)

************************************************** ********************
* newString constructor that accepts a byte array
* (an alphnumeric variable in RPG speak). It
* returns a string object.
************************************************** ********************
D newString PR O ExtProc(*JAVA:
D 'java.lang.String':
D *CONSTRUCTOR)
D Class(*JAVA:'java.lang.String')
D byes 9999A Const Varying


D javaMailSendMail...
D S O CLASS(*JAVA: 'javaMail.JavaMail' )

D sendMail PR EXTPROC(*JAVA : 'javaMail.JavaMail+
D ' : 'sendMail' )
D arg0 O CLASS(*JAVA : 'java.lang.String' )
D arg1 O CLASS(*JAVA : 'java.lang.String' )
D arg2 O CLASS(*JAVA : 'java.lang.String' )
D arg3 O CLASS(*JAVA : 'java.lang.String' )


D javaMailSendMailMitAnhang...
D S O CLASS(*JAVA: 'javaMail.JavaMail' )

D sendMailMitAnhang...
D PR EXTPROC(*JAVA : 'javaMail.JavaMail+
D ' : 'sendMailMitAnhang' )
D arg0 O CLASS(*JAVA : 'java.lang.String' )
D arg1 O CLASS(*JAVA : 'java.lang.String' )
D arg2 O CLASS(*JAVA : 'java.lang.String' )
D arg3 O CLASS(*JAVA : 'java.lang.String' )
D arg4 O DIM(99)
D CLASS(*JAVA : 'java.lang.String' )
D OPTIONS(*VARSIZE)

D absender S O CLASS(*JAVA : 'java.lang.String' )
D empfaenger S O CLASS(*JAVA : 'java.lang.String' )
D betreff S O CLASS(*JAVA : 'java.lang.String' )
D nachricht S O CLASS(*JAVA : 'java.lang.String' )

DMain PR extpgm('TEST')

PMain B
D PI
/free
absender = newString('absender@test.local');
empfaenger = newString('empfaenger@test.local');
betreff = newString('Test');
nachricht = newString('Datei-Test');
sendMail(javaMailSendMail:absender:empfaenger:betr eff:nachricht);
//sendMailMitAnhang(
// javaMailObj:absender:empfaenger:betreff:nachricht: dateien);
/end-free
P E

BenderD
09-06-10, 09:57
... ich kenne mich zwar nicht mit embedded Java in RPG aus, da ich sowas mit meinem OpenSource AppServer4RPG machen würde, aber ich finde in deinem RPG/Java Verschnitt keine Objekt Erzeugung für deine Java Mail Class.
Neben der schlechten Wartbarkeit (siehe dein Problem), freut sich über diesen Krumsch allenfalls IBM, da werden gegebenen Falls hunderte JVMs auf einer MAschine gestartet...

D*B

andreaspr@aon.at
09-06-10, 11:57
ich kenne mich zwar auch nicht so gut mit Java in RPG aus, probier aber mal das:

D sendMail PR O EXTPROC(*JAVA : 'javaMail.JavaMail+
D ' : 'sendMail' )
D arg0 O CLASS(*JAVA : 'java.lang.String' )
D arg1 O CLASS(*JAVA : 'java.lang.String' )
D arg2 O CLASS(*JAVA : 'java.lang.String' )
D arg3 O CLASS(*JAVA : 'java.lang.String' )

und du übergibst beim Aufruf von sendMail 5 Parameter. Erlaubt sind aber nur 4.

sendMail(javaMailSendMail:absender:empfaenger:betr eff:nachricht);



public void sendMail(
String absender, String empfaenger,
String betreff, String nachricht)

mk
09-06-10, 13:03
Hallo zusammen,

wie D*B geschrieben hat würde ich die Methoden nicht
direkt im RPG aufrufen. Jeder Aufruf würde das erzeugen
der JVM auf dem System verursachen. Wenn 50 Leute
das interaktiv aufrufen ????? Wieviel Hauptspeicher
hat denn deine Maschine ???

Also lieber:

* Java in einen eigenen Job auslagern ( Serverdienst )
( Warten auf DTAQ oder was auch immer )
mit RunJVA als SBMJOB

* die Anfragen vom RPG an den Dienst senden

* Ergebnis der Verarbeitung im RPG Programm auswerten


Damit sind die Aufrufe schön gekapselt. Und die JVM wird nur
von deinem Serverdienst benutzt.
Vielleicht kann Dir aber auch SendOsMail bei deiner Aufgabenstellung helfen.


Gruß
Michael

BenderD
09-06-10, 13:47
... genau das macht AppServer4RPG
RPG seitig SRVPGM zum Aufruf mit eventName und request, gibt response zurück
Java seitig schreibt man einen Eventhandler, der über properties eingeklinkt wird
Der Transfer über DataQ, bereitstellen von Context und Session ist RPG und Java seitig fix und fertig vorhanden.
BTW: wenn mein Transparent Gateway from DB2/400 to JDBC fertig ist (basiert auch auf AppServer4RPG), kann man das auch über Java stored procedures machen, dann übernimmt SQL die notwendigen Parameteranpassungen.

D*B





* Java in einen eigenen Job auslagern ( Serverdienst )
( Warten auf DTAQ oder was auch immer )
mit RunJVA als SBMJOB

* die Anfragen vom RPG an den Dienst senden

* Ergebnis der Verarbeitung im RPG Programm auswerten


Damit sind die Aufrufe schön gekapselt. Und die JVM wird nur
von deinem Serverdienst benutzt.

Ottersberg
09-06-10, 14:08
ich kenne mich zwar auch nicht so gut mit Java in RPG aus, probier aber mal das:
D sendMail PR O EXTPROC(*JAVA : 'javaMail.JavaMail+
D ' : 'sendMail' )

RNF3951E Das Schlüsselwort CLASS ist für Datenart O erforderlich.


und du übergibst beim Aufruf von sendMail 5 Parameter. Erlaubt sind aber nur 4.

Wenn die Java-Methode nicht static ist, muss als erster Parameter eine Objekt-Instanz übergeben werden.

Ich habe die Methode übrigens mal static gemacht und dann auch im RPG bei der Definition STATIC mit hinzugefügt. Jetzt läuft das Programm durch. Die Mail kommt zwar nicht an, aber das scheint jetzt zumindest am Java-Programm zu liegen bzw. vermutlich an falschen Übergabewerten.




wie D*B geschrieben hat würde ich die Methoden nicht
direkt im RPG aufrufen. Jeder Aufruf würde das erzeugen
der JVM auf dem System verursachen.


... genau das macht AppServer4RPG
RPG seitig SRVPGM zum Aufruf mit eventName und request, gibt response zurück
Java seitig schreibt man einen Eventhandler, der über properties eingeklinkt wird


Es ist das erste Mal, dass wir versuchen RPG und Java zu verbinden. Eigentlich wollte ich generell erstmal was Einfaches am Laufen haben. Ich hatte mir vorhin schon den AppServer4RPG heruntergeladen aber dann das Gefühl ich würde mit Kanonen auf Spatzen schießen, da ich ja nur eine blöde kleine Mail haben will. Michael überzeugt mich aber, dass doch damit zu versuchen.

mk
09-06-10, 14:46
Hi Dieter,


genau das macht AppServer4RPG

das weiß ich doch, und seitdem Du mir das mal erklärt hast
habe ich auch alle Javaprozesse auf einen Dienst
umgestellt.

Damit laufen die verschiedenen Umgebungen RPG , Java
und auch aus PHP die Sachen sehr zuverlässig.

Insbesondere bei der Webentwicklung werden solche
Aufrufe häufig benutzt.

Gruß
Michael

Ottersberg
10-06-10, 11:24
Wen es interessiert hier der lauffähige Code.
Bin aber bereits am Probieren, das mit dem AppServer zu machen.



H main(Main)
H dftactgrp(*no)
H actgrp(*new)

************************************************** ********************
* newString constructor that accepts a byte array
* (an alphnumeric variable in RPG speak). It
* returns a string object.
************************************************** ********************
D newString PR O ExtProc(*JAVA:
D 'java.lang.String':
D *CONSTRUCTOR)
D Class(*JAVA:'java.lang.String')
D byes 9999A Const Varying


D sendMail PR EXTPROC(*JAVA : 'javaMail.JavaMail+
D ' : 'sendMail' )
D STATIC
D arg0 O CLASS(*JAVA : 'java.lang.String' )
D arg1 O CLASS(*JAVA : 'java.lang.String' )
D arg2 O CLASS(*JAVA : 'java.lang.String' )
D arg3 O CLASS(*JAVA : 'java.lang.String' )

D sendMailMitAnhang...
D PR EXTPROC(*JAVA : 'javaMail.JavaMail+
D ' : 'sendMailMitAnhang' )
D STATIC
D arg0 O CLASS(*JAVA : 'java.lang.String' )
D arg1 O CLASS(*JAVA : 'java.lang.String' )
D arg2 O CLASS(*JAVA : 'java.lang.String' )
D arg3 O CLASS(*JAVA : 'java.lang.String' )
D arg4 O DIM(99)
D CLASS(*JAVA : 'java.lang.String' )
D OPTIONS(*VARSIZE)

D absender S O CLASS(*JAVA : 'java.lang.String' )
D empfaenger S O CLASS(*JAVA : 'java.lang.String' )
D betreff S O CLASS(*JAVA : 'java.lang.String' )
D nachricht S O CLASS(*JAVA : 'java.lang.String' )
D dateien S O DIM(99)
D CLASS(*JAVA : 'java.lang.String' )

DMain PR extpgm('TEST')

PMain B
D PI
/free

absender = newString('absender@test.local');
empfaenger = newString('empfaenger@test.local');
betreff = newString('Test');
nachricht = newString('Datei-Test');
dateien(1) = newString('/Java/JavaMail.jar');
dateien(2) = newString('/Java/activation.jar');
dateien(3) = newString('/Java/mail.jar');
sendMail(absender:empfaenger:betreff:nachricht);
sendMailMitAnhang(
absender:empfaenger:betreff:nachricht:dateien);
dsply ('Ende');
/end-free
P E




package javaMail;

import java.io.File;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class JavaMail {

public static void main(String[] args) {
String absender = args[0];
String empfaenger = args[1];
String betreff = args[2];
String nachricht = args[3];
String[] dateien = new String[1];
dateien[0] = args[4];
sendMail(absender, empfaenger, betreff, nachricht);
sendMailMitAnhang(
absender, empfaenger, betreff,
nachricht, dateien);
}

public static void sendMailMitAnhang(
String absender, String empfaenger, String betreff,
String nachricht, String[] dateien)
{
File[] files = new File[dateien.length];
for (int i=0; i<dateien.length; i++)
{
if (dateien[i]!=null)
{
files[i] = new File(dateien[i]);
}
}
try {
Properties props=new Properties();
props.put("mail.smtp.host","IP-Adresse Mail Server");
Session session = Session.getInstance(props);
Message message=new MimeMessage(session);
message.setFrom(new InternetAddress(absender));
message.setRecipient(
Message.RecipientType.TO,
new InternetAddress(empfaenger));
message.setSubject(betreff);
Multipart multipart = new MimeMultipart();
BodyPart body = new MimeBodyPart();
body.setText(nachricht);
multipart.addBodyPart(body);
for (int i=0; i<files.length; i++)
{
if (files[i]!=null)
{
BodyPart file = new MimeBodyPart();
DataSource source = new FileDataSource(files[i]);
file.setDataHandler(new DataHandler(source));
file.setFileName(files[i].getName());
multipart.addBodyPart(file);
}
}
message.setContent(multipart);
Transport.send(message);
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}

}

public static void sendMail(
String absender, String empfaenger,
String betreff, String nachricht)
{
try {
Properties props=new Properties();
props.put("mail.smtp.host","IP-Adresse Mail Server");
Session session = Session.getInstance(props);
Message message=new MimeMessage(session);
message.setFrom(new InternetAddress(absender));
message.setRecipient(
Message.RecipientType.TO,
new InternetAddress(empfaenger));
message.setSubject(betreff);
Multipart multipart = new MimeMultipart();
BodyPart body = new MimeBodyPart();
body.setText(nachricht);
multipart.addBodyPart(body);
message.setContent(multipart);
Transport.send(message);
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}

Ottersberg
10-06-10, 11:33
Moin Dieter,

ich habe den AppServer4RPG soweit eingerichtet und erstmal in einer QShell gestartet.
Beim Call des Test-Programms kommt dann die Fehlermeldung:
ClassNotFoundException: de.bender_dv.sqlgateway.application.Confirmer

Ich hab mal in die jar-Datei geguckt und die Klasse und sogar der ganze Ornder sqlgateway ist nicht vorhanden. Soll das so, damit das extra auf einen Fehler läuft?

BenderD
10-06-10, 11:49
... ne das soll nicht so, da ist wahrscheinlich der Eintrag in der global.properties inkonsistent mit dem Rest; ändere den mal auf de.bender_dv.test.Confirmer ab, dann sollte das Testteil tun. Hat aber mit der Funktionalität des AppServers nix zu tun.

Was dein RPG Teil angeht, das mit dem static zieht, weil dann kein Objekt erzeugt werden muss. Eigentlich würde man mit deiner Java class analog zu String verfahren, sprich einen *Constructor deklarieren und vor dem Methodenaufruf mit diesem das Object erzeugen, das dann beim Methodenaufruf als erster Parameter mitgegeben wird.

D*B


Moin Dieter,

ich habe den AppServer4RPG soweit eingerichtet und erstmal in einer QShell gestartet.
Beim Call des Test-Programms kommt dann die Fehlermeldung:
ClassNotFoundException: de.bender_dv.sqlgateway.application.Confirmer

Ich hab mal in die jar-Datei geguckt und die Klasse und sogar der ganze Ornder sqlgateway ist nicht vorhanden. Soll das so, damit das extra auf einen Fehler läuft?