Calling a Specific Web Service Method Using Javascript or jQuery - javascript

I've successfully invoked a web service when loading a jsp page. The issue I'm facing is setting up a user to be able to press a button to invoke a different method on that same web service. The function "getSS()" is supposed to accomplish this, but I suppose that javascript doesn't directly read that type of invocation. I've found solutions that call up the web service and pass a parameter to it, but those are usually not calling up specific methods within the webservice.
Here is my code, what can I put in the "getSS()" function to accomplish this? I've already loaded jQuery, and the web service is written in java. Note, I already wrote the code to do all the work, I just need to know how to call that specific code. None of the other solutions seem to fit my needs.
<%--
Document : index
Created on : May 6, 2016, 9:39:44 AM
Author : mmarino
--%>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script type="text/javascript">
function getSS(){
var e = document.getElementById("names");
var daString = e.options[e.selectedIndex].value;
try {
org.me.calculator.CalculatorWS_Service service = new org.me.calculator.CalculatorWS_Service();
org.me.calculator.CalculatorWS port = service.getCalculatorWSPort();
// TODO process result here
java.lang.String result = port.SS(daString);
document.getElementById('inputhere').innerHTML = "hi";
} catch (Exception ex) {
// TODO handle custom exceptions here
document.getElementById('inputhere').innerHTML = ex;
}
}
</script>
</head>
<body>
<h1>Hello World!</h1> <%-- start web service invocation --%><hr/>
<button value="hi" onclick="getSS()"> Click</button>
<select id="names">
<%
try {
org.me.calculator.CalculatorWS_Service service = new org.me.calculator.CalculatorWS_Service();
org.me.calculator.CalculatorWS port = service.getCalculatorWSPort();
// TODO process result here
java.lang.String result = port.getNames();
out.println(result);
} catch (Exception ex) {
// TODO handle custom exceptions here
}
%>
<%-- end web service invocation --%>
</select>
<hr/>
<div id="inputhere">Hi.</div>
</body>

So it seemed all I was missing was setting that java code to a variable and putting the proper opening and closing statements:
function doIt(){
<%-- start web service invocation --%>
var x = <%
try {
org.me.testbilling.TestBillingWS_Service service = new org.me.testbilling.TestBillingWS_Service();
org.me.testbilling.TestBillingWS port = service.getTestBillingWSPort();
// TODO initialize WS operation arguments here
java.lang.String name = "Marcel" ;
// TODO process result here
java.lang.String result = port.getSS(name);
out.println(result);
} catch (Exception ex) {
// TODO handle custom exceptions here
}
%>
<%-- end web service invocation --%>
alert(x);
}
</script>
Still not quite sure how to make that "java.lang.String name =" be set to a javascript variable.

Related

Silence net::ERR_CONNECTION_REFUSED

Connecting to a non-existent web socket server results in loud errors being logged to the console, usually to the tune of ... net::ERR_CONNECTION_REFUSED.
Anyone have an idea for a hackaround to silence this output? XMLHttpRequest won't work since it yields the same verbose error output if the server is not reachable.
The goal here is to test if the server is available, if it is then connect to it, otherwise use a fallback, and to do this without spamming the console with error output.
Chrome itself is emitting these messages, and there is no way to block them. This is a function of how chrome was built; whenever a ResourceFetcher object attempts to fetch a resource, its response is passed back to its context, and if there's an error, the browser prints it to the console - see here.
Similar question can be found here.
If you'd like, you can use a chrome console filter as this question discusses to block these errors in your console, but there is no way to programmatically block the messages.
I don't know why do you want to prevent this error output. I guess you just want to get rid of them when debugging. So I provide a work around here may be just useful for debugging.
Live demo: http://blackmiaool.com/soa/43012334/boot.html
How to use it?
Open the demo page, click the "boot" button, it will open a new tab. Click the "test" button in the new tab and check the result below. If you want to get a positive result, change the url to wss://echo.websocket.org.
Why?
By using post message, we can make browser tabs communicate with each other. So we can move those error output to a tab that we don't concern.
P.S. You can refresh the target page freely without loosing the connection between it and boot page.
P.P.S You can also use storage event to achieve this.
boot.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>boot page</title>
</head>
<body>
<button onclick="boot()">boot</button>
<p>BTW, you can boot the page without the button if you are willing to allow the "pop-up"</p>
<script>
var targetWindow;
function init() {
targetWindow
}
function boot() {
targetWindow = window.open("target.html");
}
boot();
window.addEventListener('message', function(e) {
var msg = e.data;
var {
action,
url,
origin,
} = msg;
if (action === "testUrl") {
let ws = new WebSocket(url);
ws.addEventListener("error", function() {
targetWindow.postMessage({
action: "urlResult",
url,
data: false,
}, origin);
ws.close();
});
ws.addEventListener("open", function() {
targetWindow.postMessage({
action: "urlResult",
url,
data: true,
}, origin);
ws.close();
});
}
});
</script>
</body>
</html>
target.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>target page</title>
</head>
<body>
<h4>input the url you want to test:</h4>
<textarea type="text" id="input" style="width:300px;height:100px;">
</textarea>
<br>
<div>try <span style="color:red">wss://echo.websocket.org</span> for success result(may be slow)</div>
<button onclick="test()">test</button>
<div id="output"></div>
<script>
var origin = location.origin;
var testUrl = origin.replace(/^https?/, "ws") + "/abcdef"; //not available of course
document.querySelector("#input").value = testUrl;
function output(val) {
document.querySelector("#output").textContent = val;
}
function test() {
if (window.opener) {
window.opener.postMessage({
action: "testUrl",
url: document.querySelector("#input").value,
origin,
}, origin);
} else {
alert("opener is not available");
}
}
window.addEventListener('message', function(e) {
var msg = e.data;
if (msg.action === "urlResult") {
output(`test ${msg.url} result: ${msg.data}`);
}
});
</script>
</body>
</html>

jsp : Could I change the order of render/execution

I am working on jsp,
What I am trying to implement is quite simple.
do some time-consuming work with Java
while processing, show users the spinner
So I have implemented like below
<%# page contentType="text/html; charset=UTF-8" %>
<%# page isThreadSafe="true" %>
<%
boolean isFinish = false;
Thread executeThread = new Thread(new Runnable() {
#Override
public void run() {
for(int i = 0; i < 10; i++){
try{
System.out.println(i + " Thread ");
Thread.sleep(1000);
}catch(Exception ex){
System.err.println(ex);
}
}
}
});
executeThread.run();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Loading</title>
</head>
<body>
<div class="popup" style="text-align: center;">
<div class="l_img">
<img src="resources/image/spinner/loading_gif.gif" alt="LOADING...">
</div>
<div class="b_txt">Processing</div>
<div class="s_txt">Please, wait..</div>
</div>
</body>
<%
if(isFinish){
%>
<script>
alert('done');
</script>
<%
}
%>
</html>
However, page shows up after Thread has terminated. Could I reverse the order?
What I wanted in order
show html page(spinner gif)
execute Java logics
catch the return of Java execution
if return is true, then alert with javascript
Is it possible?
Thanks for your answers
You can't do a server-side operation change dinamically the render the page.
the page will be rendered always where if(isFinish) has been executed.
the server will send the complete html page to the user only when all the java has been executed and in one block! you need to implement it on the front-end, for example you send a starting basic page of loading and you call the long term process with a ajax call or something similar.
<!DOCTYPE html>
<html>
<body onload="alert('done')">
Put your spinner here.
Some text here is necessary here for the browser to start displaying.
Otherwise it will wait until it receives enough of a response to begin displaying anything.
I am not sure how much is necessary. This works for me.
<%
out.print("<br/>Starting processing now. <br/>");
out.flush();
Thread.sleep(2000);
out.print("<br/>Processing..... <br/>");
out.flush();
for(int x = 1; x < 4; x++){
Thread.sleep(2000);
out.print("Result " + x + ".<br/>");
out.flush();
}
%>
</body>
</html>

Load a javascript method from Android Webview

I am trying to render a chart in an Android WebView using HighCharts.
What my app does should be simple :
- Load the HTML page and external (but local) css and js files
- Load data from the Java part of the app
- Call a javascript function with the previously-loaded data as a parameter
I setup my webview by activating Javascript :
mWebView.getSettings().setJavaScriptEnabled(true);
And also by setting a WebClient to catch javascript's console messages :
mWebView.setWebChromeClient(new WebChromeClient() {
public boolean onConsoleMessage(ConsoleMessage cm) {
Log.d(TAG, cm.message() + " -- From line "
+ cm.lineNumber() + " of "
+ cm.sourceId() );
return true;
}
});
This is my HTML page :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="style.css" />
<title>Chart</title>
<script src="jquery.js"></script>
</head>
<body>
<script src="highstock.js"></script>
<script src="exporting.js"></script>
<script language="javascript">
function plot() {
console.log("Hello !");
}
</script>
<div id="container" style="height: 100%; width: 100%"></div>
</body>
</html>
I load this page from the app's assets by calling
mWebView.loadUrl("file:///android_asset/page.html");
My external CSS file seems to be read and I suppose the external JS files are also correctly loaded
I read everywhere that I can call my javascript method anytime by calling
mWebView.loadUrl("javascript:plot()");
However, I always get the error
Uncaught ReferenceError: plot is not defined -- From line 1 of null
Is there anything I might have forgotten ?
Note that I load my page and call the javascript method right after the loadUrl call.
Thanks !
Ok, I'm sorry for your time loss. I was looking for an answer for hours, and then within 15 minutes of posting the question I found the solution.
The problem seemed to be the two consecutive calls to loadUrl. Maybe the page wasn't properly loaded yet while I was already calling the javascript function.
I added a load listener on the WebView like this
mWebView.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (url.equals("file:///android_asset/page.html")) {
mWebView.loadUrl("javascript:plot();");
}
}
});
so that I call the javascript method only when the page is completely loaded.
Now it works properly on every call.
Thank you again for your attention !
Try this:
<body>
<script src="highstock.js"></script>
<script src="exporting.js"></script>
<script language="javascript">
function plot() {
console.log("Hello !");
}
plot(); //Note the calling of the function within the HTML file once loaded into webView
</script>
<div id="container" style="height: 100%; width: 100%"></div>
</body>
And remove the line:
mWebView.loadUrl("javascript:plot()");
If you want to pass data to your javascript function, hen send your data through the URL like this:
mWebView.loadUrl("file:///android_asset/page.html?data=something");
and use:
var param1var = getQueryVariable("data");
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if (pair[0] == variable) {
return pair[1];
}
}
alert('Query Variable ' + variable + ' not found');
}
in your JavaScript like what is done here. You can also check out this example.

Play Framework 2.1 websockets in Chrome

I can't seem to get websocket communication to work in the Play Framework version 2.1.
I created a simple test that does nothing but send messages back and forth with a push of a button. All the code for it is below. But nothing shows up except for the button.
Has anybody seen this problem or can someone tell me what I may be doing wrong in the code below?
I am using the latest version of Chrome.
Here is my simple setup.
In Application.java
public static Result index() {
return ok(index.render());
}
public static WebSocket<String> sockHandler() {
return new WebSocket<String>() {
// called when the websocket is established
public void onReady(WebSocket.In<String> in,
WebSocket.Out<String> out) {
// register a callback for processing instream events
in.onMessage(new Callback<String>() {
public void invoke(String event) {
System.out.println(event);
}
});
// write out a greeting
out.write("I'm contacting you regarding your recent websocket.");
}
};
}
In Routes File
GET / controllers.Application.index()
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.at(path="/public", file)
GET /greeter controllers.Application.sockHandler()
In Index.Scala.html
#main(null) {
<div class="greeting"></div>
<button class="send">Send</button>
<script type="text/javascript" charset="utf-8">
$(function() {
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
var sock = new WS("#routes.Application.sockHandler()")
sock.onmessage = function(event) {
$('.greeting').append(event.data)
}
$('button.send').click(function() {
sock.send("I'm sending a message now.")
});
})
</script>
}
In Main.scala.html
#(title: String)(content: Html)
<!DOCTYPE html>
<html>
<head>
<title>#title</title>
<link rel="stylesheet" media="screen" href="#routes.Assets.at("stylesheets/main.css")">
<link rel="shortcut icon" type="image/png" href="#routes.Assets.at("images/favicon.png")">
<script src="#routes.Assets.at("javascripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
</head>
<body>
#content
</body>
The problem is in
var sock = new WS("#routes.Application.sockHandler()")
you have to specify the protocol and the complete url in the format: ws://localhost:9000/greeter.
Check this question to do it in javascript: How to construct a WebSocket URI relative to the page URI?
you can use a Route's webSocketURL() method to retrieve a url that can be passed to a WebSocket's constructor. Here's an example from Play's websocket-chat sample code:
$(function() {
var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
var chatSocket = new WS("#routes.Application.chat(username).webSocketURL()")
var sendMessage = function() {
chatSocket.send(JSON.stringify(
{text: $("#talk").val()}
))
$("#talk").val('')
}
// ...
So in your code you can use something like
var sock = new WS("#routes.Application.sockHandler().webSocketURL()");
Personally I don't like intermingling interpolated code with JS, since I think that any code executing on the client should only be concerned with the state of the client, and not the server (not to mention it makes refactoring the script out into an external file impossible), so I tend to do something like this:
<div class="container app-container"
data-ws-uri="#routes.Application.WSUri.webSocketURL()">
.......
</div>
Then in my JS I can just do something like
var sock = new WS(document.querySelector(".app-container").dataset.wsUri);
// ....

HTML5 Web SQL Transactions skipped without error when touch triggered in IOS

I'm experiencing problems making database transactions on IOS devices.
If the user doesn't touch the phone, everything works like expected.
If the user taps/scrolls/touches the screen, some transactions directly call their successCallback, without ever calling the actual transaction callback.
Simplified example here: http://jsfiddle.net/Tk9rv/
To test, just open http://jsfiddle.net/Tk9rv/embedded/result/ in your mobile safari on IOS and do not touch the device while loading. You will see a list of debug messages being generated looking like this:
database is running
table will be cleared
store method called for '10'.
about to insert '10'.
transaction successful for '10'
store method called for '9'.
about to insert '9'.
transaction successful for '9'
store method called for '8'.
about to insert '8'.
transaction successful for '8'
[...]
Now, reload the page and while loading, scroll and tap randomly.
You will see some "about to insert..." messages are missing.
database is running
table will be cleared
store method called for '10'.
about to insert '10'.
transaction successful for '10'
store method called for '9'.
about to insert '9'.
transaction successful for '9'
store method called for '8'.
transaction successful for '8' <-- WHERE IS MY "about to insert '8'." ???
store method called for '7'.
about to insert '7'.
transaction successful for '7'
[...]
This is because the transactionCallback is completely skipped! But WHY? And WHY does the successCallback fire instead of the errorCallback?
[This is a simplified example, please do not tell me not to do this setTimeout stuff. In the real world, there is data being loaded async and then being inserted... :) ]
I think there is a similar problem here HTML5 Web SQL transaction Missing In Action but there is no solution or hint either.
Any ideas? I'm stuck... Thanks!
Our testing showed that this behaviour would also occur whenever the keyboard was displaying and would prevent transactions in an onblur or onfocus event (although, not onkey{down|up|press}). Using setTimeout would cause terrible performance issues. We had found that the .transaction() success callback would be triggered, even if the transaction callback was not called, so came up with this method that works well for us:
var oldOpenDatabase = window.openDatabase;
window.openDatabase = function() {
var db = oldOpenDatabase.apply(window, arguments);
var oldTrans = db.transaction;
db.transaction = function(callback, err, suc) {
var db = this;
var params = arguments;
var hasRun = false;
oldTrans.call(db, function(tx){
hasRun = true; callback(tx);
}, err||function(){}, function(tx) {
if(hasRun){
if (suc != undefined)
suc(tx);
return;
}
else {
oldTrans.apply(db, params);
}
});
}
return db;
}
This code checks that the transaction callback has fired in the success handler and, if not, gives it another chance.
Web Workers and OpenDatabaseSync fix the same problem on my site. Except web workers are not supported on iOS4.x and Android so we can implement the old way for those and web workers on iOS5.
The very basic example below uses a loop to do a single insert 500 times writing to the screen after each insert. At the end a query is made to return the number of rows in the table. Now we can see transactions are not skipped even with a lot of scrolling.
This example is designed so you can test the resilience to scrolling during the inserts on iPhone or iPad.
Two pages are required, an html page and separate javascript file for the worker. So for the html page;
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<title></title>
<script src="../scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
<style type="text/css">
body
{
background-color:Black;
}
.number
{
color:#00FF00;
font-family:Courier New;
font-size:12pt;
}
button
{
position:fixed;
right:5px;
top:5px;
padding:15px;
}
</style>
<script type="text/javascript">
var worker;
$(document).ready(function () {
worker = new Worker('worker1.js');
worker.addEventListener('message', function (e) {
$("#test").html(new Date().toLocaleTimeString() + " " + e.data.message + "<BR/>" + $("#test").html());
if (e.data.complete == true) {
worker.terminate();
}
}, false);
});
function stop() {
worker.terminate();
}
</script>
</head>
<body>
<form id="form1" onsubmit="return false">
<div id="test" class="number">
<button onclick="stop()">Stop</button>
</div>
</form>
</body>
</html>
and worker1.js ;
var wdb = {};
wdb.db = openDatabaseSync('test', '1.0', 'DB test', 1024);
doQuery("CREATE TABLE IF NOT EXISTS test(abc INTEGER PRIMARY KEY);");
doQuery("DELETE FROM test"); // optional
for (var i = 0; i < 500; i++) {
doQuery("INSERT INTO test(abc) VALUES( " + i + " );");
postMessage({ message: "Inserted " + i.toString(), complete: false });
}
var summary= doQuery("SELECT COUNT(*) AS Total FROM test;");
postMessage({ message: "Found " + summary.item(0).Total.toString() + " rows", complete: true });
function doQuery(sql) {
wdb.db.transaction(function (tx) {
rs = tx.executeSql(sql, []);
});
return rs.rows;
}

Categories