JavaScript scope resolve time - java

I'm writing an app that loads javascript dynamically using rhino(or a browser); I got 2 files:
// in a file called fooDefinition.js
var definition = {
foo: function(data){return bar(data)},
loadFile: "barLib.js"
}
now, bar() is defined like this:
// in a file called barLib.js
function bar(data){
return data + " -> bar!";
}
This is what I want to do:
load fooDefinition.js into the environment
read the value of loadFile (in this case: "barLib.js") and load the file (NOTE: load the file through external mechanism, not through javascript itself!)
call foo
external mechanism & example usage (Java pseudo code):
// assume engine is a statefull engine (rhino for example)
String str = /*content of fooDefinition.js*/;
engine.eval(str);
String fileToLoad = engine.eval("definition.loadFile");
engine.load(IOUtils.readFileToString(new File(fileToLoad)));
String result = engine.eval("definition.foo('myData')");
I've tried this in Google Chrome's JS console and no error was thrown
I wonder is this the correct way of accomplish such task?
TL;DR:
Are the attributes of an object loaded and checked when the object is defined?

If your engine is statefull that is it keeps track of defined variables, yes your approach is corrent and will work as expected
But if it is not, your way will fail, because when you call the following
String fileToLoad = engine.eval("definition.loadFile");
your engine haven't any info about definition object and as a result it return an exception (in JavaScript).
It seems your engine is statefull and all things will work correctly

Related

Mounting a Vert.x sub-router on a path with path parameters

I want to create a URL structure for my Vert.x Web powered API that makes it clear how some entities are "contained" inside other entities and how you "traverse the entity path" to find child entities, so I'm thinking of using something like this to address a "grand child" (I don't expect anything deeper than a grand child):
GET /entity/:parent_id/sub-entity/:child_id/subsub-entity/:grandchild_id
So normally my Router configuration will look something like this:
router.get("/entity/:parent_id/sub-entity/:child_id/subsub-entity/:grandchild_id")
.handler(r -> {
HttpServerRequest req = r.request();
Minipart p = Entities.get(req.getParameter("parent_id"))
.getPart(req.getParameter("child_id"))
.getMinipart(req.getParameter("grandchild_id"));
// do something with p
});
When I add a lot of operations (each entity class at each level has catalog and create operations, and each level entity instance has get, update and delete operations, as well as a few other tidbits), my router class gets really large.
I was thinking of using sub-routers to offload the sub-entity management down the line, so the Entities Router configuration might do:
router.mountSubRouter("/entity/:parent_id/sub-entity", PartsRouter.init(vertx));
and then PartsRouter can do:
router.get("/:child_id").handler(r -> {
String parentEntityId = r.request().getParameter("parent_id");
Entity parent = Entities.get(parentEntityId);
String myid = r.request().getParameter("child_id");
Part myself = parent.getPart(myid);
// do something with myself
});
But when I do try that and try to access the sub-router operations, I get a 404 error from Vert.x...
Update:
Apparently Vert.x explicitly does not support this - it threw an exception that my wrapper code just logged and ignored, saying:
java.lang.IllegalArgumentException: Can't use patterns in subrouter mounts
So, is there another way to achieve what I'm trying to do (split a large router configuration into a proper class hierarchy)?
I can image 2 ways of solving your problem:
The first one would be to have a initial handler that processes the common part of the request and calls next so the following one will continue where the first stopped e.g.:
router.route("/entity/:parent_id/sub-entity", ctx -> {
// common part here...
ctx.next();
});
And then:
router.route("/entity/:parent_id/sub-entity/:child_id", ctx -> {
String parentEntityId = r.request().getParameter("parent_id");
Entity parent = Entities.get(parentEntityId);
String myid = r.request().getParameter("child_id");
Part myself = parent.getPart(myid);
// do something with myself
});
Alternatively you can use internal redirects, so you handle the initial code as before but instead of calling next() you redirect to another URL. In that case you should store in the context what you want to reuse since the request will be restarted in the new location.

Calling Java script from java using DWR not updating input field in browser

I am calling java script from java using the DWR mechanism with below code
Container container = ServerContextFactory.get().getContainer();
ScriptSessionManager manager = (ScriptSessionManager) container.getBean(ScriptSessionManager.class);
Collection sessions = manager.getAllScriptSessions();
Util utilAll = new Util(sessions);
utilAll.setStyle("isTreeUpdatedButton", "background-color", "#33C");
It is executing successfully but the input field's background(element having id isTreeUpdatedButton) color is not updating, and an alert comes saying "invalid assignment left-hand side" when above code is executed.
The problem is on your JavaScript function (Which you should post). The error says that the left side of an operation is wrong. It could be that you are using an operator in the wrong way of using a function that does not return the expetected value for the assigment:
For example:
var x;
x = "foo" += "test";
That is just an example because it can be many things.

