JavaFX Script and other musing Clarkeman's Weblog

Monday Mar 31, 2008

I read with interest Michael Heinrichs' series of posts showing how to interact with JavaFX Script objects from Java code using the Scripting API. To dig a little deeper, it is also possible to retrieve error messages from the compiled JavaFX Scripts.

The Scripting API, formally known as Scripting for the Java™ Platform, provides the basic framework for implementing the compilation and invocations as described in Micheal's blog entries. But what happens if the script has a compilation error or warning. How does your Java code get these messages. The answer is the javax.tools package with support for Diagnostics.

Both the javax.tools and javax.script packages are included in Java 6. For compatibility with Java 5, these packages are built into the JavaFX libraries. To use the Diagnostic feature, you must first cast the javax.script.ScriptEngine down to a JavaFXScriptEngine as Michael has done in his examples. The JavaFXScriptEngine contains versions of compile and eval methods that take a DiagnosticCollector argument. This object allows the JavaFX compiler to store any warnings, or errors encountered during the compilation phase.

To illustrate this, here is Michael's Java example from his blog entry, Creating JavaFX objects in Java programs, Code Sample 2, with modifications for capturing the Diagnostics. I have purposely changed the attribute in the MyJavaFXClass Object Literal declaration from the valid "property" attribute to an invalid "text" attribute shown in red in the code sample.

 1 import javax.script.ScriptEngineManager;
2 import javax.script.ScriptEngineManager;
3 import com.sun.javafx.api.JavaFXScriptEngine;
4 import javax.tools.Diagnostic;
5
import javax.tools.DiagnosticCollector;
6 import java.util.Iterator;
7 import java.util.List;
8 import javax.script.ScriptException;
9
10 public class Main {
11
12 public static void main(String[] args) {
13 ScriptEngineManager manager = new ScriptEngineManager();
14 JavaFXScriptEngine fxEngine =
15 (JavaFXScriptEngine) manager.getEngineByName("javafx");
16
17 DiagnosticCollector diags = new DiagnosticCollector();
18 try {
19 Object o = fxEngine.eval("MyJavaFXClass { text: \"JavaFX class created in Java\" }",
20 diags);
21 fxEngine.invokeMethod(o, "printProperty");
22
23 } catch (ScriptException e) {
24 List<Diagnostic> errorList = diags.getDiagnostics();
25 Iterator<Diagnostic> iter = errorList.iterator();
26 while (iter.hasNext()) {
27 Diagnostic d = iter.next();
28 System.out.println(
29 d.getKind().toString() + ": Line:" +
30 d.getLineNumber() + " Col:" + d.getColumnNumber() + "\n'" +
31 d.getMessage(null) + "'");
32
}
33 } catch (Exception ex) {
34 ex.printStackTrace();
35 }
36 }
37 }

Code Sample 2: Constructing MyJavaFXClass in Java program, added Diagnostics

When this example is run, the following out appears:

ERROR: Line:1 Col:140
'cannot find symbol
symbol  : variable text
location: class MyJavaFXClass'


 

Comments:

Hi!
I did a more complex example(fx script) of my own using the above scripting API, but unfortunately it displays an error message which is almost useless.[it says for example that the error is below 13 lines than where it should be].
Whats interesting is that when compiling the same script with javafxc, the error line is correct.

What could be a solution for this problem ?

E.g.
[using Scripting API] :
KIND: ERROR
Line: 48 Column: 9
Reason: Sorry, I was trying to understand an object literal part but I got confused when I saw 'panelId' which is an identifier. Perhaps you are missing a ':'.

[using javafxc]: XXX.fx:35: Sorry, I was trying to understand an object literal part but I got confused when I saw 'panels' which is an identifier. Perhaps you are missing a ':'. panels : [

Posted by FluerasBogdan on August 21, 2008 at 04:59 AM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed