jaroslav@166
|
1 |
<!--
|
jaroslav@166
|
2 |
|
jaroslav@358
|
3 |
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
jaroslav@166
|
4 |
|
jaroslav@551
|
5 |
Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
|
jaroslav@166
|
6 |
|
jaroslav@358
|
7 |
Oracle and Java are registered trademarks of Oracle and/or its affiliates.
|
jaroslav@358
|
8 |
Other names may be trademarks of their respective owners.
|
jaroslav@166
|
9 |
|
jaroslav@358
|
10 |
The contents of this file are subject to the terms of either the GNU
|
jaroslav@358
|
11 |
General Public License Version 2 only ("GPL") or the Common
|
jaroslav@358
|
12 |
Development and Distribution License("CDDL") (collectively, the
|
jaroslav@358
|
13 |
"License"). You may not use this file except in compliance with the
|
jaroslav@358
|
14 |
License. You can obtain a copy of the License at
|
jaroslav@358
|
15 |
http://www.netbeans.org/cddl-gplv2.html
|
jaroslav@358
|
16 |
or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
jaroslav@358
|
17 |
specific language governing permissions and limitations under the
|
jaroslav@358
|
18 |
License. When distributing the software, include this License Header
|
jaroslav@358
|
19 |
Notice in each file and include the License file at
|
jaroslav@358
|
20 |
nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
|
jaroslav@358
|
21 |
particular file as subject to the "Classpath" exception as provided
|
jaroslav@358
|
22 |
by Oracle in the GPL Version 2 section of the License file that
|
jaroslav@358
|
23 |
accompanied this code. If applicable, add the following below the
|
jaroslav@358
|
24 |
License Header, with the fields enclosed by brackets [] replaced by
|
jaroslav@358
|
25 |
your own identifying information:
|
jaroslav@358
|
26 |
"Portions Copyrighted [year] [name of copyright owner]"
|
jaroslav@358
|
27 |
|
jaroslav@358
|
28 |
Contributor(s):
|
jaroslav@358
|
29 |
|
jaroslav@358
|
30 |
The Original Software is NetBeans. The Initial Developer of the Original
|
jaroslav@551
|
31 |
Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
|
jaroslav@358
|
32 |
|
jaroslav@358
|
33 |
If you wish your version of this file to be governed by only the CDDL
|
jaroslav@358
|
34 |
or only the GPL Version 2, indicate your decision by adding
|
jaroslav@358
|
35 |
"[Contributor] elects to include this software in this distribution
|
jaroslav@358
|
36 |
under the [CDDL or GPL Version 2] license." If you do not indicate a
|
jaroslav@358
|
37 |
single choice of license, a recipient has the option to distribute
|
jaroslav@358
|
38 |
your version of this file under either the CDDL, the GPL Version 2 or
|
jaroslav@358
|
39 |
to extend the choice of license to its licensees as provided above.
|
jaroslav@358
|
40 |
However, if you add GPL Version 2 code and therefore, elected the GPL
|
jaroslav@358
|
41 |
Version 2 license, then the option applies only if the new code is
|
jaroslav@358
|
42 |
made subject to such option by the copyright holder.
|
jaroslav@166
|
43 |
|
jaroslav@166
|
44 |
-->
|
jaroslav@166
|
45 |
<!DOCTYPE html>
|
jaroslav@166
|
46 |
<html>
|
jaroslav@166
|
47 |
<body>
|
jaroslav@513
|
48 |
<div>Essential support for those who write <em>native</em> methods communicating directly with JavaScript.</div>
|
jaroslav@513
|
49 |
Mix your Java and JavaScript code seamlessly - perform calls from Java
|
jaroslav@513
|
50 |
to JavaScript and back with as much freedom as JavaScript gives you
|
jaroslav@513
|
51 |
and as much type safety you can get from Java. Execute your code
|
jaroslav@513
|
52 |
in a headless testing environment or in a
|
jaroslav@513
|
53 |
<a href="http://wiki.apidesign.org/wiki/FXBrwsr">JavaFX WebView</a>.
|
jaroslav@513
|
54 |
When done, deploy to <a href="http://bck2brwsr.apidesign.org">real browsers</a>.
|
jaroslav@513
|
55 |
|
jaroslav@513
|
56 |
<h3>Simple Meaning of World</h3>
|
jaroslav@513
|
57 |
The whole support is build around @<a href="JavaScriptBody.html">JavaScriptBody</a>
|
jaroslav@513
|
58 |
annotation. Use it to create parametrised JavaScript snippet easily
|
jaroslav@513
|
59 |
accessible from Java:
|
jaroslav@513
|
60 |
<pre>
|
jaroslav@513
|
61 |
{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"x", "y"}, body = "return x + y;")
|
jaroslav@513
|
62 |
<b>private static native int</b> meaning(<b>int</b> x, <b>int</b> y);
|
jaroslav@513
|
63 |
</pre>
|
jaroslav@513
|
64 |
The above defines method <em>meaning</em> which sums two JavaScript
|
jaroslav@513
|
65 |
objects together (being invoked inside of a JavaScript interpreter).
|
jaroslav@513
|
66 |
The <em>meaning</em> method now becomes a properly typed Java
|
jaroslav@513
|
67 |
surface to your JavaScript code which can be directly
|
jaroslav@513
|
68 |
called from the rest of your Java code:
|
jaroslav@513
|
69 |
<pre>
|
jaroslav@513
|
70 |
<b>public static void</b> main(String... args) {
|
jaroslav@513
|
71 |
<b>assert</b> 42 == meaning(40, 2) : <em>"Meaning of World should be 42!"</em>;
|
jaroslav@513
|
72 |
}
|
jaroslav@513
|
73 |
</pre>
|
jaroslav@513
|
74 |
<em>Real code tip:</em> real classes using this technique are
|
jaroslav@513
|
75 |
available online:
|
jaroslav@513
|
76 |
<a target="top" href="http://hg.netbeans.org/html4j/file/release-0.7/boot/src/test/java/org/netbeans/html/boot/impl/JsMethods.java">JsMethods</a> and
|
jaroslav@513
|
77 |
<a target="top" href="http://hg.netbeans.org/html4j/file/release-0.7/json-tck/src/main/java/net/java/html/js/tests/Bodies.java">Bodies</a>.
|
jaroslav@513
|
78 |
<p></p>
|
jaroslav@513
|
79 |
<em>Editing hint:</em> one can see the list of arguments of the
|
jaroslav@513
|
80 |
<em>meaning</em> is now duplicated - it is once specified in Java,
|
jaroslav@513
|
81 |
and once inside of the {@link net.java.html.js.JavaScriptBody}
|
jaroslav@513
|
82 |
array of <code>args</code>. This is necessary to keep the names of
|
jaroslav@513
|
83 |
arguments accessible during runtime. However don't despair - there
|
jaroslav@513
|
84 |
is a code completion for the value of <code>args</code> attribute!
|
jaroslav@513
|
85 |
Just type the Java signature first and then press Ctrl+Space and the
|
jaroslav@513
|
86 |
right parameter names will be inserted for you.
|
jaroslav@513
|
87 |
|
jaroslav@513
|
88 |
<a name="#library"><h3>Including JavaScript Libraries</h3></a>
|
jaroslav@513
|
89 |
|
jaroslav@513
|
90 |
Large amount of JavaScript code is easier to be delivered in whole
|
jaroslav@513
|
91 |
files rather than {@link net.java.html.js.JavaScriptBody small code snippets} -
|
jaroslav@513
|
92 |
that is also possible thanks to {@link net.java.html.js.JavaScriptResource}
|
jaroslav@513
|
93 |
annotation. Imagine file <code>mul.js</code> with following content:
|
jaroslav@513
|
94 |
<pre>
|
jaroslav@513
|
95 |
<b>function</b> <em>mul</em>(x, y) { <b>return</b> x * y; }
|
jaroslav@513
|
96 |
</pre>
|
jaroslav@513
|
97 |
Place the file next to your class and reference it with
|
jaroslav@513
|
98 |
{@link net.java.html.js.JavaScriptResource the annotation}:
|
jaroslav@513
|
99 |
<pre>
|
jaroslav@559
|
100 |
{@code @}{@link net.java.html.js.JavaScriptResource}("mul.js") <b>class</b> Mul {
|
jaroslav@513
|
101 |
|
jaroslav@559
|
102 |
{@code @}{@link net.java.html.js.JavaScriptBody}(args = { "x", "y" }, body = "return <b>mul</b>(x, y);")
|
jaroslav@513
|
103 |
<b>public static native int</b> multiply(int x, int y);
|
jaroslav@513
|
104 |
|
jaroslav@513
|
105 |
<b>public static void</b> main(String... args) {
|
jaroslav@513
|
106 |
<b>assert</b> 42 == multiply(6, 7) : <em>"Meaning of World should be 42!"</em>;
|
jaroslav@513
|
107 |
}
|
jaroslav@513
|
108 |
}
|
jaroslav@513
|
109 |
</pre>
|
jaroslav@513
|
110 |
All the Java methods annotated {@link net.java.html.js.JavaScriptBody}
|
jaroslav@513
|
111 |
can now reference everything that is in the <code>mul.js</code> file -
|
jaroslav@513
|
112 |
e.g. the body of the <code>multiply</code> method can reference the
|
jaroslav@513
|
113 |
function <code>mul</code> and use it.
|
jaroslav@513
|
114 |
<p></p>
|
jaroslav@513
|
115 |
<em>Real code tip:</em>
|
jtulach@1022
|
116 |
<a target="top" href="http://hg.netbeans.org/html4j/file/release-0.7/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java">this</a>
|
jaroslav@513
|
117 |
is the way
|
jtulach@1022
|
118 |
the <a target="top" href="http://knockoutjs.com">knockout.js</a> library
|
jaroslav@513
|
119 |
is included in its <em>ko4j</em> library.
|
jaroslav@513
|
120 |
|
jaroslav@513
|
121 |
<h3>Callback to Java</h3>
|
jaroslav@513
|
122 |
|
jaroslav@513
|
123 |
Often JavaScript code needs to call back into the Java classes.
|
jaroslav@513
|
124 |
For example when a button in a browser is pressed and your code would
|
jaroslav@513
|
125 |
like to invoke a runnable to handle such situation:
|
jaroslav@513
|
126 |
<pre>
|
jaroslav@513
|
127 |
{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"id", "r"}, {@link net.java.html.js.JavaScriptBody#javacall() javacall} = true, body = "\n" +
|
jaroslav@513
|
128 |
" document.getElementById(id).onclick = function() {\n" +
|
jaroslav@513
|
129 |
" r.<em>{@code @}java.lang.Runnable::run()</em>();\n" +
|
jaroslav@513
|
130 |
" };\n" +
|
jaroslav@513
|
131 |
" ")
|
jaroslav@513
|
132 |
<b>public static native void</b> onClick(String id, Runnable r);
|
jaroslav@513
|
133 |
</pre>
|
jaroslav@513
|
134 |
As can be seen, there is a special syntax (starting with <b>@</b>) to
|
jaroslav@513
|
135 |
properly identify the right Java method to call on a Java object passed
|
jaroslav@513
|
136 |
into the JavaScript interpreter. The syntax starts with a fully
|
jaroslav@513
|
137 |
qualified name of the class, followed by <b>::</b> and name of the
|
jaroslav@513
|
138 |
method including signature of its parameters. In case of runnable,
|
jaroslav@513
|
139 |
this is just <em>()</em> as the method has no parameters, but the
|
jaroslav@513
|
140 |
signature can be more complicated. For example in case of following method
|
jaroslav@513
|
141 |
<pre><b>static int</b> compare(<b>int</b> i1, String s1, <b>int</b> i2, String s2)
|
jaroslav@513
|
142 |
</pre>
|
jaroslav@513
|
143 |
it would be <em>(ILjava/lang/String;ILjava/lang/String;)</em> (btw. the
|
jaroslav@513
|
144 |
return type is not included in the signature). The actual parameters
|
jaroslav@513
|
145 |
then follows. The JavaScript call to such compare method would then
|
jaroslav@513
|
146 |
look like:
|
jaroslav@513
|
147 |
<pre>{@code @}the.pkg.Clazz::compare(ILjava/lang/String;ILjava/lang/String;)(1, 'One', 2, 'Two');
|
jaroslav@513
|
148 |
</pre>
|
jaroslav@513
|
149 |
This syntax gives enough flexibility, helps to properly select one
|
jaroslav@513
|
150 |
of overloaded methods and follows the tradition of previous attempts to
|
jaroslav@513
|
151 |
provide JavaScript to Java calling conventions.
|
jaroslav@513
|
152 |
<p></p>
|
jaroslav@513
|
153 |
Please note that to turn the special Java callback syntax on, one
|
jaroslav@513
|
154 |
needs to set the {@link net.java.html.js.JavaScriptBody#javacall()}
|
jtulach@1022
|
155 |
attribute to <b>true</b>. The callback syntax consists of
|
jtulach@1022
|
156 |
following parts:
|
jaroslav@513
|
157 |
<p></p>
|
jtulach@1022
|
158 |
<pre>[instance.]@classname::methodname(signature)(arguments)</pre>
|
jtulach@1022
|
159 |
<ul>
|
jtulach@1022
|
160 |
<li><b>instance</b> - must be present when calling an
|
jtulach@1022
|
161 |
instance method and must be absent when calling a
|
jtulach@1022
|
162 |
static method</li>
|
jtulach@1022
|
163 |
<li><b>classname</b> - fully qualified name of the class in
|
jtulach@1022
|
164 |
which the method is declared
|
jtulach@1022
|
165 |
</li>
|
jtulach@1022
|
166 |
<li><b>signature</b> - internal JVM method signature
|
jtulach@1022
|
167 |
(as specified at
|
jtulach@1022
|
168 |
<a target="top" href="http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html#wp16432">JNI type Signatures</a>)
|
jtulach@1022
|
169 |
without the trailing signature of the method return type</li>
|
jtulach@1022
|
170 |
<li><b>arguments</b> - the actual values to pass to the called Java method
|
jtulach@1022
|
171 |
</li>
|
jtulach@1022
|
172 |
</ul>
|
jtulach@1022
|
173 |
|
jtulach@1022
|
174 |
<p>Here is the <a target="top" href="http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html#wp16432">JNI type signatures table</a>
|
jtulach@1022
|
175 |
one can use to convert
|
jtulach@1022
|
176 |
Java parameters to JVM's internal <em>letter</em> based
|
jtulach@1022
|
177 |
representation:</p>
|
jtulach@1022
|
178 |
|
jtulach@1022
|
179 |
<table border=1 width='100%'>
|
jtulach@1022
|
180 |
<tr>
|
jtulach@1022
|
181 |
<td><b>Type Signature</b></td>
|
jtulach@1022
|
182 |
<td><b>Java Type</b></td>
|
jtulach@1022
|
183 |
</tr>
|
jtulach@1022
|
184 |
<tr>
|
jtulach@1022
|
185 |
<td>Z</td>
|
jtulach@1022
|
186 |
<td>boolean</td>
|
jtulach@1022
|
187 |
</tr>
|
jtulach@1022
|
188 |
<tr>
|
jtulach@1022
|
189 |
<td>B</td>
|
jtulach@1022
|
190 |
<td>byte</td>
|
jtulach@1022
|
191 |
</tr>
|
jtulach@1022
|
192 |
<tr>
|
jtulach@1022
|
193 |
<td>C</td>
|
jtulach@1022
|
194 |
<td>char</td>
|
jtulach@1022
|
195 |
</tr>
|
jtulach@1022
|
196 |
<tr>
|
jtulach@1022
|
197 |
<td>S</td>
|
jtulach@1022
|
198 |
<td>short</td>
|
jtulach@1022
|
199 |
</tr>
|
jtulach@1022
|
200 |
<tr>
|
jtulach@1022
|
201 |
<td>I</td>
|
jtulach@1022
|
202 |
<td>int</td>
|
jtulach@1022
|
203 |
</tr>
|
jtulach@1022
|
204 |
<tr>
|
jtulach@1022
|
205 |
<td>J</td>
|
jtulach@1022
|
206 |
<td>long</td>
|
jtulach@1022
|
207 |
</tr>
|
jtulach@1022
|
208 |
<tr>
|
jtulach@1022
|
209 |
<td>F</td>
|
jtulach@1022
|
210 |
<td>float</td>
|
jtulach@1022
|
211 |
</tr>
|
jtulach@1022
|
212 |
<tr>
|
jtulach@1022
|
213 |
<td>D</td>
|
jtulach@1022
|
214 |
<td>double</td>
|
jtulach@1022
|
215 |
</tr>
|
jtulach@1022
|
216 |
<tr>
|
jtulach@1022
|
217 |
<td>L fully-qualified-class ;</td>
|
jtulach@1022
|
218 |
<td>fully-qualified-class</td>
|
jtulach@1022
|
219 |
</tr>
|
jtulach@1022
|
220 |
<tr>
|
jtulach@1022
|
221 |
<td>[ type</td>
|
jtulach@1022
|
222 |
<td>type[]</td>
|
jtulach@1022
|
223 |
</tr>
|
jtulach@1022
|
224 |
</tbody>
|
jtulach@1022
|
225 |
</table>
|
jtulach@1022
|
226 |
<p></p>
|
jtulach@1022
|
227 |
<em>Editing hint:</em> The callback syntax may seem complicated at
|
jtulach@1022
|
228 |
first, however there is an associated <b>annotation processor</b>
|
jaroslav@513
|
229 |
that checks the syntax and verifies the referenced class and
|
jtulach@1022
|
230 |
method with the requested signature exist. If it does not, the
|
jtulach@1022
|
231 |
<em>compilation fails offering correct alternatives</em>.
|
jtulach@1022
|
232 |
Thus don't despair seeing the syntax, make sure you get the
|
jtulach@1022
|
233 |
fully qualified name of the callback class right.
|
jtulach@1022
|
234 |
You'll get warning and help
|
jtulach@1022
|
235 |
if there is a typo in the specified signature then -
|
jtulach@1022
|
236 |
during compilation of your code.
|
jaroslav@514
|
237 |
|
jtulach@937
|
238 |
<h3>Overloaded Methods</h3>
|
jtulach@937
|
239 |
|
jtulach@937
|
240 |
Specifying the actual callback signature is important in case of
|
jtulach@937
|
241 |
overloaded methods. Imagine a class:
|
jtulach@937
|
242 |
<pre>
|
jtulach@937
|
243 |
<b>package</b> x.y.z;
|
jtulach@937
|
244 |
<b>class</b> Handler {
|
jtulach@937
|
245 |
<b>int</b> pulse() {
|
jtulach@937
|
246 |
<b>return</b> 1;
|
jtulach@937
|
247 |
}
|
jtulach@937
|
248 |
<b>int</b> pulse(<b>int</b> howMuch) {
|
jtulach@937
|
249 |
<b>return</b> howMuch;
|
jtulach@937
|
250 |
}
|
jtulach@937
|
251 |
<b>int</b> pulse(<b>long</b> evenMore) {
|
jtulach@937
|
252 |
<b>return</b> (<b>int</b>) (5 + evenMore);
|
jtulach@937
|
253 |
}
|
jtulach@937
|
254 |
}</pre>
|
jtulach@937
|
255 |
you then need to choose in {@link net.java.html.js.JavaScriptBody}
|
jtulach@937
|
256 |
the appropriate method to call:
|
jtulach@937
|
257 |
<pre>
|
jtulach@937
|
258 |
{@code @}{@link net.java.html.js.JavaScriptBody}(args = { "h" }, javacall = <b>true</b>, <em>// you want to process the @ syntax</em>
|
jtulach@937
|
259 |
body = "<b>return</b> h.@x.y.z.Handler::pulse()() +" + <em>// the call to no argument method</em>
|
jtulach@937
|
260 |
"h.@x.y.z.Handler::pulse(I)(10) +" + <em>// the call to method with integer argument</em>
|
jtulach@937
|
261 |
"h.@x.y.z.Handler::pulse(J)(10);" <em>// the call to method with long argument</em>
|
jtulach@937
|
262 |
)
|
jtulach@937
|
263 |
<b>static native void</b> threePulsesFromJavaScript(Handler h);
|
jtulach@937
|
264 |
<b>static</b> {
|
jtulach@937
|
265 |
<b>assert</b> 26 == threePulsesFromJavaScript(<b>new</b> Handler());
|
jtulach@937
|
266 |
}
|
jtulach@937
|
267 |
</pre>
|
jtulach@937
|
268 |
<p>
|
jtulach@937
|
269 |
To avoid ambiguity, the specification of the correct signature is
|
jtulach@937
|
270 |
required on every call. However, to simplify the development,
|
jtulach@937
|
271 |
there is an annotation processor to
|
jtulach@937
|
272 |
verify the signature really refers to an existing method.
|
jtulach@937
|
273 |
</p>
|
jtulach@937
|
274 |
|
jaroslav@514
|
275 |
<h3>Arrays by Copy</h3>
|
jaroslav@514
|
276 |
|
jaroslav@514
|
277 |
It is possible to exchange arrays between Java and JavaScript. Some
|
jaroslav@514
|
278 |
implementations can pass arrays by reference, however in some systems
|
jaroslav@514
|
279 |
this is hard to achieve. To choose the least common denominator,
|
jaroslav@514
|
280 |
the TCK for behavior of {@link net.java.html.js.JavaScriptBody} requires
|
jaroslav@514
|
281 |
the arrays to be always transfered by a copy. As such following code:
|
jaroslav@514
|
282 |
<pre>
|
jaroslav@514
|
283 |
{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"arr"}, body = "arr[0] = null;")
|
jaroslav@514
|
284 |
<b>private static native void</b> uselessModify(String[] arr);
|
jaroslav@514
|
285 |
<b>public static void</b> main(String... args) {
|
jaroslav@514
|
286 |
String[] hello = { "Hello", "World!" };
|
jaroslav@514
|
287 |
uselessModify(arr);
|
jaroslav@514
|
288 |
System.out.println(arr[0] + " " + arr[1]);
|
jaroslav@514
|
289 |
}
|
jaroslav@514
|
290 |
</pre>
|
jaroslav@514
|
291 |
will still print <em>Hello World!</em> in spite the JavaScript code
|
jaroslav@514
|
292 |
sets the 0-th array element to <code>null</code>. Because the array
|
jaroslav@514
|
293 |
is passed as a copy, such assignment has no effect on the Java array.
|
jaroslav@514
|
294 |
<p></p>
|
jaroslav@514
|
295 |
In case one needs to modify an array in a JavaScript and use its
|
jaroslav@514
|
296 |
values in Java, one has to return the array back as a return value:
|
jaroslav@514
|
297 |
<pre>
|
jaroslav@514
|
298 |
{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"arr"}, body = "arr[0] = 'Ahoy'; return arr;")
|
jaroslav@515
|
299 |
<b>private static native</b> Object[] usefulModify(String[] arr);
|
jaroslav@514
|
300 |
<b>public static void</b> main(String... args) {
|
jaroslav@514
|
301 |
String[] hello = { "Hello", "World!" };
|
jaroslav@514
|
302 |
Object[] ret = usefulModify(arr);
|
jaroslav@514
|
303 |
System.out.println(ret[0] + " " + ret[1]);
|
jaroslav@514
|
304 |
}
|
jaroslav@514
|
305 |
</pre>
|
jaroslav@514
|
306 |
now the program prints <em>Ahoy World!</em> as the modified array
|
jaroslav@514
|
307 |
is returned back and converted (by a copy) into a Java <code>Object[]</code>
|
jaroslav@514
|
308 |
(but of course the <code>ret != hello</code>). Usually the copy based
|
jaroslav@514
|
309 |
passing of arrays works OK. It is however good to keep it in mind to
|
jaroslav@514
|
310 |
avoid unwanted surprises.
|
jaroslav@514
|
311 |
|
jtulach@883
|
312 |
<h3>Instance Reference to JavaScript Object</h3>
|
jtulach@883
|
313 |
|
jtulach@883
|
314 |
When writing wrappers around existing JavaScript libraries, it may be
|
jtulach@883
|
315 |
useful to hold a reference to some JavaScript object from a Java
|
jtulach@883
|
316 |
instance and use it later.
|
jtulach@883
|
317 |
<pre>
|
jtulach@883
|
318 |
<b>class</b> WrapperAroundJsObj {
|
jtulach@883
|
319 |
<b>private final</b> Object js;
|
jtulach@883
|
320 |
|
jtulach@883
|
321 |
WrapperAroundJsObj() {
|
jtulach@883
|
322 |
js = initValue();
|
jtulach@883
|
323 |
}
|
jtulach@883
|
324 |
|
jtulach@883
|
325 |
<b>public void</b> set(int v) {
|
jtulach@883
|
326 |
setValue(js, v);
|
jtulach@883
|
327 |
}
|
jtulach@883
|
328 |
|
jtulach@883
|
329 |
{@link net.java.html.js.JavaScriptBody @JavaScriptBody}(args = {}, body = "return { value : 0 };")
|
jtulach@883
|
330 |
<b>private static native</b> Object initValue();
|
jtulach@883
|
331 |
|
jtulach@883
|
332 |
{@link net.java.html.js.JavaScriptBody @JavaScriptBody}(
|
jtulach@883
|
333 |
args = { "js", "v" }, body = "js.value = v;", wait4js = false
|
jtulach@883
|
334 |
)
|
jtulach@883
|
335 |
<b>private static native void</b> setValue(Object js, int v);
|
jtulach@883
|
336 |
}
|
jtulach@883
|
337 |
</pre>
|
jtulach@883
|
338 |
The type of the Java reference is {@link java.lang.Object}.
|
jtulach@883
|
339 |
From a Java perspective it has no additional methods or fields, however
|
jtulach@883
|
340 |
its properties can be manipulated from JavaScript. Send the object back
|
jtulach@883
|
341 |
to JavaScript by passing it as a parameter of some method
|
jtulach@883
|
342 |
(like the <code>setValue</code> one) and perform necessary JavaScript
|
jtulach@883
|
343 |
calls or changes on it.
|
jtulach@883
|
344 |
|
jaroslav@514
|
345 |
<h3>Post Process Classes</h3>
|
jtulach@884
|
346 |
<a name="post-process"></a>
|
jaroslav@530
|
347 |
|
jaroslav@530
|
348 |
Classes with {@link net.java.html.js.JavaScriptBody} annotated methods need to
|
jaroslav@530
|
349 |
be post processed before they can be used - e.g. their <code>native</code>
|
jaroslav@530
|
350 |
body needs to be generated to call into JavaScript (btw. the code is performed
|
jtulach@838
|
351 |
via {@link org.netbeans.html.boot.spi.Fn}). There are three ways
|
jaroslav@530
|
352 |
such post processing can happen.
|
jaroslav@530
|
353 |
<p></p>
|
jaroslav@530
|
354 |
<b>Compile time</b> processing - this is the preferred method that
|
jaroslav@530
|
355 |
most of the <a href="http://html.java.net">Html Java APIs</a> are using.
|
jaroslav@530
|
356 |
Just include following plugin configuration into your <code>pom.xml</code>
|
jaroslav@530
|
357 |
and your classes will be ready for execution as soon as <em>process-classes</em>
|
jaroslav@530
|
358 |
<a href="http://wiki.apidesign.org/wiki/Maven">Maven</a> phase is over:
|
jaroslav@530
|
359 |
<pre>
|
jaroslav@530
|
360 |
<plugin>
|
jaroslav@530
|
361 |
<groupId>org.netbeans.html</groupId>
|
jaroslav@530
|
362 |
<artifactId>html4j-maven-plugin</artifactId>
|
jaroslav@530
|
363 |
<version>${net.java.html.version}</version>
|
jaroslav@530
|
364 |
<executions>
|
jaroslav@530
|
365 |
<execution>
|
jaroslav@530
|
366 |
<id>js-classes</id>
|
jaroslav@530
|
367 |
<goals>
|
jaroslav@530
|
368 |
<goal>process-js-annotations</goal>
|
jaroslav@530
|
369 |
</goals>
|
jaroslav@530
|
370 |
</execution>
|
jaroslav@530
|
371 |
</executions>
|
jaroslav@530
|
372 |
</plugin>
|
jaroslav@530
|
373 |
</pre>
|
jaroslav@530
|
374 |
This plugin works in orchestration with
|
jaroslav@530
|
375 |
<a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation
|
jaroslav@530
|
376 |
processor</a> associated with {@link net.java.html.js.JavaScriptBody}
|
jaroslav@530
|
377 |
and {@link net.java.html.js.JavaScriptResource} - the processor creates
|
jaroslav@530
|
378 |
list of files that need post-processing. The
|
jaroslav@530
|
379 |
<a href="http://wiki.apidesign.org/wiki/Maven">Maven</a>
|
jaroslav@530
|
380 |
plugin reads these files, processes classes mentioned in them and
|
jaroslav@530
|
381 |
modifies (and deletes at the end) the files to not include classes
|
jaroslav@530
|
382 |
already processed.
|
jaroslav@530
|
383 |
<p></p>
|
jaroslav@530
|
384 |
<b>Instrumentation Agent</b> - one can do processing in runtime
|
jaroslav@530
|
385 |
using JDK's {@link java.lang.instrument.ClassFileTransformer instrumentation}
|
jaroslav@530
|
386 |
abilities. The JAR artifact of <code>org.netbeans.html:net.java.html.boot</code>
|
jaroslav@530
|
387 |
contains an <code>Agent-Class</code> and <code>Premain-Class</code>
|
jaroslav@530
|
388 |
definitions in its manifest. As such one can launch the Java virtual
|
jaroslav@530
|
389 |
machine with
|
jaroslav@530
|
390 |
<pre>
|
jaroslav@530
|
391 |
$ java -javaagent:jarpath=net.java.html.boot-x.y.jar
|
jaroslav@530
|
392 |
</pre>
|
jaroslav@530
|
393 |
and the runtime will take care of processing bytecode of classes
|
jaroslav@530
|
394 |
not yet processed in compile time before they are loaded into the
|
jaroslav@530
|
395 |
virtual machine.
|
jaroslav@530
|
396 |
<p></p>
|
jaroslav@530
|
397 |
<b>Special classloading</b> - when booting your application with
|
jaroslav@530
|
398 |
{@link net.java.html.boot.BrowserBuilder} there is a 3rd option of
|
jaroslav@530
|
399 |
processing the classes. If there are some classes not yet processed
|
jaroslav@530
|
400 |
(remember the files listing them generated by the
|
jaroslav@530
|
401 |
<a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation
|
jaroslav@530
|
402 |
processor</a>), the {@link net.java.html.boot.BrowserBuilder#showAndWait() launching method}
|
jaroslav@530
|
403 |
will create a special classloader to that does the processing before
|
jaroslav@530
|
404 |
loading the bytecode into the virtual machine.
|
jaroslav@530
|
405 |
<p></p>
|
jtulach@884
|
406 |
The options are rich, however to avoid any troubles (as the runtime
|
jtulach@884
|
407 |
processing needs to also include <code>asm-5.0.jar</code> on application
|
jtulach@884
|
408 |
classpath), it is recommended
|
jaroslav@530
|
409 |
to perform the <b>compile time</b> processing.
|
jaroslav@514
|
410 |
|
jaroslav@530
|
411 |
<h3>Getting Started</h3>
|
jaroslav@530
|
412 |
|
jaroslav@530
|
413 |
There are many ways to start developing
|
jaroslav@530
|
414 |
<a href="http://html.java.net">Html for Java</a> application.
|
jaroslav@530
|
415 |
However to be sure one chooses the most recent setup, it is recommended
|
jaroslav@530
|
416 |
to switch to good old command line and use a
|
jaroslav@530
|
417 |
<a href="http://wiki.apidesign.org/wiki/Knockout4Java">Maven archetype</a>
|
jaroslav@530
|
418 |
associated with every version of this project. Just type:
|
jaroslav@530
|
419 |
<pre>
|
jaroslav@530
|
420 |
$ mvn archetype:generate \
|
jaroslav@530
|
421 |
-DarchetypeGroupId=org.apidesign.html \
|
jaroslav@530
|
422 |
-DarchetypeArtifactId=knockout4j-archetype \
|
jaroslav@530
|
423 |
-DarchetypeVersion=x.y
|
jaroslav@530
|
424 |
</pre>
|
jaroslav@530
|
425 |
Answer few questions (for example choose myfirstbrwsrpage as artifactId) and then you can:
|
jaroslav@530
|
426 |
<pre>
|
jaroslav@530
|
427 |
$ cd myfirstbrwsrpage
|
jaroslav@530
|
428 |
$ mvn process-classes exec:java
|
jaroslav@530
|
429 |
</pre>
|
jaroslav@530
|
430 |
In a few seconds (or minutes if
|
jaroslav@530
|
431 |
<a href="http://wiki.apidesign.org/wiki/Maven">Maven</a>
|
jaroslav@530
|
432 |
decides to download the whole Internet of dependencies) you should
|
jaroslav@530
|
433 |
see a sample Hello World application. It is basically composed from one
|
jaroslav@530
|
434 |
Java and one HTML file:
|
jaroslav@530
|
435 |
<pre>
|
jaroslav@530
|
436 |
$ ls src/main/java/**/DataModel.java
|
jaroslav@530
|
437 |
$ ls src/main/webapp/pages/index.html
|
jaroslav@530
|
438 |
</pre>
|
jaroslav@530
|
439 |
Play with them, modify them and enjoy
|
jaroslav@530
|
440 |
<a href="http://html.java.net">Html for Java</a>!
|
jaroslav@614
|
441 |
|
jaroslav@614
|
442 |
<a name="debugging">
|
jaroslav@614
|
443 |
<h3>Mixed Java/JavaScript Debugging</h3>
|
jaroslav@614
|
444 |
</a>
|
jaroslav@614
|
445 |
|
jaroslav@614
|
446 |
<p>
|
jaroslav@614
|
447 |
The following video shows how easy it is to use
|
jaroslav@614
|
448 |
NetBeans 8.0, JDK8 to debug an application that intermixes Java
|
jaroslav@614
|
449 |
and JavaScript calls. One can put breakpoints into Java part,
|
jaroslav@614
|
450 |
as well as JavaScript source code, inspect Java as well
|
jaroslav@614
|
451 |
as JavaScript variables and switch between these two
|
jaroslav@614
|
452 |
languages without any restrictions.
|
jaroslav@614
|
453 |
</p>
|
jaroslav@614
|
454 |
|
jaroslav@614
|
455 |
<iframe width="420" height="315"
|
jaroslav@614
|
456 |
src="http://www.youtube.com/embed/EvaTejQDRwA"
|
jaroslav@614
|
457 |
frameborder="0" allowfullscreen>
|
jaroslav@614
|
458 |
</iframe>
|
jaroslav@166
|
459 |
</body>
|
jaroslav@166
|
460 |
</html>
|