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@513
|
100 |
{@link net.java.html.js.JavaScriptResource}("mul.js") <b>class</b> Mul {
|
jaroslav@513
|
101 |
|
jaroslav@513
|
102 |
{@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>
|
jaroslav@513
|
116 |
<a 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
|
jaroslav@513
|
118 |
the <a 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()}
|
jaroslav@513
|
155 |
attribute to <b>true</b>.
|
jaroslav@513
|
156 |
<p></p>
|
jaroslav@513
|
157 |
<em>Editing hint:</em> there is an associated annotation processor
|
jaroslav@513
|
158 |
that checks the syntax and verifies the referenced class and
|
jaroslav@513
|
159 |
method of the right signature exist. If they do not, the
|
jaroslav@513
|
160 |
compilation fails. Thus don't despair seeing the syntax, you'll get early
|
jaroslav@513
|
161 |
warnings when there is a typo.
|
jaroslav@514
|
162 |
|
jaroslav@514
|
163 |
<h3>Arrays by Copy</h3>
|
jaroslav@514
|
164 |
|
jaroslav@514
|
165 |
It is possible to exchange arrays between Java and JavaScript. Some
|
jaroslav@514
|
166 |
implementations can pass arrays by reference, however in some systems
|
jaroslav@514
|
167 |
this is hard to achieve. To choose the least common denominator,
|
jaroslav@514
|
168 |
the TCK for behavior of {@link net.java.html.js.JavaScriptBody} requires
|
jaroslav@514
|
169 |
the arrays to be always transfered by a copy. As such following code:
|
jaroslav@514
|
170 |
<pre>
|
jaroslav@514
|
171 |
{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"arr"}, body = "arr[0] = null;")
|
jaroslav@514
|
172 |
<b>private static native void</b> uselessModify(String[] arr);
|
jaroslav@514
|
173 |
<b>public static void</b> main(String... args) {
|
jaroslav@514
|
174 |
String[] hello = { "Hello", "World!" };
|
jaroslav@514
|
175 |
uselessModify(arr);
|
jaroslav@514
|
176 |
System.out.println(arr[0] + " " + arr[1]);
|
jaroslav@514
|
177 |
}
|
jaroslav@514
|
178 |
</pre>
|
jaroslav@514
|
179 |
will still print <em>Hello World!</em> in spite the JavaScript code
|
jaroslav@514
|
180 |
sets the 0-th array element to <code>null</code>. Because the array
|
jaroslav@514
|
181 |
is passed as a copy, such assignment has no effect on the Java array.
|
jaroslav@514
|
182 |
<p></p>
|
jaroslav@514
|
183 |
In case one needs to modify an array in a JavaScript and use its
|
jaroslav@514
|
184 |
values in Java, one has to return the array back as a return value:
|
jaroslav@514
|
185 |
<pre>
|
jaroslav@514
|
186 |
{@code @}{@link net.java.html.js.JavaScriptBody}(args = {"arr"}, body = "arr[0] = 'Ahoy'; return arr;")
|
jaroslav@515
|
187 |
<b>private static native</b> Object[] usefulModify(String[] arr);
|
jaroslav@514
|
188 |
<b>public static void</b> main(String... args) {
|
jaroslav@514
|
189 |
String[] hello = { "Hello", "World!" };
|
jaroslav@514
|
190 |
Object[] ret = usefulModify(arr);
|
jaroslav@514
|
191 |
System.out.println(ret[0] + " " + ret[1]);
|
jaroslav@514
|
192 |
}
|
jaroslav@514
|
193 |
</pre>
|
jaroslav@514
|
194 |
now the program prints <em>Ahoy World!</em> as the modified array
|
jaroslav@514
|
195 |
is returned back and converted (by a copy) into a Java <code>Object[]</code>
|
jaroslav@514
|
196 |
(but of course the <code>ret != hello</code>). Usually the copy based
|
jaroslav@514
|
197 |
passing of arrays works OK. It is however good to keep it in mind to
|
jaroslav@514
|
198 |
avoid unwanted surprises.
|
jaroslav@514
|
199 |
|
jaroslav@514
|
200 |
<h3>Post Process Classes</h3>
|
jaroslav@530
|
201 |
|
jaroslav@530
|
202 |
Classes with {@link net.java.html.js.JavaScriptBody} annotated methods need to
|
jaroslav@530
|
203 |
be post processed before they can be used - e.g. their <code>native</code>
|
jaroslav@530
|
204 |
body needs to be generated to call into JavaScript (btw. the code is performed
|
jaroslav@530
|
205 |
via {@link org.apidesign.html.boot.spi.Fn}). There are three ways
|
jaroslav@530
|
206 |
such post processing can happen.
|
jaroslav@530
|
207 |
<p></p>
|
jaroslav@530
|
208 |
<b>Compile time</b> processing - this is the preferred method that
|
jaroslav@530
|
209 |
most of the <a href="http://html.java.net">Html Java APIs</a> are using.
|
jaroslav@530
|
210 |
Just include following plugin configuration into your <code>pom.xml</code>
|
jaroslav@530
|
211 |
and your classes will be ready for execution as soon as <em>process-classes</em>
|
jaroslav@530
|
212 |
<a href="http://wiki.apidesign.org/wiki/Maven">Maven</a> phase is over:
|
jaroslav@530
|
213 |
<pre>
|
jaroslav@530
|
214 |
<plugin>
|
jaroslav@530
|
215 |
<groupId>org.netbeans.html</groupId>
|
jaroslav@530
|
216 |
<artifactId>html4j-maven-plugin</artifactId>
|
jaroslav@530
|
217 |
<version>${net.java.html.version}</version>
|
jaroslav@530
|
218 |
<executions>
|
jaroslav@530
|
219 |
<execution>
|
jaroslav@530
|
220 |
<id>js-classes</id>
|
jaroslav@530
|
221 |
<goals>
|
jaroslav@530
|
222 |
<goal>process-js-annotations</goal>
|
jaroslav@530
|
223 |
</goals>
|
jaroslav@530
|
224 |
</execution>
|
jaroslav@530
|
225 |
</executions>
|
jaroslav@530
|
226 |
</plugin>
|
jaroslav@530
|
227 |
</pre>
|
jaroslav@530
|
228 |
This plugin works in orchestration with
|
jaroslav@530
|
229 |
<a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation
|
jaroslav@530
|
230 |
processor</a> associated with {@link net.java.html.js.JavaScriptBody}
|
jaroslav@530
|
231 |
and {@link net.java.html.js.JavaScriptResource} - the processor creates
|
jaroslav@530
|
232 |
list of files that need post-processing. The
|
jaroslav@530
|
233 |
<a href="http://wiki.apidesign.org/wiki/Maven">Maven</a>
|
jaroslav@530
|
234 |
plugin reads these files, processes classes mentioned in them and
|
jaroslav@530
|
235 |
modifies (and deletes at the end) the files to not include classes
|
jaroslav@530
|
236 |
already processed.
|
jaroslav@530
|
237 |
<p></p>
|
jaroslav@530
|
238 |
<b>Instrumentation Agent</b> - one can do processing in runtime
|
jaroslav@530
|
239 |
using JDK's {@link java.lang.instrument.ClassFileTransformer instrumentation}
|
jaroslav@530
|
240 |
abilities. The JAR artifact of <code>org.netbeans.html:net.java.html.boot</code>
|
jaroslav@530
|
241 |
contains an <code>Agent-Class</code> and <code>Premain-Class</code>
|
jaroslav@530
|
242 |
definitions in its manifest. As such one can launch the Java virtual
|
jaroslav@530
|
243 |
machine with
|
jaroslav@530
|
244 |
<pre>
|
jaroslav@530
|
245 |
$ java -javaagent:jarpath=net.java.html.boot-x.y.jar
|
jaroslav@530
|
246 |
</pre>
|
jaroslav@530
|
247 |
and the runtime will take care of processing bytecode of classes
|
jaroslav@530
|
248 |
not yet processed in compile time before they are loaded into the
|
jaroslav@530
|
249 |
virtual machine.
|
jaroslav@530
|
250 |
<p></p>
|
jaroslav@530
|
251 |
<b>Special classloading</b> - when booting your application with
|
jaroslav@530
|
252 |
{@link net.java.html.boot.BrowserBuilder} there is a 3rd option of
|
jaroslav@530
|
253 |
processing the classes. If there are some classes not yet processed
|
jaroslav@530
|
254 |
(remember the files listing them generated by the
|
jaroslav@530
|
255 |
<a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation
|
jaroslav@530
|
256 |
processor</a>), the {@link net.java.html.boot.BrowserBuilder#showAndWait() launching method}
|
jaroslav@530
|
257 |
will create a special classloader to that does the processing before
|
jaroslav@530
|
258 |
loading the bytecode into the virtual machine.
|
jaroslav@530
|
259 |
<p></p>
|
jaroslav@530
|
260 |
The options are rich, however to avoid any troubles, it is recommended
|
jaroslav@530
|
261 |
to perform the <b>compile time</b> processing.
|
jaroslav@514
|
262 |
|
jaroslav@530
|
263 |
<h3>Getting Started</h3>
|
jaroslav@530
|
264 |
|
jaroslav@530
|
265 |
There are many ways to start developing
|
jaroslav@530
|
266 |
<a href="http://html.java.net">Html for Java</a> application.
|
jaroslav@530
|
267 |
However to be sure one chooses the most recent setup, it is recommended
|
jaroslav@530
|
268 |
to switch to good old command line and use a
|
jaroslav@530
|
269 |
<a href="http://wiki.apidesign.org/wiki/Knockout4Java">Maven archetype</a>
|
jaroslav@530
|
270 |
associated with every version of this project. Just type:
|
jaroslav@530
|
271 |
<pre>
|
jaroslav@530
|
272 |
$ mvn archetype:generate \
|
jaroslav@530
|
273 |
-DarchetypeGroupId=org.apidesign.html \
|
jaroslav@530
|
274 |
-DarchetypeArtifactId=knockout4j-archetype \
|
jaroslav@530
|
275 |
-DarchetypeVersion=x.y
|
jaroslav@530
|
276 |
</pre>
|
jaroslav@530
|
277 |
Answer few questions (for example choose myfirstbrwsrpage as artifactId) and then you can:
|
jaroslav@530
|
278 |
<pre>
|
jaroslav@530
|
279 |
$ cd myfirstbrwsrpage
|
jaroslav@530
|
280 |
$ mvn process-classes exec:java
|
jaroslav@530
|
281 |
</pre>
|
jaroslav@530
|
282 |
In a few seconds (or minutes if
|
jaroslav@530
|
283 |
<a href="http://wiki.apidesign.org/wiki/Maven">Maven</a>
|
jaroslav@530
|
284 |
decides to download the whole Internet of dependencies) you should
|
jaroslav@530
|
285 |
see a sample Hello World application. It is basically composed from one
|
jaroslav@530
|
286 |
Java and one HTML file:
|
jaroslav@530
|
287 |
<pre>
|
jaroslav@530
|
288 |
$ ls src/main/java/**/DataModel.java
|
jaroslav@530
|
289 |
$ ls src/main/webapp/pages/index.html
|
jaroslav@530
|
290 |
</pre>
|
jaroslav@530
|
291 |
Play with them, modify them and enjoy
|
jaroslav@530
|
292 |
<a href="http://html.java.net">Html for Java</a>!
|
jaroslav@166
|
293 |
</body>
|
jaroslav@166
|
294 |
</html>
|