Hallo zusammen,
habe da wohl ein verzwicktes Problem wo ich echt Hilfe benötige.
Zweck:
Ich habe eine Java Anwendung, die SWT zur Visualisierung nutzt.
Und zwar will ich von meinem Java-App-Server per RMI eine entfernte Anwendung rufen, die dann mit Hilfe von SWT und dem dort per OLE integrierten Internet-Explorer die Daten visualisiert. Die gefeuerte RMI Methode soll also quasi eine Aktivität in dem OLE-Objekt (Internet-Explorer) auslösen.
Bisher ist das wie folgt realisiert:
Mit SWT definiere ich einen OLE-Frame und steuere den Internet-Explorer als OLE-Objekt. Der IE startet einmalig eine URL. In dieser URL ist wiederum ein Active-X-Control eingebettet. Dieses Active-X-Control wird dann von meiner Java-Anwendung indirekt über Javascript der aufgerufenen HTML-Seite angesteuert.
Dieses Active-X startet ein grafisches Tool im Explorer. Das Control ist leider nicht direkt per OLE ansteuerbar. Meine Java-Anwendung startet dann im IE wie gesagt eine Java-Script-Funktion die dann das Active-X veranlasst jeweils eine neue Grafik zu verarbeiten.
Soweit so gut. Das ganze funktioniert mit unterschiedlichen Aufrufen der JS-Funktion wenn ich das z.B. von unterschiedlichen Buttons in SWT ansteuere.
Jetzt kommt RMI ins Spiel.
Nämlich die ganze Anwendung soll nämlich nicht interaktiv über Buttons, sondern von einem Java-App-Server aus getriggert werden (einer Bean um genau zu sein), der die zu visualisierenden Daten hält.
Also Server ruft per RMI meine Java-Client-Anwendung (nur JRE). Eine Methode meines RMI-Objektes soll dann die Java-Methode meiner Visualisierung aufrufen, die ihrerseits dann im IE per OLE die Javascript-Funktion startet.
RMI an sich funktioniert. Visualisierung in SWT mit OLE im IE auch.
Aber wenn meine RMI-Methode (die als Parameter das Objekt erhält welches die UI steuert) dann die SWT-Visualisierungsmethode aufruft fliegt mir die JVM um die Ohren mit EXCEPTION_ACCESS_VIOLATION (0xc0000005)
Jetzt hab ich schon gelesen das das wohl was mit Threads zu tun haben wird. Die Methode des RMI-Objekts läuft ja wohl in einem anderen Thread als dem, der das SWT-UI erzeugt hat.
Wie kann ich das Problem lösen? Mit eigener Thread-Steuerung hab ich nicht so wahnsinnig viel Erfahrung bisher.
So sieht der Quellcode (gekürzt) im wesentlichen aus (bitte keine Syntax-Fehler melden..können durch die Kürzung reingekommen sein):
Vielen lieben Dank im Vorraus für Eure Unterstützung:
McD
Das Objekt mit meiner Main-Methode. Sie erzeugt das Objekt mit dem UI und erzeugt Registry und das Binding für das RMI-Objekt
[JAVA=42]
private static final Logger log = Logger.getLogger( FpViewer.class.getName() );
public static void main(String[] args) {
Registry r;
try
{
// UI aufbauen
Display display = Display.getDefault();
Shell shell = new Shell(display);
FpViewerUI ui = new FpViewerUI(shell, SWT.NULL, log);
Point size = ui.getSize();
shell.setLayout(new FillLayout());
shell.layout();
if(size.x == 0 && size.y == 0) {
ui.pack();
shell.pack();
} else {
Rectangle shellBounds = shell.computeTrim(0, 0, size.x, size.y);
shell.setSize(shellBounds.width, shellBounds.height);
}
RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory());
r = LocateRegistry.createRegistry(28000);
// RemoteServer.setLog( System.out );
System.out.println("Binde Klasse Kall2FpDevRMI an Server...");
log.log(Level.INFO,"Binde Klasse Kall2FpDevRMI an Server...");
r.bind("IKall2FpViewer", new Kall2FpViewer(log,ui));
System.out.println("Starte UI-Loop");
shell.open();
// UI-Loop
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
[/code]
meine RMI-Klasse Kall2FpViewer hier. Die Methode createJPG ist die Methode die vom App-Server aufgerufen wird:
[JAVA=42]
public class Kall2FpViewer extends UnicastRemoteObject implements IKall2FpViewer {
public static final long serialVersionUID = 4711;
private Logger log;
private FpViewerUI ui;
public Kall2FpViewer (Logger logger, FpViewerUI fpViewerUI) throws RemoteException
{
super ();
// Daten im Objekt sichern
log = logger;
ui = fpViewerUI;
}
public boolean createJPG(String fileName, String guid) {
ui.startJPGRendering(fileName, guid);
return false;
}
}
[/code]
meine Visualisierungs-Klasse (gekürzt, könnte sein das deshalb vielleicht mal ne Klammer oder so fehlt, aber vom Prinzip funzt es ja wenn das Teil per Buttons, die hier jetzt weggelassen wurden, getriggert wird)
[JAVA=42]
public class FpViewerUI extends org.eclipse.swt.widgets.Composite {
public FpViewerUI(Composite parent, int style, Logger) {
super(parent, style);
browserAvailable = false;
initGUI();
log = logger;
}
public boolean startJPGRendering (String fileName, String guid)
{
System.out.println("In startJPGRendering");
boolean result = false;
if (this.browserAvailable)
{
int[] htmlDocumentID = browser.getIDsOfNames(new String[] { "Document" });
System.out.println("htmlDocumentID="+htmlDocumentID);
if (htmlDocumentID == null)
return result;
Variant pVarResult = browser.getProperty(htmlDocumentID[0]);
System.out.println("pVarResult="+pVarResult);
if (pVarResult == null || pVarResult.getType() == 0)
return result;
// IHTMLDocument2
OleAutomation htmlDocument = null;
try {
htmlDocument = pVarResult.getAutomation();
pVarResult.dispose();
int[] scriptID = htmlDocument.getIDsOfNames(new String[] { "Script" });
System.out.println("scriptID="+scriptID);
if (scriptID == null)
return result;
pVarResult = htmlDocument.getProperty(scriptID[0]);
System.out.println("pVarResult2="+pVarResult);
if (pVarResult == null || pVarResult.getType() == 0)
return result;
OleAutomation htmlWindow = null;
try {
// IHTMLWindow2
htmlWindow = pVarResult.getAutomation();
pVarResult.dispose();
int[] evaluateID = htmlWindow.getIDsOfNames(new String[] { "testGenerate" });
System.out.println("testGenerateId="+evaluateID);
if (evaluateID == null)
return result;
String expression = fileName;
Variant[] rgvarg = new Variant[] { new Variant(
fileName), new Variant(guid) };
pVarResult = htmlWindow.invoke(evaluateID[0], rgvarg,
null);
if (pVarResult == null || pVarResult.getType() == 0)
return result;
System.out.println(expression + " ="
+ pVarResult.getString());
result = true;
} finally {
htmlWindow.dispose();
}
} finally {
htmlDocument.dispose();
}
}
System.out.println("Raus startJPGRendering");
return result;
}
/**
* Initializes the GUI.
*/
private void initGUI() {
try {
FormData composite1LData = new FormData();
composite1LData.width = 700;
composite1LData.height = 500;
composite1 = new Composite(this, SWT.NONE);
GridLayout composite1Layout = new GridLayout();
composite1Layout.makeColumnsEqualWidth = true;
composite1.setLayout(composite1Layout);
composite1.setLayoutData(composite1LData);
{
OleFrame frame = new OleFrame(composite1, SWT.NONE);
site = new OleControlSite(frame, SWT.NONE, "Shell.Explorer");
site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
site.setBounds(5, 0, 700, 500);
browser = new OleAutomation(site);
// When the document is loaded, access the document object for the new
// page
// and evalute expression using Script.
int DownloadComplete = 104;
site.addEventListener(DownloadComplete, new OleListener() {
public void handleEvent(OleEvent event) {
browserAvailable = true;
System.out.println("browserAvailable set");
int[] htmlDocumentID = browser.getIDsOfNames(new String[] { "Document" });
System.out.println("htmlDocumentID="+htmlDocumentID);
if (htmlDocumentID == null)
return;
Variant pVarResult = browser.getProperty(htmlDocumentID[0]);
System.out.println("pVarResult="+pVarResult);
if (pVarResult == null || pVarResult.getType() == 0)
return ;
// IHTMLDocument2
OleAutomation htmlDocument = null;
try {
htmlDocument = pVarResult.getAutomation();
pVarResult.dispose();
} finally {
htmlDocument.dispose();
}
}
});
int[] ids = browser.getIDsOfNames(new String[] { "Navigate", "URL" });
Variant[] rgvarg = new Variant[] { new Variant("file://myhtml.html") };
int[] rgdispidNamedArgs = new int[] { ids[1] };
browser.invoke(ids[0], rgvarg, rgdispidNamedArgs);
System.out.println("Nach brower.invoke");
}
this.layout();
} }
catch (Exception e) {
e.printStackTrace();
}
}
}
[/code]
habe da wohl ein verzwicktes Problem wo ich echt Hilfe benötige.
Zweck:
Ich habe eine Java Anwendung, die SWT zur Visualisierung nutzt.
Und zwar will ich von meinem Java-App-Server per RMI eine entfernte Anwendung rufen, die dann mit Hilfe von SWT und dem dort per OLE integrierten Internet-Explorer die Daten visualisiert. Die gefeuerte RMI Methode soll also quasi eine Aktivität in dem OLE-Objekt (Internet-Explorer) auslösen.
Bisher ist das wie folgt realisiert:
Mit SWT definiere ich einen OLE-Frame und steuere den Internet-Explorer als OLE-Objekt. Der IE startet einmalig eine URL. In dieser URL ist wiederum ein Active-X-Control eingebettet. Dieses Active-X-Control wird dann von meiner Java-Anwendung indirekt über Javascript der aufgerufenen HTML-Seite angesteuert.
Dieses Active-X startet ein grafisches Tool im Explorer. Das Control ist leider nicht direkt per OLE ansteuerbar. Meine Java-Anwendung startet dann im IE wie gesagt eine Java-Script-Funktion die dann das Active-X veranlasst jeweils eine neue Grafik zu verarbeiten.
Soweit so gut. Das ganze funktioniert mit unterschiedlichen Aufrufen der JS-Funktion wenn ich das z.B. von unterschiedlichen Buttons in SWT ansteuere.
Jetzt kommt RMI ins Spiel.
Nämlich die ganze Anwendung soll nämlich nicht interaktiv über Buttons, sondern von einem Java-App-Server aus getriggert werden (einer Bean um genau zu sein), der die zu visualisierenden Daten hält.
Also Server ruft per RMI meine Java-Client-Anwendung (nur JRE). Eine Methode meines RMI-Objektes soll dann die Java-Methode meiner Visualisierung aufrufen, die ihrerseits dann im IE per OLE die Javascript-Funktion startet.
RMI an sich funktioniert. Visualisierung in SWT mit OLE im IE auch.
Aber wenn meine RMI-Methode (die als Parameter das Objekt erhält welches die UI steuert) dann die SWT-Visualisierungsmethode aufruft fliegt mir die JVM um die Ohren mit EXCEPTION_ACCESS_VIOLATION (0xc0000005)
Jetzt hab ich schon gelesen das das wohl was mit Threads zu tun haben wird. Die Methode des RMI-Objekts läuft ja wohl in einem anderen Thread als dem, der das SWT-UI erzeugt hat.
Wie kann ich das Problem lösen? Mit eigener Thread-Steuerung hab ich nicht so wahnsinnig viel Erfahrung bisher.
So sieht der Quellcode (gekürzt) im wesentlichen aus (bitte keine Syntax-Fehler melden..können durch die Kürzung reingekommen sein):
Vielen lieben Dank im Vorraus für Eure Unterstützung:
McD
Das Objekt mit meiner Main-Methode. Sie erzeugt das Objekt mit dem UI und erzeugt Registry und das Binding für das RMI-Objekt
[JAVA=42]
private static final Logger log = Logger.getLogger( FpViewer.class.getName() );
public static void main(String[] args) {
Registry r;
try
{
// UI aufbauen
Display display = Display.getDefault();
Shell shell = new Shell(display);
FpViewerUI ui = new FpViewerUI(shell, SWT.NULL, log);
Point size = ui.getSize();
shell.setLayout(new FillLayout());
shell.layout();
if(size.x == 0 && size.y == 0) {
ui.pack();
shell.pack();
} else {
Rectangle shellBounds = shell.computeTrim(0, 0, size.x, size.y);
shell.setSize(shellBounds.width, shellBounds.height);
}
RMISocketFactory.setSocketFactory(new FixedPortRMISocketFactory());
r = LocateRegistry.createRegistry(28000);
// RemoteServer.setLog( System.out );
System.out.println("Binde Klasse Kall2FpDevRMI an Server...");
log.log(Level.INFO,"Binde Klasse Kall2FpDevRMI an Server...");
r.bind("IKall2FpViewer", new Kall2FpViewer(log,ui));
System.out.println("Starte UI-Loop");
shell.open();
// UI-Loop
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
[/code]
meine RMI-Klasse Kall2FpViewer hier. Die Methode createJPG ist die Methode die vom App-Server aufgerufen wird:
[JAVA=42]
public class Kall2FpViewer extends UnicastRemoteObject implements IKall2FpViewer {
public static final long serialVersionUID = 4711;
private Logger log;
private FpViewerUI ui;
public Kall2FpViewer (Logger logger, FpViewerUI fpViewerUI) throws RemoteException
{
super ();
// Daten im Objekt sichern
log = logger;
ui = fpViewerUI;
}
public boolean createJPG(String fileName, String guid) {
ui.startJPGRendering(fileName, guid);
return false;
}
}
[/code]
meine Visualisierungs-Klasse (gekürzt, könnte sein das deshalb vielleicht mal ne Klammer oder so fehlt, aber vom Prinzip funzt es ja wenn das Teil per Buttons, die hier jetzt weggelassen wurden, getriggert wird)
[JAVA=42]
public class FpViewerUI extends org.eclipse.swt.widgets.Composite {
public FpViewerUI(Composite parent, int style, Logger) {
super(parent, style);
browserAvailable = false;
initGUI();
log = logger;
}
public boolean startJPGRendering (String fileName, String guid)
{
System.out.println("In startJPGRendering");
boolean result = false;
if (this.browserAvailable)
{
int[] htmlDocumentID = browser.getIDsOfNames(new String[] { "Document" });
System.out.println("htmlDocumentID="+htmlDocumentID);
if (htmlDocumentID == null)
return result;
Variant pVarResult = browser.getProperty(htmlDocumentID[0]);
System.out.println("pVarResult="+pVarResult);
if (pVarResult == null || pVarResult.getType() == 0)
return result;
// IHTMLDocument2
OleAutomation htmlDocument = null;
try {
htmlDocument = pVarResult.getAutomation();
pVarResult.dispose();
int[] scriptID = htmlDocument.getIDsOfNames(new String[] { "Script" });
System.out.println("scriptID="+scriptID);
if (scriptID == null)
return result;
pVarResult = htmlDocument.getProperty(scriptID[0]);
System.out.println("pVarResult2="+pVarResult);
if (pVarResult == null || pVarResult.getType() == 0)
return result;
OleAutomation htmlWindow = null;
try {
// IHTMLWindow2
htmlWindow = pVarResult.getAutomation();
pVarResult.dispose();
int[] evaluateID = htmlWindow.getIDsOfNames(new String[] { "testGenerate" });
System.out.println("testGenerateId="+evaluateID);
if (evaluateID == null)
return result;
String expression = fileName;
Variant[] rgvarg = new Variant[] { new Variant(
fileName), new Variant(guid) };
pVarResult = htmlWindow.invoke(evaluateID[0], rgvarg,
null);
if (pVarResult == null || pVarResult.getType() == 0)
return result;
System.out.println(expression + " ="
+ pVarResult.getString());
result = true;
} finally {
htmlWindow.dispose();
}
} finally {
htmlDocument.dispose();
}
}
System.out.println("Raus startJPGRendering");
return result;
}
/**
* Initializes the GUI.
*/
private void initGUI() {
try {
FormData composite1LData = new FormData();
composite1LData.width = 700;
composite1LData.height = 500;
composite1 = new Composite(this, SWT.NONE);
GridLayout composite1Layout = new GridLayout();
composite1Layout.makeColumnsEqualWidth = true;
composite1.setLayout(composite1Layout);
composite1.setLayoutData(composite1LData);
{
OleFrame frame = new OleFrame(composite1, SWT.NONE);
site = new OleControlSite(frame, SWT.NONE, "Shell.Explorer");
site.doVerb(OLE.OLEIVERB_INPLACEACTIVATE);
site.setBounds(5, 0, 700, 500);
browser = new OleAutomation(site);
// When the document is loaded, access the document object for the new
// page
// and evalute expression using Script.
int DownloadComplete = 104;
site.addEventListener(DownloadComplete, new OleListener() {
public void handleEvent(OleEvent event) {
browserAvailable = true;
System.out.println("browserAvailable set");
int[] htmlDocumentID = browser.getIDsOfNames(new String[] { "Document" });
System.out.println("htmlDocumentID="+htmlDocumentID);
if (htmlDocumentID == null)
return;
Variant pVarResult = browser.getProperty(htmlDocumentID[0]);
System.out.println("pVarResult="+pVarResult);
if (pVarResult == null || pVarResult.getType() == 0)
return ;
// IHTMLDocument2
OleAutomation htmlDocument = null;
try {
htmlDocument = pVarResult.getAutomation();
pVarResult.dispose();
} finally {
htmlDocument.dispose();
}
}
});
int[] ids = browser.getIDsOfNames(new String[] { "Navigate", "URL" });
Variant[] rgvarg = new Variant[] { new Variant("file://myhtml.html") };
int[] rgdispidNamedArgs = new int[] { ids[1] };
browser.invoke(ids[0], rgvarg, rgdispidNamedArgs);
System.out.println("Nach brower.invoke");
}
this.layout();
} }
catch (Exception e) {
e.printStackTrace();
}
}
}
[/code]
Zuletzt bearbeitet: