Eclipse SWT: Browser#evaluate() always returns null - java

I use SWT Browser object to load a web page like this:
Browser browser = new Browser(parent, SWT.BORDER);
browser.setUrl("http://localhost:18080/app/test-servlet");
I have a function to call the evaluate method. (The function is triggered by clicking a SWT Button on the control.)
public void evaluate() {
Object content = browser.evaluate("getClientContent();");
System.out.println("content: " + content);
}
On the web page, the javascript function getClientContent() is:
<script type="text/javascript">
function getClientContent() {
alert("test");
return "test";
}
</script>
When I click the test button on SWT application, I could see the alert box shown up with "test". But the evaluate() always returns null. What is wrong with the code? Thanks

You need to 'return' the result in the JavaScript, like this:
Object content = browser.evaluate("return getClientContent();");

The return values are restricted to a few types:
Returns the result, if any, of executing the specified script.
Evaluates a script containing javascript commands in the context of
the current document. If document-defined functions or properties are
accessed by the script then this method should not be invoked until
the document has finished loading (ProgressListener.completed() gives
notification of this).
If the script returns a value with a supported type then a java
representation of the value is returned. The supported javascript ->
java mappings are:
*javascript null or undefined -> null
*javascript > number -> java.lang.Double
*javascript string -> java.lang.String
*javascript boolean -> java.lang.Boolean
*javascript array whose elements are all of supported types -> java.lang.Object[]
Try for example
Object result = browser.evaluate("return 1;");
If the return type is not supported ... null seems to be returned.
Try for example
Object window = browser.evaluate("return window;");
The documentation for "evaluate" states
An SWTException is thrown if the return value has an unsupported type, or
if evaluating the script causes a javascript error to be thrown.
which I find misleading since I would expect the above line to throw an exception since the window object can not be returned.

Related

JavaFX WebView: how to check if form is valid?

Is there a way to tell if a form is valid from Java?
Basically, a method that returns true if all input fields constrains are satisfied and false otherwise.
Strangely enough, org.w3c.dom.html.HTMLFormElement doesn't actually have a checkValidity() method.
EDIT:
Even more strangely, the implementation com.sun.webkit.dom.HTMLFormElementImpl does support the method checkValidity(). Unfortunately, the package com.sun.webkit is not accessible directly and thus the method is unavailable.
DOM objects like HTMLFormElement only model structure. They are not capable of executing JavaScript.
However, WebEngine itself does have a JavaScript interpreter, which you can invoke using the executeScript method:
boolean valid = (Boolean) webView.getEngine().executeScript(
"document.forms[0].checkValidity();");
The checkValidity() method is documented here and here.
Cast the form to JSObject
Most HTML Java elements, including HTMLFormElement, can be directly cast to the JavaScript object JSObject. It is then trivial to validate the form.
Example:
JSObject jsObject = (JSObject) form;
boolean valid = (boolean) jsObject.call("checkValidity");

How to send and recive serialized object in jxbrowser from java

I have to send a serialized object from java to javascript with jxbrowser and I do this like this
String json = objectMapper.writeValueAsString(value);
JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty(requestName, json);
As far as I know it will set a object in global window as requestName? It is true?
And in another way how I can read this object from java site. This code is ok?
JSValue window = browser.executeJavaScriptAndReturnValue("window."+requestName);
T t = objectMapper.readValue(window.toString(), clazz))
Thanks in advance
Hi there are two aspects here.
Javascript execution context
JSValue that can be a plain value or a JavaScript object.
Once you invoke executeJavaScriptAndReturnValue your execution context is complete. And you can evaluate the returned object. This returned object can be a Java script object with functions in which case you can access it.
Lets say that your JavaScriptObject has a method helloWorld which accepts string.
JSValue document = browser.executeJavaScriptAndReturnValue("myJavascriptObject");
JSValue write = document.asObject().getProperty("helloWorldMethod");
write.asFunction().invoke(document.asObject(), "To Me");
This way we have passed the "To Me" string to the helloWorldMethod.
You can also set properties on the Object and invoke later another method. If this method uses this property, than within the next execution it will be taken into account:
JSValue document = browser.executeJavaScriptAndReturnValue("myJavascriptObject");
JSValue write = document.asObject().getProperty("helloWorldMethod");
document.asObject().setProperty("shouldISayGoodByeInstead",true)
write.asFunction().invoke(document.asObject(), "To Me");
The property shouldISayGoodByeInstead will be evaluated as part of the second execution which happens when helloWorldMethod is invoked, not during the first execution of executeJavaScriptAndReturnValue.
If I understand you correctly, you want to set a JavaScript object through JSON. This can be achieved via the JSONString. You can check the example here: https://jxbrowser.support.teamdev.com/support/solutions/articles/9000013064-working-with-json
After that, you want to get the JSON object. For this case, there is a method
JSObject.toJSONString()
So if we change your sample in the following way, it should work as expected:
String json = objectMapper.writeValueAsString(value);
JSValue window = browser.executeJavaScriptAndReturnValue("window");
window.asObject().setProperty(requestName, new JSONString(json));
JSValue window = browser.executeJavaScriptAndReturnValue("window."+requestName);
T t = objectMapper.readValue(window.asObject().toJSONString(), clazz))

doEval() With Multiline String Argument

