How to call a JavaScript callback from a Java applet thread? - java

I have some long-running Java code running in a thread started by a Java applet. As soon as the code has finished, it has information for the user. I'd like to pass this information to a JavaScript callback in a thread-safe way. Just using the Java DOM API to modify the HTML document is not good enough, unless my JavaScript callback gets called as a side effect in a thread safe way (i.e. eventually, in the same browser thread where JavaScript callbacks execute). How can I implement this? Are there libraries already doing it?

Looks as though the Common DOM API is what you need. In essence you request a DOMService to call you back on the main UI thread when it is good and ready.
http://docs.oracle.com/javase/1.5.0/docs/guide/plugin/developer_guide/java_js.html
As I understand things, JSObject is the "old way" and the Common DOM API is the newer way (as of Java 6). What you need to do is call a method of your applet and pass the function object that you want to have called back. Your applet then calls that function object from within your DOMAction.
I have no code at hand to show you and this is not something I've done before using Java. However I have used a similar technique from with an NPAPI web plugin written in C++ i.e. had JS call my C++ object passing a function as a parameter, and then at a later stage, have the C++ object call the JS function. 'hope that this helps.

I had concurrency issues with multiple applet threads calling Javascript. Some of the calls were simply ignored by Internet Explorer 8 (Firefox 3.6 and Safari 5 worked fine).
I tried to wrap calls to Javascript with DOMService.invokeAndWait - that didn't help.
I ended up ensuring that all the Java->Javascript calls are made from the same thread, and my problems were solved (at least temporarily - I haven't checked what happens if the Javascript thread is busy with some user-initiated work).
To serialize the calls, I used Executors.newSingleThreadExecutor

It seems that there is no public tutorial how to do it. The whole JavaScript--Java interface is underdocumented, and it is subject to browser limitations.

Related

Environment sharing between request threads in Google App Engine

I have noticed that when I create a new thread using the request thread factory provided by GAE then the new thread has the same Environment as the parent thread. (The identityHashCode of the current environment is the same in both threads.)
On the one hand, this is nice because the newly created thread starts with the same context as the parent.
The problem is that the Environment is not immutable. It contains the ".currentNamespace" attribute which is used in namespace handling. If one of the threads changes the current namespace it is applied on all threads which is clearly not what I want.
My idea to fix this was that I created an own Environment implementation and when a new thread is created I copy the content of the current environment into this new environment and set this environment as current on the new thread. So the new thread starts with the same context but it can independently change later.
This solution worked during initial testing but then I run into a problem
Caused by: java.lang.ClassCastException: MyEnvironmentImplementation cannot be cast to com.google.apphosting.runtime.ApiProxyImpl$EnvironmentImpl
at com.google.apphosting.runtime.ApiProxyImpl.log(ApiProxyImpl.java:67)
I have no access to the code of com.google.apphosting.runtime.ApiProxyImpl but it is clear that this method tries to cast the interface it received into its own implementation class without checking the type.
I find this strange because there is a void setEnvironmentFactory(ApiProxy.EnvironmentFactory factory) in the ApiProxy so it is expected that someone might use a different implementation of the Environment interface than the default one.
Is there another way to use different namespaces in different request threads?
Is this unchecked casting considered a bug or is it fundamentally wrong to use my own Environment implementation?
I use app engine standard with 1.9.84 of the java sdk.
Edit:
It is actually documented that "This should not be used from user-code." on the
ApiProxy.setEnvironmentForCurrentThread() and ApiProxy.setEnvironmentFactory() methods. So my suggested workaround is not expected to work. You shouldn't try something like it either.
No need to use Google API threads. Do not let Google API's cause you problems. Do this yourself outside of the browser as I describe here.
Write a program that sub-classes your browser, and subclass each window that is opened. Then run a javascript on each page that saves your result to the location bar where it is easy to collect it later. Then collect that information from the location bar and then put the previous (which was in the location bar) back into it so that it will be seen as being the same as it was before.
If you want to use that data in a different web page then put it there via your separate program.
Each opened browser window could theoretically be running a separate google api process.
With your program subclassing all of the browser windows separately, have your program to share information between them without the google api getting confused.
Like this:
Write a program (in VB6 sp5 I did this years ago. Never use any later version of Visual Studio for anything. In C++11 this should work.).
Using FireFox as a browser for this example.
(1) Have your program start and Subclass FireFox.
(2) Have your program tell Firefox to open up a new window (might need to make this a FireFox "new tab" or maybe not).
(3) Tell your program to get the pre-handle of the newly opening window. Do this quickly and keep trying (up to 30 seconds if you have an overloaded operating system) until you get the pre-handle, then assign a new Window's handle to that new window or new tab.
(4) Use that new handle and send a javascript to the address bar (minus the "j"), meaning that you send an entire "avascript..." to that address bar, then add the previous "j" since if FireFox detects that you placed any command into the addressbar with the entire word "javascript" it will stop you from doing some things (if I recall correctly).
(5) Run that javascript obtaining from or placing into each page your changes.
(6) The web pages in the browser, having the javascript running in them do part of the work.
(7) No need to use Google API threads.

It is possible to control a java application from a delphi written application?

My problem is pretty simple i have an application written in java and i want to send commands to it ex ( click a button , send some key strokes , click a menu item ) from my application witch i will write in delphi. Is this concept even possible ?
I actually had to do this at the last place I worked, you can get around it with complex window events etc... as mentioned above but if you have access to the Java source simply write other access methods either that call a specific runtime that closes (i.e. trigger a public static void main(String[] args); via a native call or via the command line.
OR
Implement simple a simple message system between Java/Delphi over TCP/IP and send either XML or some simple string mappings (I think it took about an hour to set up Maps that could pass back and forth).
In my case we were simply handling reporting and talking to the database so it was pretty easy to work around without getting into a native call. Alternatively, there is(was) a port of the JNI for Delphi that worked pretty well with Delphi 7. I have no clue what runtime you're using but it might be an option.
Honestly, the TCP/IP method is probably the easiest. It doesn't take a lot to implement, it doesn't eat a lot of resources and it allows you to execute "myMenuItem.onClick()" pretty easily as a packet, you just have to expose the methods.
http://home.pacifier.com/~mmead/jni/delphi/
Well It depends on which Java GUI technology is used . If SWT or AWT is used , you can get handle of UI components, because these two toolkit uses native libararies.. On the other hand, if that java application GUI is created by beans of SWING, you can not get any handle. Because, swing toolkit is implemented by pure Java..
If the Java app can be modified, the Java Robot API (included in JRE 1.3 and newer) might be helpful. This would allow to control a Swing application which does not provide windows handles as Gursel wrote. Obviously there would be some IPC required, which could be implemented using sockets for example.
The short: YES, but depending on the Java application, it might be difficult and unreliable.
I'm not a Java guy so I don't know if this is the norm, but the one Java application I had to automate displayed a single dialog that only used 1 (one) window handle! It was made up of several edit boxes, buttons, what looked like combo-boxes, but those were not true Windows controls but widgets re-created by whatever GUI toolkit the original developer used. I wasn't able to use normal Windows messages to manipulate those because, as far as Windows was concerned, it was a single window.
Happily the only thing I had to do was click a single button. I used mouse_event to move the mouse over the expected area for the button and then again to click the button. It works, but manipulating input this way is both unreliable and fragile.
To clarify Daniel ChapmanĀ  and mjnĀ  comments, find below a code extract showing Delphi controlling a Java Swing UI component (TextField) contained in a Jframe based on NetBeans ClientEditor sample.
Please notice, that this example does not use the Java source code or use TCP, XML, Windowing events handling technics or IPC, it's just simply Delphi code calling some Java code.
procedure TForm1.Button1Click(Sender: TObject);
begin
FJFrame := Tjavax_swing_JFrame.Create('Client Editor');
FClientEditor := Tclienteditor_ClientEditor.Create;
FJFrame.GetContentPane().Add(FClientEditor);
FJFrame.Pack;
FJFrame.SetVisible(True);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
// Delphi setting a value in a Java Swing UI component
FclientEditor.FirstNameTextField.SetText('Delphi 1stName');
end;
The long type names are just as a matter of clarity for this example and can be shorter of course.Additionally there is no problem with JNI in this example.
Have you had a look at Java for Delphi?
It let's you call Java from Delphi exposing the Java types as Delphi types.

How does a browser interact with a Flash Player or a Java Applet?

I've been trying to understand how flash animations or a Java Applet work within a browser.
I can think of a couple of ways -
The Flash Player/Java Applet are machine code that's dynamically linked it, and given
some parameters about the area of the screen that belongs to them; after that, they
run within the same process space.
The browser exposes an API that the player/applet use to talk to it and they live
in a separate process. (Presumably they talk via sockets?) The API could correspond to
openGL/X11/some custom calls.
These possibilities still don't explain things like how a button click can make the
player full-screen, how it can play music, how it can inspect the DOM, etc. For that matter,
is the video displayed by decoding to a sequence of images, and rendering them
one at a time, or is there a more efficient way, e.g., of pushing the deltas in the image?
The Wikipedia page on Java Applets (1)
talks about how the applet is run in a sandbox (presumably a separate process), but
it doesn't say how the browser and the applet communicate.
Perhaps the answer depends on the underlying platform?
Any pointers to systematic discussion of this topic would be appreciated (as would
a reference to the APIs).
(My interest in this stems from an insatiable curiosity.)
I'm pretty sure plugins like Java applets and Flash run via NPAPI in most browsers. I looked into this matter myself some time ago and NPAPI was the answer I found.
In the case of browser and Java applets, the applets are typically run within the Java plugin, which runs as a separate process (you can see it e.g. in the task administrator in Windows).
The plugin creates an object for each applet in the DOM, and you can thus interact with the applet from Javascript. Anyway, calls to the applet that take a while to return do have the effect to freeze the browser, therefore I'd say the communication with the plugin runs in the same thread as the main refresh loop. This seems at least to be the case with Firefox.

load ActiveX object in Applet

I have a web application that processes events and audio received from a specialised microphone. The audio is processed by a Java applet that runs in the web page, but other events (microphone connected, microphone disconnected, microphone button pressed) are handled by an ActiveX object.
The ActiveX object traps these events and calls JavaScript code to handle them
<!-- Load the ActiveX control -->
<object id="PhilipsSpeechMikeCtrl" width="0" height="0" tabindex="-1"
classid="CLSID:AAA44754-CC81-4692-91AF-7064E58EB22A"
standby="Loading Philips SpeechMike component..."
type="application/x-oleobject">
</object>
<script type="text/javascript">
// This is Microsofts javascript way of trapping ActiveX object events.
function PhilipsSpeechMikeCtrl::SPMEventDeviceConnected(deviceID) {
// Call JavaScript code to handle the microphone connected event
}
function PhilipsSpeechMikeCtrl::SPMEventDeviceDisconnected(deviceID) {
// Call JavaScript code to handle the microphone disconnected event
}
function PhilipsSpeechMikeCtrl::SPMEventButton(deviceID, eventId) {
// Call JavaScript code to handle the microphone button pressed event
}
</script>
Of course a problem with this approach is that it's completely IE dependent. I would prefer to load the ActiveX object within the applet, trap the events there and handle the events either within the applet, or JavaScript code called from the applet. This should then enable me to run the app in any browser that supports applets.
I'm not entirely sure how to go about implementing the solution I've proposed above, any suggestions?
Update: I realise the solution I've proposed above would still be IE dependent, that's fine. My immediate goal is to support all browsers on Windows.
It has been suggested that instead of using ActiveX, I could use JNI (or JNA) to access the DLLs underlying the ActiveX object. However, I don't actually want to call the functions in the DLLs, I want the DLLs to call me, i.e. register an event handler.
Thanks,
Don
ActiveX are not supported by an another browser than IE, so there is no way for your application to support all browsers, even on Windows only.
An attempt (plugin) to port ActiveX under Firefox 1 was made, but wasn't really useful so as far as I know, there is today no "emulation" solution to your question.
Sorry...
(see here for Mozilla comments)
JACOB is supposed to let you call COM from Java. It looks like it supports events too.
You can probably access the dlls in the activeX component directly,
so you can write a jni wrapper that calls the native functions,
and then build a signed applet that can get permission to use jni.
Check this:
http://www.raditha.com/java/jni/
Ahh. You can do want you desire, but may have to eschew Javascript and instead leverage VBScript. It is about the ability to send "events" between two components.
You can use use JavaScript to directly call public methods in the applet or access public variables. JavaScript treats the embedded applet as an object. In the applet tag give the applet a name id.
Consider the example below where the applet has a method public void myMethodInMyApplet();
The HTML page would look something like :
<APPLET CODE="MyApplet.class"
width=200 height=200
name=counter ID=counter>
</APPLET>
<script type="text/javascript">
// This is Microsofts javascript way of trapping ActiveX object events.
function PhilipsSpeechMikeCtrl::SPMEventDeviceConnected(deviceID) {
document.applets[0].myMethodInMyApplet();
}
</script>
Wouldn't that still be Windows- or even IE-dependent, given that Java applets are executed on the client side? Just wondering...
You will obviously have to pass the events twice if you want them to end up in JavaScript.
There is a version of SWT that can be used in applets and can embed ActiveX controls. There are also commercial libraries like Coroutine who can do this as well (and are smaller in jar size). Someone else mentioned JACOB here, which would be another choice.
So, use any of these components to wrap your ActiveX control. These libraries will call a Java method when a registered event occurs.
To pass events from Java to JavaScript, you can use the netscape.javascript.JSObject class which is supported by all major browsers.
If you have the source code for the COM component, it might be a good idea to rewrite it to use JNI, as COM wrappers use up a lot of resources (which is especially important in applets), and most probably there is also some overhead inside the COM component for COM interop.
is activexobjects always hitting the acivex sites like activex.microsoft.com

How do I get my Java application to shutdown nicely in windows?

I have a Java application which I want to shutdown 'nicely' when the user selects Start->Shutdown. I've tried using JVM shutdown listeners via Runtime.addShutdownHook(...) but this doesn't work as I can't use any UI elements from it.
I've also tried using the exit handler on my main application UI window but it has no way to pause or halt shutdown as far as I can tell. How can I handle shutdown nicely?
The previously mentioned JNI approach will likely work.
You can use JNA which is basically a wrapper around JNI to make it easier to use. An added bonus is that it (in my opinion at least) generally is faster and more maintainable than raw JNI. You can find JNA at https://jna.dev.java.net/
If you're just starting the application in the start menu because you're trying to make it behave like a service in windows, you can use the java service wrapper which is found here:
http://wrapper.tanukisoftware.org/doc/english/download.jsp
As far as I know you need to start using JNI to set up a message handler for the Windows WM_QUERYENDSESSION message.
To do this (if you're new to Windows programming like me) you'll need to create a new class of window with a new message handling function (as described here) and handle the WM_QUERYENDSESSION from the message handler.
NB: You'll need to use the JNIEnv::GetJavaVM(...) and then JavaVM::AttachCurrentThread(...) on the message handling thread before you can call any Java methods from your native message handling code.

Categories