Autor Thema: Java OutOfMemoryError  (Gelesen 15790 mal)

Offline birdy

  • Frischling
  • *
  • Beiträge: 37
  • Geschlecht: Weiblich
  • Keep smiling!
Java OutOfMemoryError
« am: 22.04.05 - 08:25:55 »
Hallo,

mein Java-Agent verursacht immer wieder nen OutOfMemoryError, wenn er mehrmals hintereinander läuft.

Der Agent wird aus einer Notes-DB gestartet, stellt über JDBC eine Connection zur DB2 her und liest dort Daten aus. In der Notes-DB wird dann ein Dokument erstellt und die Daten dort eingelesen. Das Ganze funktioniert im Grunde, hatte mich aber wohl zu früh gefreut.

Nach ca. 7 Aufrufen des Agenten kommt es zu einem Error in Notes:

NotesError: JVM: Versuch, den Java Agent-Anhang zu öffnen, ist fehlgeschlagen.

In der Java-Konsole steht folgender Error:

java.lang.OutOfMemoryError

Kenne mich mit Java leider gar nicht gut aus und bin schon froh, dass ich den Agenten überhaupt hinbekommen hab.

Hier ist der Code:

Code

import lotus.domino.*;
import java.sql.*;
import java.io.*;
import java.util.*;

public class JavaAgent extends AgentBase {

	public void NotesMain() {

		try {
			Session session = getSession();
			AgentContext agentContext = session.getAgentContext();
			Database db = agentContext.getCurrentDatabase();
			Document doc = agentContext.getDocumentContext();
			Document profildok = db.getProfileDocument("Profildok", "");
			
			// Variablen deklarieren
			String l_Feld1;
			String l_Feld2;
			String l_Feld3;
			boolean rc;
			
			// Nr. aus Profildokument auslesen
			l_Feld1 = profildok.getItemValueString("Nr");
			
			
			PrintWriter pw = getAgentOutput();
			Connection con=null;
			Statement stmt=null;
			ResultSet rs=null;
			
			String JDBCDriverName="Treibername";
			String system="Pfad";
			String user = "username"; 
			String pwd = "passwort"; 

			DriverManager.registerDriver((Driver) Class.forName(JDBCDriverName).newInstance());
			con = DriverManager.getConnection(system,user,pwd);
			stmt = con.createStatement();
			
						
			// Abfrage
			String sql = "SELECT ...;
			rs = stmt.executeQuery(sql);
			
			// prüfen ob rs leer ist
			rc = rs.next();
				if (rc) {
			// Felder auslesen
			l_Feld1 = rs.getString(1);
l_Feld2 = rs.getString(2);
l_Feld3 = rs.getString(3);
										}
		else {
										l_Feld1 = "";
		l_Feld2 = "";
		l_Feld3 = "";
					
			};							
			if (z) {
			// neues Dokument anlegen		
			doc = db.createDocument();
			doc.appendItemValue("Form", "Dok");
			System.out.println("Dok. angelegt.");
			
			// Felder im Dokument füllen
			doc.appendItemValue("NFeld1", l_Feld1);
			doc.appendItemValue("NFeld2", l_Feld2);
			doc.appendItemValue("NFeld3", l_Feld3);
			// Dokument speichern
			doc.save(true, true);
			}
			else {
							}

			// Close statement and connection
			rs.close();
			stmt.close();
			con.close();
			} 
			catch (Exception e) {
				e.printStackTrace();
				}
	}
}



Bin für jeden Tipp dankbar.

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re: Java OutOfMemoryError
« Antwort #1 am: 22.04.05 - 08:43:29 »
Hallo!

Ich empfehle dir auf jeden Fall das Datenbankobjekt in deinem Agent mit db.recycle() zu löschen.

Zur kurzen Erklärung, die Notes Java Klassen sind nur ünne Hüllenklassen für das darunterliegende C++ Api. das heisst, wenn du in Java ein DominoDatenbankObjekt erstellst, wird im Hintergrund zusätzlich zu deinem Java Objekt auch ein C++ Objekt erstellt. Diese C++ Objekte werden aber vom Java Garbage collector nicht gesehen und daher auch nicht automatisch bereinigt. Deshalb ist es wichtig wenn du in Domino Java Programmen oder Agenten Domino Backendobjekte verwendest die auch wieder ordentlich bereinigst. Dafür hat jedes Objekt die recycle Methode.

Hört sich schlimmer an, als es ist denn die recycle Methode hat die praktische Funktion, das wenn du ein Objekt bereinigst, sämtliche abhängigen Objekte mit recycelt werden. Das heisst, wenn du aus einem Datenbankobjekt eine View oder ein Dokument erstellst, dann werden auch die bereinigt wenn du das Datenbankobjekt recycelst. Deshalb ist es in Java Programmen (nicht jedoch Agenten) Best Practise zum Schluß auf jeden Fall die session zu recyceln. In Java Agenten ist es jedoch so, dass di Session die Session deines NotesClients ist und wenn du die recycelst, wünsche ich dir gleich viel Spaß, denn dann treten die seltsamsten Phänomene auf.

Ich hoffe, das hilft dir falls nicht einfach nochmal fragen.

Grüße

Ralf

P.S. Eventuell kann das wer von den Mods ins Java Forum verschieben.
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Marinero Atlántico

  • Gast
Re: Java OutOfMemoryError
« Antwort #2 am: 22.04.05 - 09:07:33 »
Versuch erstmal Ralfs tipp.
Also:

am Schluss:
Code
con.close();
db.recycle();
}
catch (Exception e) {
e.printStackTrace();
if (con != null) con.close(); // was anderes, aber wo du schon dabeibist.
if (db != null) db.recycle();
}

OBEN:
Deklaration von con und db oberhalb des trys schieben:
Code
Database db = null;
Connection con = null;
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// auskomentiert Database db = agentContext.getCurrentDatabase();
Document doc = agentContext.getDocumentContext();
Document profildok = db.getProfileDocument("Profildok", "");
[... weiter unten]
PrintWriter pw = getAgentOutput();
// auskommentiert : Connection con=null;

Desweiteren kann das errorhandling verbessert werden, aber dazu später mehr.