Using Groovy 2.3.6, GMongo 1.2, Java 1.8, MongoDB 3.0.0...
I'm trying to use doEval() to get a count of documents in a collection. (For various reasons I want to use doEval() rather than count()). Invoking doEval() with a single line string argument returns retval with a double value of 1.0 and ok with a double value of 1.0 which is what I expect:
def str = "db.configurations.count({name: 'Mike'})"
database.doEval(str)
If the argument is on multiple lines retval that is returned is null (ok is 1.0).
def str = "db.configurations.count({\nname: 'Mike'\n})"
database.doEval(str)
I expect doEval to return a retval of 1.0 not null, like in the first example. Is this a bug or is my expectation incorrect? Should doEval() support a multiline string argument?
From doEval() javadoc:
Evaluates JavaScript functions on the database server. This is useful
if you need to touch a lot of data lightly, in which case network
transfer could be a bottleneck.
Parameters:
code - String representation of JavaScript function
args - arguments to pass to the JavaScript function
So you are not passing a javascript function to doEvalmethod. Anyway, the result you are getting is consistent with the result you can get invoking directly the mongo shell:
> db.eval("db.configurations.count({name: 'Mike'})");
1
> db.eval("db.configurations.count({\nname: 'Mike'\n})");
null
(I did not dig deeper on mongo shell javascript internals... :-)
Passing a javascript function you can get the result you want:
println db.configurations.count([name: 'Mike'])
def str = '''function(name) {
return db.configurations.count({
name: name
});
}'''
println db.doEval(str, 'Mike')
The above yields:
1
[serverUsed:/127.0.0.1:27017, retval:1.0, ok:1.0]

Passing nullable parameters to a Page via PageParameters in Wicket 6

I need to pass a parameter to my page and I can't find a way to pass parameters that might be null.
If I do:
PageParameters pageParameters = new PageParameters ();
pageParameters.add ("key", null);
This will result in an exception
java.lang.IllegalArgumentException: Argument 'value' may not be null.
at org.apache.wicket.util.lang.Args.notNull(Args.java:41)
If I use Google Guava's Optional, I can't find any way to cast the object even if the the Optional object is not holding a null ie not equals to Optional.absent() :
In my landing page's constructor I do
StringValue sv = parameters.get ("key");
sv.to ( Optional.of (MyEnum.SOME_ENUM_CONSTANT).getClass () );
and when I run it I get this error:
org.apache.wicket.util.string.StringValueConversionException: Cannot
convert 'Optional.of(SOME_ENUM_CONSTANT)'to type class
com.google.common.base.Present.
Am I doing something wrong?
Is there any other way to pass a possibly null object in wicket 6?
I noticed in wicket 1.4 they have PageParameters.NULL which seems to have dissapeared in wicket 6.
Thank you
This might be too simple, but what's wrong with
Object value = ?
if (value != null) {
pageParameters.add ("key", value);
}
and
StringValue sv = pageParameters.get("key");
if (!sv.isNull()) {
// process string value
}
All page parameters in wicket will be treated as Strings eventually. The idea is that a page parameter will be on the URL of the request.
From the javadoc:
Suppose we mounted a page on /user and the following url was accessed /user/profile/bob?action=view&redirect=false. In this example profile and bob are indexed parameters with respective indexes 0 and 1. action and redirect are named parameters.
If you add something like x=y&x, the parameter x will appear twice, once with the String y and another with the empty string.
Depending on what you are trying to accomplish I would suggest to either
Don't pass the parameter at all when there is a null value required and use the isNull or toOptional methods.
Use indexed parameters and test for presence of a certain word

Rhino: How to return a string from Java to Javascript?

How do I use Rhino return a string from Java to Javascript, all I get is org.mozilla.javascript.JavaNativeObject when I use
var jsString = new java.lang.String("test");
inside my js file.
Is this the right way to do it?
var jsString = String(new java.lang.String("test"));
The goal is to have a Java method to return the String object instead of creating it on the fly like above.
In general, you would call Context.javaToJS which converts a Java object to its closest representation in Javascript. However, for String objects, that function returns the string itself without needing to wrap it. So if you're always returning a string, you don't need to do anything special.
Although in most cases the returned Java String type can be used just like the JS String type within the JS code, it does not have the same methods!
In particular I found it cannot be used in a JS object passed to 'stringify()' as it does not have the toJSON() method.
The only solution I found is to explicitly do the addition of "" in the JS, to convert the Java String to a JS String. I found no way to code the java method to return a good JS string directly... (as Context.javaToJS() doesn't convert a Java String)
Eg:
var jstr = MyJavaObj.methodReturningAString();
JSON.stringify({ "toto":jstr}); // Fails
JSON.stringify({ "toto": ""+jstr}); // OK
Turn off the wrapping of Primitives and then the value returned in your expression will be a JS string:
Context cx = Context.enter();
cx.getWrapFactory().setJavaPrimitiveWrap(false);
For me this is a Rhino bug. The s+"" trick inside JavaScript works, but here's a quick patch to fix it Java-side - after this line in NativeJavaMethod.call()
Object retval = meth.invoke(javaObject, args);
add this check to convert it to a native JavaScript string (ie typeof returns "string" not "object")
if (retval instanceof String) {
return NativeJavaObject.coerceTypeImpl(String.class, retval);
}
This is important otherwise s.replace() calls the Java version so is wrong for eg "h e l l o".replace(" ", "")
https://github.com/mozilla/rhino/issues/638

Categories

Resources