Call Java from Javascript with GWT JNSI

How do I call a Java method from Javascript? I tried the following
http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html#calling
But it is not working. I can't put the JS into Java file because the library uses a callback. In my App.html file:
function pickerCallback(data) {
var doc = data[google.picker.Response.DOCUMENTS][0];
var name= doc[google.picker.Document.NAME];
var fileId = data.docs[0].id;
// set the path text field
//[instance-expr.]#class-name::field-name
//[instance-expr.]#class-name::method-name(param-signature)(arguments)
// Call static method
//#com.onix.sdm.client.SDM_Mailer::setSelectedFolder(Ljava/lang/String;Ljava/lang/String;)(name, fileId);
$entry(#com.onix.sdm.client.SDM_Mailer::setSelectedFolder(name, fileId));
}
In SDM_Mailer.java:
private static void setSelectedFolder(String folder, String id) {
SDM_Mailer myThis = SDM_Mailer.getInstance();
myThis.textFolder.setText(folder);
myThis.folderId = id;
}
When I load the app, in gives this error in the browser console:
Uncaught SyntaxError: Unexpected token ILLEGAL
On this line:
$entry(#com.onix.sdm.client.SDM_Mailer::setSelectedFolder(name, fileId));
I also tried the line immediately before that (commented for now), which also gave the same error.
I can't put the JS into Java file because the library uses a callback
That's by design - the purpose of this syntax is not to expose methods where they can be called by external JS, but instead to let you call it from within JSNI. This is because the JSNI can be modified to actually call the java method.
If you want to call Java/GWT methods from in plain js, you must expose them for this. You linked http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html#calling, but didn't actually use the important part:
public static native void exportStaticMethod() /*-{
$wnd.computeLoanInterest =
$entry(#mypackage.MyUtilityClass::computeLoanInterest(IFI));
}-*/;
This is the important piece - you must expose the function to where the outside JS can call it, but you must do this exposing from within a JSNI func. Note that we are not calling the function here, just referring to it.
I think you missed the Type Parameter:
$entry(#com.onix.sdm.SDM_Mailer::setSelectedFolder(Ljava/lang/String;Ljava/lang/String;)(name, fileId));
JSNI is well explained at DevGuideCodingBasicsJSNI

How to run vbscript function from java?

From java code i am able to run the vbscript by using this code
Runtime.getRuntime().exec("wscript C:\\ppt\\test1.vbs ");
But want to know how to call the method of vbscript from java..for example in test1.vbs
Set objPPT = CreateObject("PowerPoint.Application")
objPPT.Visible = True
Set objPresentation = objPPT.Presentations.Open("C:\ppt\Labo.ppt")
Set objSlideShow = objPresentation.SlideShowSettings.Run.View
sub ssn1()
objPPT.Run "C:\ppt\Labo.ppt!.SSN"
End sub
how to call only ssn1() method from java.Otherwise can we run the macro of a power point from java code..kindly help!!
This should make you happy :) Go to the WScript section : http://technet.microsoft.com/library/ee156618.aspx
Here's my idea... in your vbscript file, make your script listen to a command line parameter that would specify which method to call. Then, in Java, you could only have to use this parameter whenever you want to call a specific method in the file.
Otherwise, if you want to access powerpoint in java, you will need to access its API like you did in vbscript, which is possible if vbscript can do it but the approach / syntax may change.
I'm not so much into the visual basic script side, but if you can expose your visual basic script as a COM object, the you can access the methods of it from java by usage of frameworks such as for example com4j:
http://com4j.java.net/
The PowerPoint application object's .Run method lets you call any public subroutine or function in any open presentation or loaded add-in
This post answers the OP's question:
Otherwise can we run the macro of a power point from java code..kindly help!!
(but does not address the original vbscript question)
There's the JACOB library, which stands for Java COM Bridge, you can find here: http://sourceforge.net/projects/jacob-project/?source=directory
With it you can invoke Excel, Word, Outlook, PowerPoint application object model methods.
I've tried this with Excel but not PowerPoint. (This is just some sample code, one might want to make it more object oriented.)
public class Excel {
private static ActiveXComponent xl = null;
public static Init() {
try {
ComThread.InitSTA();
xl = ActiveXComponent.connectToActiveInstance("Excel.Application.14");
// 14 is Office 2010, if you don't know what version you can do "Excel.Application"
if (xl==null) {
// code to launch Excel if not running:
xl = new ActiveXComponent("Excel.Application");
Dispatch.put(xl, "Visible", Constants.kTrue);
}
}
catch (Exception e) {
ComThread.Release();
}
}
public static String Run(String vbName) {
// Variant v = Dispatch.call(xl, "Run", vbName); // using string name lookup
Variant v = Dispatch.call(xl, 0x103, vbName); // using COM offset
// return Dispatch.get(this, "Name").getString();
return v.getString();
}
public static Variant Run1p(String vbName, Object param) {
// Variant v = Dispatch.call(xl, "Run", vbName, param);
return Dispatch.call(xl, 0x103, vbName, param);
// return Dispatch.get(this, "Name").getString();
}
public static Worksheet GetActiveWorksheet () {
// Dispatch d = xl.getProperty("ActiveSheet").toDispatch();
Dispatch d = Dispatch.get(xl, 0x133).toDispatch ();
return d; // you may want to put a wrapper around this...
}
}
Notes:
For Excel, at least, to get Run to invoke a VBA macro/subroutine several things have to be true:
The Excel workbook containing the macro must be "Active" (i.e. must
be the ActiveWorkbook) otherwise Run will not find the VBA subroutine. (However the workbook does not have to be
screen visible!! This means you can call a VBA Macro that is in an add-in!).
You can then pass the name of the macro using the following syntax as a string literal:
VBAProjectName.VBAModuleName.SubroutineName
For COM object invocations, you can use the name lookup version or the id number version. The id numbers come from the published COM interfaces (which you can find in C++ header files, or possibly have JACOB look them up for you).
If you successfully did the connection to Excel, be sure to call ComThread.Release() when you're done. Put it in some appropriately surrounding finally. If the process of your Java code terminates without calling it, the COM reference count on Excel will be wrong, and the Excel process will never terminate, even after you exit the Excel application. Once that happens, needless to say, Excel starts to behave screwy then (when you try to use it next, it runs but will fail to load any plug-ins/add-ons). If that happens (as it can during debugging esp. if you are bypassing finally's for better debugging) you have to use the task manager to kill the Excel process.

Externalizing client ChannelSet configuration for Flex/Java web application

I am looking for an approach that will allow me to (somehow) dynamically pass the server name, server port, and web context to my Flex client so it can create a ChannelSet for it's RemoteObjects to use. These three properties are, of course, readily available to my Java server-side code so I just need a way to get them to the client.
By default, Adobe says you should compile your Flex application against the server configuration file "services-config.xml". This is a highly inflexible practice that Spring says should be avoided (I agree).
One popular approach is to use Flex's http service to download an XML configuration file. I like this idea, but I don't want to hard-code an XML file and keep it inside my WAR file. Is there a way to dynamically generate this from Java code?
Another idea I had is to somehow use flashvars to pass the properties in from the containing HTML page to the SWF file. But again, I don't want to hard code them into the HTML page. Is there a way (maybe with Javascript?) to dynamically set the value of these when the page loads?
This is how I do it. I hope you'll find it useful:
public static function getRemoteObject(destination:String, channelName:String,
showBusyCursor:Boolean=true):RemoteObject{
var remoteService:RemoteObject=new RemoteObject(destination);
var channelSet:ChannelSet=new ChannelSet();
var url:String = Application(Application.application).url;
var secure:Boolean = URLUtil.isHttpsURL(url);
var protocol:String = URLUtil.getProtocol(url);
var amf:AMFChannel;
if (secure){
amf = new SecureAMFChannel(channelName, protocol +
"://{server.name}:{server.port}" +
(Application.application as Application).parameters.contextRoot +
"/graniteamf/amf");
}else{
amf = new AMFChannel(channelName, protocol +
"://{server.name}:{server.port}" +
(Application.application as Application).parameters.contextRoot
+ "/graniteamf/amf");
}
channelSet.addChannel(amf);
remoteService.channelSet=channelSet;
remoteService.showBusyCursor=showBusyCursor;
return remoteService;
}
So as you can see the only things you need to provide are destination - which must be configured in server side XML and contextRoot - passed as flashVar. Passing as flashVar in my case (through JSP) looks like this:
String flashVariables = "contextRoot=" + request.getContextPath() +
"&locale=" + request.getLocale().getLanguage();

Categories

Resources