Es liegt nicht an Java. Die Integration von Java und Notes ist ein bischen ätzend. Ich  programmiere pro Woche durchschnittlich 20 neue SQLConnections low level oder mit wechselnden Frameworks, Tools (Ant, ibatis sqlmaps, springframework-jdbc, hibernate, ejb) und laufe da einfach nicht in eine OutOfMemory.  >:(

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re: Java OutOfMemoryError
« Antwort #3 am: 22.04.05 - 09:21:26 »

Es liegt nicht an Java. Die Integration von Java und Notes ist ein bischen ätzend. Ich programmiere pro Woche durchschnittlich 20 neue SQLConnections low level oder mit wechselnden Frameworks, Tools (Ant, ibatis sqlmaps, springframework-jdbc, hibernate, ejb) und laufe da einfach nicht in eine OutOfMemory. >:(

War ich früher auch der Meinung, aber ganz richtig ist es nicht. Es liegt insofern an Java, das Java nicht gewährleistet, dass die finalize Methode eines Objekts aufgerufen wird, wenn das Objekt garbage collected wird. Wenn du also mit Native peers arbeitest, dann hast du dieses recycle() Problem in irgendeiner Form. So was ähnliches gibt es meines Wissens ja auch bei SWT.

Ich hoffe birdy gerhört nicht zu der Sorte die nie weider etwas posten nach dem Sie eine Frage gestellt haben.

Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline birdy

  • Frischling
  • *
  • Beiträge: 37
  • Geschlecht: Weiblich
  • Keep smiling!
Re: Java OutOfMemoryError
« Antwort #4 am: 22.04.05 - 09:44:09 »
Keine Sorge, lass mich so schnell nicht vertreiben ;-)

Also danke erstmal für eure Tipps. Das mit dem recycle hab ich eingebaut, hat leider nicht geholfen.

Code
profildok.recycle();
			doc.recycle();
			db.recycle();
			agentContext.recycle();
			session.recycle();

Das Deklarieren von Database und Connection hab ich oberhalb des trys platziert. Allerdings bekomme ich zu den beiden If-Clauses am Ende des Codes einen Fehler bei der Kompilierung ???

Fehler:
Exception java.sql.SQLException must be caught, or it must be declared in the throws clause of this mehtod.

Code
public void NotesMain() {
		
		Database db = null;
		Connection con = null;

		try {
			Session session = getSession();
			AgentContext agentContext = session.getAgentContext();
			db = agentContext.getCurrentDatabase();
			Document doc = agentContext.getDocumentContext();
			Document profildok = db.getProfileDocument("Profildok", "");

Code
catch (Exception e) {
				e.printStackTrace();
			if (con != null) con.close();
			if (db != null) db.recycle();
				}


Hat mich bisher leider nicht weitergebracht.
Fällt euch vielleicht noch was ein?

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re: Java OutOfMemoryError
« Antwort #5 am: 22.04.05 - 10:14:27 »
Hallo!

Bitte Posts genau lesen!!! ich habe bereits geschrieben, dass man die Session in Agenten nicht recyceln darf. Nur die Objekte recyceln die du selbst erstellt hast. Die Session in Agenten ist eine Session die von Lotus Notes kommt.

hier ein Auszug aus der Agent FAQ auf Notes.net

For any agent even when you need recycle for some things you don't ever need to recycle these two things:
agentContext.recycle();
session.recycle();

Zu deinen Compile Problemen. Jede Methode eines DominoBackend Objekts wirft eine Notesexception im Fehlerfalle und muß daher in einer Try catch Klammer sein.

Übrigens, habe offensichtlich einen Fehler gemacht, du darfst in deinem Fall auch die Datenbank nicht recyceln, da diese aus dem AgentContext kommt.  Recyceln darf man nur Objekte die man selbst erstellt hat und wenn man im AgentContext auf currentDatabase zugreift, bekommt man keine neue Datenbank sondern die im AgentContext bestehende Datenbank.

Hoffe das hilft, übrigens welche Version setzt du ein und läuft der Agent auf dem Client oder Server?

Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline birdy

  • Frischling
  • *
  • Beiträge: 37
  • Geschlecht: Weiblich
  • Keep smiling!
Re: Java OutOfMemoryError
« Antwort #6 am: 22.04.05 - 10:35:42 »
Sorry Ralf, war auch im IBM-Forum unterwegs und da hat jemand auch agentContext und session recycelt, deshalb dachte ich kann ja nicht schaden.


Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re: Java OutOfMemoryError
« Antwort #7 am: 22.04.05 - 10:37:05 »
No Problem, wie schaut es aus, hast du erfolg gehabt?

Sonst hätte ich noch weitere Ideen.

Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline birdy

  • Frischling
  • *
  • Beiträge: 37
  • Geschlecht: Weiblich
  • Keep smiling!
Re: Java OutOfMemoryError
« Antwort #8 am: 22.04.05 - 10:45:31 »
Der Agent läuft auf dem Client und die Notes-Verion ist 6.5.2

Das Problem besteht immer noch. :-\

Marinero Atlántico

  • Gast
Re: Java OutOfMemoryError
« Antwort #9 am: 22.04.05 - 10:48:14 »
Oh ich dummy.

Fehler:
Exception java.sql.SQLException must be caught, or it must be declared in the throws clause of this mehtod.

Bitte ersetze im catch.
Code
catch (Exception e) {
				e.printStackTrace();

			if (con != null) 
try {
con.close();
} catch (SQLException sqle) {
// einer der wenigen Fälle, wo leere catch - clauses ok sind. IST SONST EINE SEHR SCHLECHTE IDEE!!!
}
			if (db != null) db.recycle();
				}


Hat mich bisher leider nicht weitergebracht.
Fällt euch vielleicht noch was ein?

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re: Java OutOfMemoryError
« Antwort #10 am: 22.04.05 - 10:48:38 »
Ok, dann gehe ich davon aus, dass es nicht am C++ Backend liegt, das haben wir ja jetzt ausgeschaltet, eventuell läuft deine Garbage Collection nicht richtig. Setz mal alle größeren Objekte in deinen Agent zum Schluß auf null.

Also:

rs=null;
stmt=null;
con=null;

usw.
und

dann bau noch

System.gc();

Das sollte die Garbagge Collection der Notes Jvm auslösen. Ich hoffe, deine Probleme sind dann behoben. Noch eine Frage, wie hast du denn den JDBC Treiber eingebunden? Direkt importiert, oder in JavaUserClasses in der Notes.ini?


Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline qojote

  • Aktives Mitglied
  • ***
  • Beiträge: 229
  • I love YaBB 1G - SP1!
Re: Java OutOfMemoryError
« Antwort #11 am: 22.04.05 - 11:00:39 »
Hi,

ich hatte daselbe Problem wenn ich den die Sachen in den Agent als Attachement gepackt habe.
Auch der Anwendungsfall ist der selbe JDBC auf eine DB2.
Einziger Unterschied ich habe einen Backendagent auf dem Server genutzt
Ich habe jetzt meine jt400.jar die ich für den JDBC Zugriffbrauche auf den Server gelegt und habe seitdem keine Probleme mehr.

Gruß
Qojote

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re: Java OutOfMemoryError
« Antwort #12 am: 22.04.05 - 11:14:10 »
Genau war auch meine Vermutung. Blöd wäre es nur wenn er es am Client braucht, denn dann muß er sich was ein fallen lassen wie er die JT400.jar auf die Clients deployed warten wir mal ab.

Grüße

Ralf
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Offline birdy

  • Frischling
  • *
  • Beiträge: 37
  • Geschlecht: Weiblich
  • Keep smiling!
Re: Java OutOfMemoryError
« Antwort #13 am: 22.04.05 - 11:39:19 »
Hallo Ralf,

hab alles auf null gesetzt am Ende und System.gc() eingebaut, ohne Erfolg.

Hallo qjote,

der Treiber für die AS400 liegt auf dem Server, daran kanns also auch nicht liegen.

Danke trotzdem für alle eure Tipps und Mühe. Trau mich ja gar nicht mehr fragen, ob ihr sonst noch Ideen habt  :-[

LG, Birgit

Offline Ralf_M_Petter

  • Gold Platin u.s.w. member:)
  • *****
  • Beiträge: 1.879
  • Geschlecht: Männlich
  • Jeder ist seines eigenen Glückes Schmied
    • Ralf's Blog
Re: Java OutOfMemoryError
« Antwort #14 am: 22.04.05 - 11:41:45 »
Jetzt nochmal langsam, was heisst, kein Erfolg. du bekommst also noch immer die Fehlermeldung OutofMemoryError. Kannst du mal den genauen Inhalt der Javakonsole posten?

Grüße

Ralf

P.S. Eventuell poste nochmal deinen jetzigen Code und deine genaue Vorgehendsweise.
Jede Menge Tipps und Tricks zu IT Themen findet Ihr auf meinem Blog  Everything about IT  Eine wahre Schatzkiste sind aber sicher die Beiträge zu meinem Lieblingsthema Tipps und Tricks zu IBM Notes/Domino Schaut doch einfach mal rein.

Marinero Atlántico

  • Gast
Re: Java OutOfMemoryError
« Antwort #15 am: 22.04.05 - 11:56:49 »
Hi,

ich hatte daselbe Problem wenn ich den die Sachen in den Agent als Attachement gepackt habe.
Guter Punkt  :D
In deinem Programmverzeichnis müsste sich ein VErzeichnis java\lib\ext (oder so ähnlihc) befinden.
Tu da den DB2Treiber rein und starte den Notes Client neu.
Lösche dann den DB2Treiber aus dem Attachment und kompiliere neu.

Offline birdy

  • Frischling
  • *
  • Beiträge: 37
  • Geschlecht: Weiblich
  • Keep smiling!
Re: Java OutOfMemoryError
« Antwort #16 am: 22.04.05 - 12:09:06 »
Yep, die Fehlermeldung ist immer noch die gleiche.

Die Vorgehensweise im Detail:

1. Der User gibt über eine Dialogbox eine Auftragsnr. ein.
2. Die Nr. wird in einem Profildokument gespeichert.
3. Der Java-Agent wird aufgerufen.

 - bis hierher alles über LotusScript -

4. Der Agent liest die Nr. aus dem Profildokument aus.
5. Es wird über JDBC eine Verbindung zur DB2 aufgebaut.
6. SQL-Abfrage
7. Im RecordSet wird nach der Nr. gesucht.
8. Anhand der Auftragsnr. werden mehrere Daten aus der DB2 gefischt und in Variablen gespeichert.
9. Ein neues Notes-Document wird erstellt.
10. Die Daten werden an Felder im Notes-Doc übergeben.
11. Das Notes-Doc wird gespeichert.
12. Die JDBC-Verbindung wird gekappt.
13. Objekte werden recycelt und alles auf null gesetzt.

Hier nochmal der Code:

Code
import lotus.domino.*;
import java.sql.*;
import java.io.*;
import java.util.*;

public class JavaAgent extends AgentBase {

	public void NotesMain() {
		
		Database db = null;
		Connection con = null;

		try {
			Session session = getSession();
			AgentContext agentContext = session.getAgentContext();
			db = agentContext.getCurrentDatabase();
			Document doc = agentContext.getDocumentContext();
			Document profildok = db.getProfileDocument("Profildok", "");
			
			// Variablen deklarieren
			String l_nr;
			String l_artikel;
			String l_stueck;
			String l_text;
			String l_termin;
			boolean rc;
			
			// Nr. aus Profildokument auslesen
			l_nr = profildok.getItemValueString("Nr");
			
			System.out.println("lfd.Nr. " + l_lfdnr);

			PrintWriter pw = getAgentOutput();
			// Connection con=null;
			Statement stmt=null;
			ResultSet rs=null;
			
			String JDBCDriverName="com.ibm.as400.access.AS400JDBCDriver";
			String system="Serverpfad/; libraries=libname";

			String user = "username"; 
			String pwd = "password"; 

			DriverManager.registerDriver((Driver) Class.forName(JDBCDriverName).newInstance());
			con = DriverManager.getConnection(system,user,pwd);
			stmt = con.createStatement();
			
			System.out.println("Connection hergestellt.");
			
			// SQL-Abfrage
			String sql = "SELECT feld1, feld2, feld3, feld4 FROM libname.tablename;
			rs = stmt.executeQuery(sql);
			
			// prüfen ob rs leer ist
			rc = rs.next();
				if (rc) {
					// Felder auslesen
					System.out.println("RS gefüllt");
					l_nr = rs.getString(1);
					l_artikel = rs.getString(2);
					l_stueck = rs.getString(3);
					l_termin = rs.getString(4);
					l_text = rs.getString(5);
					}
				else {
					// Leerstring
					System.out.println("RS leer");
					l_nr = "";
					l_artikel = "";
					l_stueck = "";
					l_termin = "";
					l_text = "";
					};
			 
			// Anzahl der Zeichen zählen, wenn < 0 ist Leerstring
			int l_zeichen = l_artikel.length();
			System.out.println("Zeichen " + l_zeichen);

			boolean z = (l_zeichen > 0);
			
			if (z) {
			// neues Dokument anlegen		
			doc = db.createDocument();
			doc.appendItemValue("Form", "maskenname");
			System.out.println("Dok. angelegt.");
			
			// Felder im Dokument füllen
			doc.appendItemValue("Nr", l_nr);
			doc.appendItemValue("Artikel", l_artikel);
			doc.appendItemValue("Stueck", l_stueck);
			doc.appendItemValue("Termin", l_termin);
			doc.appendItemValue("Text", l_text);
						
			// Dokument speichern
			doc.save(true, true);
			}
			else {
				System.out.println("Kein Dokument angelegt.");
			}
			
			// Close statement and connection
			rs.close();
			stmt.close();
			con.close();
			
			// alles bereinigen
			profildok.recycle();
			doc.recycle();		
			
			rs = null;
			stmt = null;
			con = null;
			
			System.gc();

			} //end try


			catch (Exception e) {
				e.printStackTrace();
			
			if (con != null)
			try{
				con.close();
				} catch (SQLException sqle) {
					}
				}
	}
}

Offline birdy

  • Frischling
  • *
  • Beiträge: 37
  • Geschlecht: Weiblich
  • Keep smiling!
Re: Java OutOfMemoryError
« Antwort #17 am: 22.04.05 - 12:13:30 »
@marinero atlantico

das Verzeichnis hab ich.
nur, was meinst du mit Attachment?

und, müsste dann jeder user der die db nutzt diesen treiber im verzeichnis stehen haben? fürchte da spielt mein admin nicht mit.

Marinero Atlántico

  • Gast
Re: Java OutOfMemoryError
« Antwort #18 am: 22.04.05 - 12:47:26 »
Das die fEhlermeldung kommt verstehe ich nicht, aber es fehlte die Klammerung nach dem if in der catch clause. Mit // NEU gekennzeichnet.
Code
import lotus.domino.*;
import java.sql.*;
import java.io.*;
import java.util.*;

public class JavaAgent extends AgentBase {

	public void NotesMain() {
		
		Database db = null;
		Connection con = null;

		try {
			Session session = getSession();
			AgentContext agentContext = session.getAgentContext();
			db = agentContext.getCurrentDatabase();
			Document doc = agentContext.getDocumentContext();
			Document profildok = db.getProfileDocument("Profildok", "");
			
			// Variablen deklarieren
			String l_nr;
			String l_artikel;
			String l_stueck;
			String l_text;
			String l_termin;
			boolean rc;
			
			// Nr. aus Profildokument auslesen
			l_nr = profildok.getItemValueString("Nr");
			
			System.out.println("lfd.Nr. " + l_lfdnr);

			PrintWriter pw = getAgentOutput();
			// Connection con=null;
			Statement stmt=null;
			ResultSet rs=null;
			
			String JDBCDriverName="com.ibm.as400.access.AS400JDBCDriver";
			String system="Serverpfad/; libraries=libname";

			String user = "username"; 
			String pwd = "password"; 

			DriverManager.registerDriver((Driver) Class.forName(JDBCDriverName).newInstance());
			con = DriverManager.getConnection(system,user,pwd);
			stmt = con.createStatement();
			
			System.out.println("Connection hergestellt.");
			
			// SQL-Abfrage
			String sql = "SELECT feld1, feld2, feld3, feld4 FROM libname.tablename;
			rs = stmt.executeQuery(sql);
			
			// prüfen ob rs leer ist
			rc = rs.next();
				if (rc) {
					// Felder auslesen
					System.out.println("RS gefüllt");
					l_nr = rs.getString(1);
					l_artikel = rs.getString(2);
					l_stueck = rs.getString(3);
					l_termin = rs.getString(4);
					l_text = rs.getString(5);
					}
				else {
					// Leerstring
					System.out.println("RS leer");
					l_nr = "";
					l_artikel = "";
					l_stueck = "";
					l_termin = "";
					l_text = "";
					};
			 
			// Anzahl der Zeichen zählen, wenn < 0 ist Leerstring
			int l_zeichen = l_artikel.length();
			System.out.println("Zeichen " + l_zeichen);

			boolean z = (l_zeichen > 0);
			
			if (z) {
			// neues Dokument anlegen		
			doc = db.createDocument();
			doc.appendItemValue("Form", "maskenname");
			System.out.println("Dok. angelegt.");
			
			// Felder im Dokument füllen
			doc.appendItemValue("Nr", l_nr);
			doc.appendItemValue("Artikel", l_artikel);
			doc.appendItemValue("Stueck", l_stueck);
			doc.appendItemValue("Termin", l_termin);
			doc.appendItemValue("Text", l_text);
						
			// Dokument speichern
			doc.save(true, true);
			}
			else {
				System.out.println("Kein Dokument angelegt.");
			}
			
			// Close statement and connection
			rs.close();
			stmt.close();
			con.close();
			
			// alles bereinigen
			profildok.recycle();
			doc.recycle();		
			
			rs = null;
			stmt = null;
			con = null;
			
			System.gc();

			} //end try


			catch (Exception e) {
				e.printStackTrace();
			
			if (con != null) { //NEU NEU NEU (die Klammer)
			try{
				con.close();
				} catch (SQLException sqle) {
					}
				}
	}
}
Kanns z.Zt. nicht ausprobieren.
Ja. Der Treiber müsste dann auf jeden Desktop deployed werden.
3-Tier Umgebungen sind mit Notes ein bischen nicht so gut.

Marinero Atlántico

  • Gast
Re: Java OutOfMemoryError
« Antwort #19 am: 23.04.05 - 01:24:48 »
Hier zu später Stunde noch das versprochene verbesserte ExceptionHandling:
Über
Code
catch (Exception e) 
das hier:
Code
catch(SQLException sqlEx)
    {
      while(sqlEx != null) {
        System.err.println("SQLException information");
        System.err.println("Error msg: " + sqlEx.getMessage());
        System.err.println("SQLSTATE: " + sqlEx.getSQLState());
        System.err.println("Error code: " + sqlEx.getErrorCode());
        sqlEx.printStackTrace();
        sqlEx=sqlEx.getNextException();
      }
    }
Falls es Probleme mit dem SQL gibt, erhält man so alle wichtigen Fehlerinformationen. Über SQLState und ErrorCode bekommt man aus der DB2 Doku direkt raus, woran es hakt. Meistens ist bei mir das SQL-Statement doch nicht so richtig (bei mir zumindest)

Btw. bringt System.gc() fast nie etwas.

Ausserdem solltest du PreparedStatement statt Statement verwenden. Das macht den Code oft sicherer und vielleicht können so auch die Ausführungspfade von SQL-Statements auf DB2 gecached werden (die Regeln habe ich immer noch nicht so richtig verstanden). JDBC läuft immer über sogenanntes "dynamisches SQL" und da wird auf DB2 immer zuerst der "Ausführungsplan" errechnet und das nimmt Zeit in Anspruch. Bei einfachen SQL aber im Milisekundenbereich.

Warum diese komische Konstruktion mit connection noch mal in catch schliessen?
Oben öffnest du eine Datenbank-Connection. Das ist eine knappe Ressource. Wenn nun in dem Code des try-Blocks an irgend einer Stelle eine Exception auftritt, wechselt das Programm direkt in den catch-Block und kommt nie wieder in den try zurück. Die Connection muß aber geschlossen werden. So muß man das eben im catch auch noch machen. Und dieses Statement muß wiederum mit try-catch umgeben werden, da connection.close() eine SQLException wirft.

Das sind all diese kleinen JDBC-Basics.

In der realen Java-Welt ist JDBC Programmierung mittlerweile ziemlich selten. Die Leute benutzen irgendwelche Frameworks und Objekt-Relationalen-Mapper wie Hibernate.
Ich hab hier z.B. ein Framework namens IBAtis SQLMaps und da stehen die ganzen SQL-Queries gar nicht mehr im Source-Code sondern werden per xml definiert:
Sieht ungefähr so aus:
Als Beispiel steht ein solcher sql-query in einer xml-Datei (mit den entsprechenden Datentypen die übergeben und zurückgegeben werden:
Code
<select id="getIdByIdUserAndIdStockDescr"
		parameterClass="java.util.HashMap" resultClass="java.lang.Long">
		Select ID from STockUser where IDUSER=#idUser# AND IDStockDescr=#idStockDescr#
</select>
Wird dann einfach so in einem sogenannten DataAcces Object aufgerufen und ich spar mir den ganzen restlichen Quatsch. Den Rest macht das Framework. Hier lass ich mir nur eine ID als Long zurückgeben. Ganze Objekte geht aber auch. Auch als Collection.
Code
public StockUser getStockUserByIdUserAndIdStockDescr(long idUser, int idStockDescr) throws IllegalArgumentException {
		if (idUser < 0) throw new IllegalArgumentException("Parameter idUser cannot be lower than 0");
		if (idStockDescr < 0) throw new IllegalArgumentException("Parameter idStockDescr cannot be lower than 0");
		
		Map params = new HashMap();
		params.put("idUser", new Long(idUser));
		params.put("idStockDescr", new Long(idStockDescr));
		return (StockUser)getSqlMapClientTemplate().queryForObject("getStockUserByIdUserAndIdStockDescr", params);
	}

Leider kann man mit Notes solche schönen Sachen nur unter ziemlichen Verrenkungen schwer verwenden.

« Letzte Änderung: 23.04.05 - 01:33:43 von Marinero Atlántico »

 

Impressum Atnotes.de  -  Powered by Syslords Solutions  -  Datenschutz