Call Java API from javascript on the client (no web service) - javascript

I need a way to use a Java API (jar) from the javascript code on the local client. Can this be achieved and how?
Context
I have a Java API (jar file) that allows to connect to a real time information feed. You can submit a query and, for example, print the events you will receive:
service.subscribe(query, evt -> print(evt));
That API can only be used on the client machine for legal reasons so I can't expose it as a web service from a server.
Goal
I would like to create a web page that gets data from a web service and combines it with the real time information data obtained from the Java API locally.
I am using angular 2 but happy to consider any suggestions.
Web service
I have seen various similar questions but the answers tend to be: expose the API via a web service - that is not possible in my case.

You can use java applets for this purpose.
You should start by making an applet that encloses the call to your method:
public class TestApplet extends Applet{
private ? service = ...;
public Object subscribe(Object query) {
return service.subscribe(query, evt -> print(evt));;
}
}
This applet can then be included in the html of the webpage:
<script src="https://www.java.com/js/deployJava.js"></script>
<script>
<!-- applet id can be used to get a reference to the applet object -->
var attributes = { id:'testApplet', code:'yourpackage.TestApplet', width:1, height:1} ;
var parameters = {jnlp_href: 'test_applet.jnlp'} ;
deployJava.runApplet(attributes, parameters, '1.6');
</script>
Then you can use javascript to call the methods:
var greeting = testApplet.subscribe("Test");
Note that applets are being phased out because of their security problems, but this is ok in an controlled and embedded environment.
The following oracle tutorial gives more information about this technique: Invoking Applet Methods From JavaScript Code

The only way I can think of is using the javafx webview: http://docs.oracle.com/javafx/2/webview/jfxpub-webview.htm
Basically:
you create your own java-based-"webbrowser" withjavafx
you can then expose the java api into the webview
you can open a normal html page (i.e. http://server.tld/mypage.html) within the webview and use javascript to access the api
in the javascript you can check if the site has been opened with a normal browser or with you custom webview by checking if the exposed api is available:
the java code for something like that:
WebView webView = new WebView();
jfxPanel.setScene(new Scene(webView));
webEngine = webView.getEngine();
webEngine.setJavaScriptEnabled(true);
webEngine.setConfirmHandler(new ModalConfirmDialog(self));
// get the window and pass the required daos
JSObject jsobj = (JSObject) webEngine.executeScript("window");
// pass the dataaccess to the js context
jsobj.setMember("javaapi", getApiInstance());
webEngine.load("http://whatever.tld/mypage.html");
in javascript:
if(!window.javaapi) {
alert("Unable to get local java api");
return;
}
Other possibilities:
Applets: they wont work because they need to be downloaded from the same source as the webpage (which you cant use because of licensing restrictions)
JSP/Servlet: cant be used because this means the api must reside on the server (again licensing restriction)
Java Javascript Engine: You can call javascript directly from java, but since you want the javascript in a webpage, this wont work either...

Simply you cannot run .jar file from java script (But you can execute from nodejs) You can use applet to do that. You can refer this link.

It might sound really weird but actually, there's such tool that enable's you to 'convert' from java to js. But of course it has it's limitations and in order to successfully apply it in your particular case w/o doing modifications and dancing with a tambourine, you should be extremely lucky. this tool is able to convert it to js and allows you to create a JS API for the converted JS, so that it can be accessible from other js scripts. What I'm talking about is GWT. You must have source files of a jar (it might be decompiled sources) including all sources of dependencies that are used by lib.

Maybe you can invest in building a bridge between your JS code and the jar using Nashorn.
It allows you to evaluate JS code and invoke JS functions from Java, so it may serve your usecase. You can build a Java layer to connect to the API from the jar and then publish the results to JS by calling some function using Nashorn.
Or you can make use of the ability to directly call Java functions from JS.
Here is a simple tutorial

Related

Access DOM content of browser within Android runtime

Say we have a standard login page like the one below:
We can access the HTML elements in the DOM using jQuery or plain JavaScript like this:
In other words, the way to get the pixel location of an element in a web page is quite simply by using element.getBoundingClientRect():
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
So we can do this from the console or programmatically from a web app.
Now, say we have an Android browser (Chrome/Mozilla/WebView) in the foreground at any time. I can retrieve the URL of the web page in the browser. In this case:
https://login.microsoftonline.com/
So my question is, given the URL of a login page, how do I similarly get access to the same input field on an Android browser?
I need to be able to access the HTML elements of a web page in an Android browser, and calculate its pixel location. As input, I have the URL of a web page in any Android browser.
I am talking about doing this from an Android app, within the Android runtime, i.e. programmatically using Java/JS code.
In case someone needs the DOM structure of the page as text, it can be obtained programmatically with the following (Java) code:
URL url;
HttpURLConnection urlConnection;
String DOMContent = null;
try {
url = new URL("https://login.microsoftonline.com/");
urlConnection = (HttpURLConnection) url.openConnection();
int responseCode = urlConnection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
DOMContent = readStream(urlConnection.getInputStream());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I need access to the HTML elements of a mobile web page within the Android runtime, just as we would in a web app or extension in a desktop browser. Or in other words, I need to be able to access/manipulate the DOM content of a mobile browser from an Android app.
How can this be done?
Update:
JavaScriptBridge looks promising. DocumentBuilder could help us convert the DOM into Java objects which may then be accessed/manipulated natively from Android.
References:
1. How to execute JavaScript on Android?
2. Calling JavaScript functions in WebView
3. How to run Javascript code in a background Service on Android
4. Is there any way to get access to DOM structure in Android's WebView?
5. Android webview Access the DOM
6. In Android Webview, am I able to modify a webpage's DOM?
7. Android WebViews and the JavaScript to Java bridge
8. Using Javascript bridge in android
9. Alternative way for communication between WebView and native
Use the following code after the page has been loaded (implement a custom WebViewClient and check the onPageFinished)
String query = "document.getElementById(\"WhateverElement\").getBoundingClientRect();"
webView.evaluateJavascript(query, new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // s has the getBoundingClientRect
}
});
The webpage needs to be rendered first in order to get the pixel position of the input field. and to manipulate dom content in android, the best way is to go with JS Interface. The way mentioned by ZUN is also helpful. You can execute arbitrary JavaScript at runtime either way.
However, there is one particular library that can catch your attention i.e. jsoup
From the jsoup website:
jsoup is a Java library for working with real-world HTML. It provides
a very convenient API for extracting and manipulating data, using the
best of DOM, CSS, and jquery-like methods. jsoup implements the WHATWG HTML5 specification and parses HTML to the same DOM as modern browsers do.
Side note: if you don't want to show webpage to the user till all of your calculations are done, you might be interested in playing with Visibility of WebView

