I'm new to JavaScript environment and it's the one running on the system i'm newly at.
We're using GWT for JavaScript.
What is the best way to detect the connections between the back-end processes
and front-end actions? Eg. which back-end method is invoked when "that" button is pressed, tab is clicked,
window is opened, ... .
The only way I can think of is using the debugger and Eclipse search/call hierarchies facilities: keep putting breakpoints
in places where I anticipate will run-- until i hit the spot.
Is/n't there a more efficient way of doing this?
How do other developers do?
I'm a back-end developer.
In a previous system, I put a port monitor-- Fiddler,
saw the contents of the request the FE is sending and went from there.
I'm aware that this is a naive Q-- please bear with me.
TIA.
//======================
EDIT:
the best would be a
debugger-like tool showing the stack-trace, or even the
execution path in any way, telling the back-end methods that are running and/or spawning the threads.
is there such a tool?
The following takes for granted that you are using a decent IDE and that you have imported the GWT project into such IDE. There's some help at the end if this is not your case.
If you know which Java class contains the front-end logic, and the element you're interested in
Find the object representing the element (a Button, a ListBox, whatever) and look at the event handlers attached to it.
Something like this:
//...
#UiField
ListBox myDropDownList;
//...
myDropDownList.addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent changeEvent) {
SomeService.someRPCmethod(... params, callback, ...);
}
});
The SomeService.someRPCmethod method implementation should contain all the backend calls.
If you know the Java class, but not which one of all the buttons is the one you're looking for
Most GWT apps make use of *.ui.xml files which are like a skeleton for the actual web page. This XML files reference the actual Java objects used in the Java class, and are usually named like the class they represent.
Locate the ui.xml file and look for something like this:
...
<g:ListBox ui:field="myDropDownList" styleName="cssClassName"/>
...
This should appear in your webpage like this:
<select class="cssClassName" ...>
<option ...>
The position inside the XML file, and the CSS class name, should help you pinpoint the element you're looking for. Once you find it, the ui:field attribute points to the Java object (try ctrl+clicking it in your IDE).
Now you just have to look at the handlers as explained before.
If you don't know the Java class which contains the front-end logic
To find the Java class for a given webpage, you can resort to the good ol' string search.
Locate a not-so-common string literal used in the web page. Not something like "Add" but more like "User registration".
Use your IDE to search the project's code base for that string. It should appear inside a .properties file, or a class with constants and literals, or maybe even hardcoded inside the front-end Java class.
Now just use your IDE to follow the references. It might be something like .properties file -> Constants interface -> .ui.xml file -> front-end Java class, or literals Java class -> front-end Java class.
If you don't have access to the front-end source code
You can try to use your Developer Tools / Fiddler to look for REST calls, which is how GWT implements RPC.
So the call to SomeService.someRPCmethod above might appear in Fiddler as a http:://yourwebpage/somepath/SomeService call with a bunch of GET/POST parameters, one of which should be someRPCmethod (the method's name). But this is not always the case.
If you're running GWT 2.6+ in SuperDev mode with Sources enabled, you can also try to debug the Javascript in the front-end until you reach the RPC calls. See abhinav3414's answer.
Last (or maybe first!) resource
Ask the front-end developers, they put the calls in there and can get you on track in minutes ;)
I had similar issue, so I installed an extension in my chrome.Below is the name of the extension. You can try once.
Visual Event 2.1
Know what event is bound on each dom element
There is one more approach, You can debug your code from front end. You can inspect element in your browser and then open Source tab.
Press ctrl + P to search the file in which you want to put the debug points.
Put debug points by clicking on the row number.
This way you need not to go to eclipse that often.
I would start by searching the code for the listeners of whatever events you are interested in and go from there. I work in EXT JS and I do this all the time.
Following all code paths through is the only guarantee unless all calls to the backend go through some known class.
Monitoring the network is also a good way to go.
This can be done in Chrome through the "Developer Tools" on the Network tab.
In GWT you have on the client side "import java.util.logging.Logger;" which output your debug info to the browsers console. On the server side you just use "System.out.println("debug");" for debugging which goes to the Apaches Tomcat log files. Which makes debugging on a live server a bit easier.
GWT uses RPC's for communication between the client and server. The data sent is serialized and can be a whole class if needed. The three folder for source in a module as 'client', 'server' and 'shared'.
For example a shared class used for sending data back and forth: (The blank constructor is required to serialise the class)
public class MySharedData implements Serializable {
private static final long serialVersionUID = 1987236748763652L; // used for serializing data
public List<String> lotsOfStrings = new ArrayList<String>(); // use most java vars
public int width, height;
public MySharedData() {} // 'need' a blank constructor
public MySharedData(MySharedData data) { //do stuff } // also can
}
On the server side it may look something like this:
public class MyServerRPCImpl extends RemoteServiceServlet implements MyServerRPC {
private static final long serialVersionUID = 4435555929902374350L;
public List<String> getStringList(int var, List<String> strs) {
// do stuff
System.out.println("debugging output"); // to tomcat log file
return stringList;
}
}
The client will use an Asynchronous callback with two methods, onSuccess() and onFailure() so you can handle call failures. To use this is something along the lines of:
public class MyGWTApp implements EntryPoint {
// the server RPC class
final MyServerRPCAsync server = GWT.create(MyServerRPC.class); // create RPC instance
final Logger log = Logger.getLogger("tag");
public void doSomething() {
MySharedData data = new MySharedData();
server.getStringList(data, new AsyncCallback<List<String>>() {
#Override
public void onFailure(Throwable caught) {
log.info("error"); // logging goes to the javascript console output
}
#Override
public void onSuccess(List<String> result) {
log.info("call worked");
}
};)
}
}
The above is my way of managing logging as my projects have to run straight from a Tomcat server. I also believe the server logging when run from Eclipse will go to Eclipse's console log, but I'm unsure on that. All server output and errors, including stack traces will be in the /var/log/tomcat/ folder on linux, or the equivalent on Windows. I can honestly say, I've yet not used breakpoints debugging with GWT.
Client and server code is in separate classes in their own folders within the project.
Just want to mention that sometimes debugger is used in situations where other tools can also help (not sure if this is the situation here - but bear with me just another two sentences):
(1) you can grep the relevant html asset , grep is a wonderful tool to learn large systems
(2) you can add log , in some cases you can switch to debug mode and see tons of log traces
Use Network tab in developer tools of your preferred browser you are using to test.
CHROME
Press F12 or alternatively choose from menu - tools > developer tools
FIREFOX
Press F12 or alternatively choose from menu - Developer > toggle tools
IE
Press F12
Related
I am sorry if this is an unclear title because I do not know all the terminology, so please bear with me.
So I am trying to create a controlled environment to run any JavaScript code in a Java application. Note: code is created by a user so I have to block/prevent code that is specifically trying to access/modify java variables that are not supposed to be at reach. (preferably by throwing a compile error for user feedback)
Edit 1: By the way I tried to use Rhino and Nashorn.
Here is a simple example.
public class ScriptRunner{
public Foo foo=new Foo();
//this is not supposed to be accessed by the script
public int money=0;
public Object run(){
return compiler.compile(STRING START (obtained from a file)
function main(someObject){
//this is not allowed
someObject.money=10000000000000000000000;
//or this
var someBlacklistedJavaObject=.....
someBlacklistedJavaObject.someFuncton();
//but this is allowed
someObject.foo.name="Bob";
return someObject.foo.someFunction();
}
STRING END).run("main",this);
}
}
Also I am not sure if this would be one of the possible solution but I can't use the built in java security class due to some unreachable code implementing it and not allowing to set the security object to anything else.
What comes to my mind is that an easy implementation of this would be to create wrapper Java classes in some package. Than check if a java object in script does not have that path and throw an error. But the problem is that I have no idea how to do that.
Here is a simple visualization of what I am trying to do.
Edit 2: It is desirable to maintain a low Java compatibility profile, but it's not 100% necessary.
Use a ClassFilter with Nashorn (note: requires Java >= 1.8.0_40)
I am writing a Selenium script to test a Chrome app that uses the Chrome.fileSystem.chooseEntry API to select a directory. When I do this manually, it works fine. But when I do this in a Selenium script, I get back this error:
Unchecked runtime.lastError while running fileSystem.chooseEntry: Invalid calling page. This function can't be called from a background page.
Any ideas on how to make Selenium and chooseEntry play nicely together?
I updated to the latest Chromedriver, but still no luck. I also looked at ChromeOptions, but didn't see anything that looked like it would be helpful. The interwebs doesn't seem to have much to say about Selenium and chooseEntry. I'm on version 51 of Chrome.
I'm down to thinking I'll need a special javascript entry point to set the path values for testing instead of using chooseEntry. But I would strongly prefer to not have a separate code execution path for my tests. Anybody have a cleaner solution?
EDIT: per commenter's request, here's the offending code:
chrome.fileSystem.chooseEntry({type:'openDirectory'},function(entry) {
chrome.fileSystem.getWritableEntry(entry,function(writeable_entry) {
console.log("got writeable entry");
});
}, function(e) { errorHandler(e); });
EDIT #2: I've gone with the special javascript entry point hack. In manual mode -- i.e., not running under Selenium -- I run code that executes chooseEntry, and then use the retainEntry API to get the entry id. I added an entry point in my javascript to take an entry id and call the restoreEntry API to turn it back into an entry. I also modified my code so if this entry object is set, then use that as the file instead of calling chooseEntry. Lastly, I modified my Selenium script to call the restoreEntry entry point before running the rest of the script.
This is not ideal, since now my test code execution path is somewhat different from my actual live-human-being-at-the-controls code execution path. But at least it lets me use Selenium scripts now. Of course, if anyone can think of a non-horrible way to solve this solution, I'd love to hear about it.
EDIT #3: Per #Xan's comment, corrected my terminology from "extension" to "Chrome App."
I can only offer this horrible hack. For Chrome Apps under OSX I created folder favorites and use Robot keyPress to navigate and select the 'favorite' folders needed for the App. The only possible redeeming factor is that it does mirror a valid/possible actual human interaction with the file interface.
private void selectOSXFolderFavorite(int favorite) {
// With an OSX file folder dialog open, Shift-Tab to favorites list
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_TAB);
robot.keyRelease(KeyEvent.VK_SHIFT);
// move to the top of favorites list
int i = 40;
while (i-- > 0) {
robot.keyPress(KeyEvent.VK_UP);
robot.keyRelease(KeyEvent.VK_UP);
}
while (favorite-- > 0) {
robot.keyPress(KeyEvent.VK_DOWN);
robot.keyRelease(KeyEvent.VK_DOWN);
}
// Send an enter key to Select the selected folder
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
}
Well here's a problem.
I've got a website with large javascript backend. This backend talks to a server over a socket with a socket bridge using http://blog.deconcept.com/swfobject/
The socket "bridge" is a Flex/Flash .swf application/executable/plugin/thing for which the source is missing.
I've got to change it.
More facts:
file appExePluginThing.swf
appExePluginThing.swf Macromedia Flash data (compressed), version 9
I've used https://www.free-decompiler.com/flash/ to decompile the .swf file and I think I've sorted out what's the original code vs the libraries and things Flash/Flex built into it.
I've used FDT (the free version) to rebuild the decompiled code into MYappExePluginThing.swf so I can run it with the javascript code and see what happens.
I'm here because what happens isn't good. Basically, my javascript code (MYjavascript.js) gets to the point where it does
window.log("init()");
var so = new SWFObject("flash/MYappExePluginThing.swf"", socketObjectId, "0", "0", "9", "#FFFFFF");
window.log("init() created MYappExecPluginThing!!!");
so.addParam("allowScriptAccess", "always");
log("init() added Param!!");
so.write(elId);
log("init() wrote!");
IE9's console (yeah, you read that right) shows
init()
created MYappExecPluginThing!!!
init() added Param!!
init() wrote!
but none of the debugging i've got in MYappExePluginThing.as displays and nothing else happens.
I'm trying to figure out what I've screwed up/what's going on? Is MYappExePluginThing.as running? Is it waiting on something? Did it fail? Why aren't the log messages in MYappExePluginThing.as showing up?
The first most obvious thing is I'm using FDT which, I suspect, was not used to build the original. Is there some kind of magic "build javascript accessible swf thing" in FlashBuilder or some other IDE?
First noteworthy thing I find is:
file MYappExePluginThing.swf
MYappExePluginThing.swf Macromedia Flash data (compressed), version 14
I'm using Flex 4.6 which, for all I know, may have a completely different mechanism for allowing javascript communication than was used in appExePluginThing.swf
Does anyone know if that's true?
For example, when FDT runs this thing (I can compile but FDT does not create a .swf unless i run it) I get a warning in the following method:
private function init() : void
{
Log.log("console.log", "MYappExePluginThing init()");
//var initCallback:String = Application.application.parameters.initCallback?Application.application.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
var initCallback:String = FlexGlobals.topLevelApplication.parameters.initCallback?FlexGlobals.topLevelApplication.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
try
{
ExternalInterface.addCallback("method1Callback",method1);
ExternalInterface.addCallback("method2Callback",method2);
ExternalInterface.call(initCallback);
}
catch(err:Error)
{
Log.log("console.log", "MYappExePluginThing init() ERROR err="+err);
}
}
I got a warning that Application.application was deprecated and I should change:
var initCallback:String = Application.application.parameters.initCallback?Application.application.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
to:
var initCallback:String = FlexGlobals.topLevelApplication.parameters.initCallback?FlexGlobals.topLevelApplication.parameters.initCallback:"MYjavascript.MYappExePluginThing_init";
which I did but which had no effect on making the thing work.
(FYI Log.log() is something I added:
public class Log{
public static function log(dest:String, mssg:String):void{
if(ExternalInterface.available){
try{
ExternalInterface.call(dest, mssg);
}
catch(se:SecurityError){
}
catch(e:Error){
}
}
trace(mssg);
}
}
)
Additionally, in MYjavascript.js MYappExePluginThing_init looks like this:
this.MYappExePluginThing_init = function () {
log("MYjavascript.js - MYappExePluginThing_init:");
};
Its supposed to be executed when MYappExePluginThing finishes initializing itself.
Except its not. The message is NOT displaying on the console.
Unfortunately, I cannot find any references explaining how you allow javascript communication in Flex 4.6 so I can check if I've got this structured correctly.
Is it a built in kind of thing all Flex/Flash apps can do? Is my swf getting accessed? Is it having some kind of error? Is it unable to communicate back to my javascript?
Does anyone have any links to references?
If this was YOUR problem, what would you do next?
(Not a full solution but I ran out of room in the comment section.)
To answer your basic question, there's nothing special you should need to do to allow AS3-to-JS communication beyond what you've shown. However, you may have sandbox security issues on localhost; to avoid problems, set your SWFs as local-trusted (right-click Flash Player > Global Settings > Advanced > Trusted Location Settings). I'm guessing this not your problem, though, because you'd normally get a sandbox violation error.
More likely IMO is that something is broken due to decompilation and recompilation. SWFs aren't meant to do that, it's basically a hack made mostly possible due to SWF being an open format.
What I suggest is that you debug your running SWF. Using break-points and stepping through the code you should be able to narrow down where things are going wrong. You can also more easily see any errors your SWF is throwing.
Not really an answer, but an idea to get you started is to start logging everything on the Flash side to see where the breakage is.
Since you're using IE, I recommend getting the Debug flash player, installing it, then running Vizzy along side to show your traces.
Should give you a good idea of where the app is breaking down.
Vizzy
Debug Player
I have business logic that is written in JavaScript, this code is shared with other non-android apps.
What is the best way to use the functions in this piece of JavaScript from within a Service in Android.
AFAIK, there are 2 options?
V8 that is built into the standard WebView and superfast, no extra apk bloat.
Rhino, which is tricky to get going on Android?
Focusing on V8/Webview, when I attempt to access the WebView, with any function, I get;
All WebView methods must be called on the UI thread. Future versions of WebView may not support use on other threads.
The warning being noted, it doesn't even work now. When I set the webviewclient up, I get nothing after loading an URL.
My question is in 3 parts;
1) Has anyone had any success with running javascript in a webview without a UI thread?
2) How do I get results from the functions inside the javascript, does the webview interface "addJavascriptInterface " support loading a parameter and sending it back to the java?
3) If either of the above are impossible.. I guess I'll go get Rhino, any tips would be appreciated, I've only seen a few blogs complaining of issues with regards to getting it going on Android and wondering if there is a "go to" version for android maintained somewhere.
Couldn't find anything with regards to V8 from deep down in a service.
Ended up using Rhino, however a word of warning to anyone following down my footsteps, it's incredibly slow.
Just grab the jar from the official latest distribution of Rhino from
https://developer.mozilla.org/en-US/docs/Rhino/Download_Rhino?redirectlocale=en-US&redirectslug=RhinoDownload
js.jar is what you need in the zip. js-14 is a bigger java 1.4 compatible version you don't need.
Integration was a snap just chuck the jar into your libs folder.
Below is me scraping a webpage using javascript (turning the data into better formatted json). With the parse.js script I made coming from the assets folder.
Rhino doesn't come with DOM, and env.js crashes out with stackoverflow errors. Overall, I'd say this solution is slow and not well supported...
public static void sync(Context context, ){
String url = BASE_URL;
String html = Utils.inputStreamToString(Utils.getHTTPStream(url));
timeList.add(System.currentTimeMillis());
if(html == null){
Utils.logw("Could not get board list.");
return;
}
String parsingCode = null;
try {
parsingCode = Utils.inputStreamToString(context.getAssets().open("parse.js"));
} catch (IOException e) {
Utils.logw("Could not get board parser js");
return;
}
// Create an execution environment.
org.mozilla.javascript.Context cx = org.mozilla.javascript.Context.enter();
// Turn compilation off.
cx.setOptimizationLevel(-1);
try {
// Initialize a variable scope with bindnings for
// standard objects (Object, Function, etc.)
Scriptable scope = cx.initStandardObjects();
ScriptableObject.putProperty(
scope, "html", org.mozilla.javascript.Context.javaToJS(html, scope));
//load up the function
cx.evaluateString(scope, parsingCode,"parseFunction", 1 , null);
// Evaluate the script.
Object result = cx.evaluateString(scope, "myFunction()", "doit:", 1, null);
JSONArray jsonArray = new JSONArray(result.toString());
we have developed an Intranet Management Application with Silverlight 4. We have been asked to add the functionality to call a remote desktop tool which is installed on clients using the Intranet SL App. In an earlier version of the tool written in ASP.NET we just added a Javascript function to the aspx page like this:
function RunShellCommand()
{
var launcher = new ActiveXObject("WScript.Shell");
launcher.Run("mstsc.exe");
}
and called it from ASP.NET.
Now it's clear that SL4 is running in a sandbox and that I cant use the AutomationFactory to create a WScript.Shell object (out of browser mode is not an option).
I thought I could circle around the problem by, again, adding the RunShellCommand javascript method in the aspx page where the SL4 control is hosted and call it via
HtmlPage.RegisterScriptableObject("Page", this);
HtmlPage.Window.Invoke("RunShellCommand", "dummydata");
from my ViewModel. When I run the Application the debugger just skips the RegisterScriptableObject method and quits. Nothing happens.
My question is if am doing something wrong or if this just wont work this way.
Is it possible that I cant do a RegisterScriptableObject from a viewmodel?
EDIT: When I explicitly put a try, catch block around the two methods I get an ArgumentException from the first method stating that the current instance has no scriptable members. When I delete the first method and only run the Invoke, I get a browser error stating that the automation server cant create the object. So is there really no way (except OOB mode) to do this?
Yes, the explanation is correct: you should add at least one method with the ScriptableMember attribute in order that you can use the RegisterScriptableObjectmethod. But it is used only for calling C#-methods from JavaScript.
As far as I see, you want to do the opposite: to call JavaScript code from the Silverlight application. Then you need only one line:
HtmlPage.Window.Invoke("RunShellCommand");
The error automation server cant create the object has nothing to do with Silverlight. I'm sure that if you call the JS function directly - the error will remain.
According to the internet, the reason might be not installed Microsoft Windows Script. Or it is because of security restrictions of the browser.