Automation server can't create object: ActiveXObject creation error

I have a very simple javascript code in oracle procedure which us used for fetching the Username for Active Directory as my application don't have any user interface.
htp.p('function disp_alert()');
htp.p('{');
htp.p('var WinNetwork = new ActiveXObject("WScript.Network")');
htp.p(' WinNetwork = WinNetwork.UserName');
htp.p('alert(WinNetwork)');
htp.p('}');
It throws exception ActiveXObject creation error: Automation server can't create object
I tried changing browser setting script ActiveX controls marked safe for scripting to enable and it worked.
But in my case the application is accessed by users in client network and we can't tweak security settings for each machine in network. Can anyone suggest an alternative solution or any other method for fetching the windows username?
If you absolutely have to use WScript.Shell for whatever you want to accomplish, you may set the option for your intranet zone by GPO.
You may find the corresponding GPO setting with the help of that site: https://getadmx.com/?Category=InternetExplorer&Policy=Microsoft.Policies.InternetExplorer::IZ_PolicyScriptActiveXMarkedSafe_3

How to execute node function using html button

I'm new at nodejs and I want to write to a serial port using node but now I want it to be triggered by a button. And the data is coming from a textbox.
My node script is doing fine when I run it in the console/terminal. But can't do it with a button in a webpage.
Here's my nodejs embedded in html
<!DOCTYPE html>
<html>
<head>
<title>Node x HTML</title>
</head>
<body>
<script>
function write_serial()
{
var serialport = require("serialport");
var SerialPort = serialport.SerialPort;
var sp = new SerialPort("/dev/ttyACM0", {
baudrate: 9600,
parser: serialport.parsers.readline("\n")
});
var text = document.getElementById("textbox1").value;
sp.on('open', function()
{
sp.on('data', function (data)
{
sp.write(name);
});
});
}
</script>
<Input Type = "text" id = "textbox1" >
<BR>
<br><button onclick="write_serial();" href="javascript:;">Go!</button>
</body>
</html>
Here's the error I got when I open the console of the page (F12)
ReferenceError: require is not defined
Thanks in advance for your help. :)
Node.js is a hosting environment, that can execute JS and provides Node.js specific API. Browser, is a different hosting environment, with different API's. You can't use Node's specific API in a browser, and JS that uses Node API will result in an error in a browser.
For example, your script is using global require function, which is not available in a browser API's. And that's why:
ReferenceError: require is not defined
Conversely, your script can't be executed on Node as well, since it uses browser API:
document.getElementById("textbox1")
You've mixed API's from different environments in one script.
However, if your JS script doesn't use Node or browser specific API, it can be executed in both Node and a browser without an error. But it's not the case with your script.
The solution to your problem can be to split your script into two separate scripts, run one in a browser, and the other in Node.js, and to exchange data between them using XMLHttpRequest.
NodeJS is a non-browser JavaScript environment. You can't use most NodeJS features in a browser environment, because they aren't designed for it.
Instead, you'd have a local NodeJS process providing a web endpoint (e.g., a web server; perhaps using Express, but you don't have to) and run that NodeJS process so it's listening for web requests. Then you'd have a button on your web page that makes an ajax call to the NodeJS server, which performs the work.
Naturally, this would only allow you to perform the work on the machine where the server process is running.
Maybe import the serialport module from https://wzrd.in/standalone/serialport#latest
In other hand, try to seperate the logic from the view, i don't know if your app will grow or if it's just a POC, but use a messageBroker or sockets to bind your actions'view with the engine ?
Hope it helps

How to call AJAX API function from Windows App?

Some company is providing me with web-based API for using their services. I have no problem calling this API functions from within web brower:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript"
src="http://someaddress.com?&key=somekey"></script>
<script type="text/javascript">
var object = new SomeObject();
object.SomeFunction();
</script>
</head>
I am interested in return value of SomeFunction().
How would I get this return value from windows application?
You can use a tool like Firebug. That will let you watch the actual HTTP requests, and step through the JavaScript. In combination, that will let you see where the return value comes from.
Once you understand this, you can replicate the requests (and possibly parts of the JavaScript logic) in your Windows app using an appropriate HTTP client library.
Note that this may be a violation of the TOS.
You can embed web browser control in WinForm and return value from SomeFunction
into some DOM element, then you can access that element from WinForm.WebBrowser1.
There are also javascript emulators available, I think you can even use JSCRIPT dll from c#
but that may not work if SomeFunction() depends on DOM.

Detect if javascript is enabled in a winforms/mfc embedded browser

I have a native (windows) application that has an embedded web browser. Currently I'm invoking a javascript function from the backend (c++/c#). However, if javascript is disabled this fails and I'd like to provide a fallback mechanism. Is there a way to determine if javascript is disabled?
In the IE Web Control, you can simply force JavaScript on. Please refer to the following interfaces, which your host has to implement:
IDocHostUIHandler
IDocHostShowUI
IInternetSecurityManager
IServiceProvider
Another approach would be for your HTML page to query the window.external object and call a method on it, which you implement in your host, which sets a flag to true. Not being called would mean the JavaScript was not executed.
Wow, using web browser under mfc is really pain in the ass, you can do it by getting the IInternetSecurityManager, and check if is enabled to execute javascript by current policy, if user select to disable javascript on his IE, you will need to overwrite the value in the registry.
HRESULT hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL,
CLSCTX_INPROC_SERVER,IID_IInternetSecurityManager, (void**)&pSecurityMgr);
int policy = URLPOLICY_ALLOW;
hr = pSecurityMgr->ProcessUrlAction(L"http://www.google.com", URLACTION_SCRIPT_RUN,
(BYTE*)&policy, sizeof(policy), NULL, 0, PUAF_TRUSTED, 0);
if hr = S_FALSE, javascript execution is disabled...

Categories