Sample usage of @JavaScriptBody annotation. Preprocessing classes and adding a Js/Java interoperability test
1.1 --- a/ko/archetype/src/main/resources/archetype-resources/pom.xml Thu Jan 23 20:03:25 2014 +0100
1.2 +++ b/ko/archetype/src/main/resources/archetype-resources/pom.xml Tue Feb 04 09:32:27 2014 +0100
1.3 @@ -43,6 +43,7 @@
1.4 <bck2brwsr.launcher.version>${project.version}</bck2brwsr.launcher.version>
1.5 <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
1.6 <brwsr.startpage>pages/index.html</brwsr.startpage>
1.7 + <netbeans.compile.on.save>none</netbeans.compile.on.save>
1.8 </properties>
1.9 <build>
1.10 <plugins>
1.11 @@ -64,6 +65,19 @@
1.12 </configuration>
1.13 </plugin>
1.14 <plugin>
1.15 + <groupId>org.netbeans.html</groupId>
1.16 + <artifactId>html4j-maven-plugin</artifactId>
1.17 + <version>${net.java.html.version}</version>
1.18 + <executions>
1.19 + <execution>
1.20 + <id>js-classes</id>
1.21 + <goals>
1.22 + <goal>process-js-annotations</goal>
1.23 + </goals>
1.24 + </execution>
1.25 + </executions>
1.26 + </plugin>
1.27 + <plugin>
1.28 <groupId>org.apache.maven.plugins</groupId>
1.29 <artifactId>maven-compiler-plugin</artifactId>
1.30 <version>2.3.2</version>
1.31 @@ -110,7 +124,7 @@
1.32 <dependency>
1.33 <groupId>org.testng</groupId>
1.34 <artifactId>testng</artifactId>
1.35 - <version>6.5.2</version>
1.36 + <version>6.7</version>
1.37 <scope>test</scope>
1.38 </dependency>
1.39 <dependency>
1.40 @@ -131,6 +145,12 @@
1.41 <version>\${net.java.html.version}</version>
1.42 <type>jar</type>
1.43 </dependency>
1.44 + <dependency>
1.45 + <groupId>org.netbeans.html</groupId>
1.46 + <artifactId>net.java.html.boot</artifactId>
1.47 + <version>\${net.java.html.version}</version>
1.48 + <type>jar</type>
1.49 + </dependency>
1.50 </dependencies>
1.51 <profiles>
1.52 <profile>
1.53 @@ -211,6 +231,9 @@
1.54 <compilerArguments>
1.55 <bootclasspath>netbeans.ignore.jdk.bootclasspath</bootclasspath>
1.56 </compilerArguments>
1.57 + <testExcludes>
1.58 + <exclude>**/JsInteractionTest*</exclude>
1.59 + </testExcludes>
1.60 </configuration>
1.61 </plugin>
1.62 <plugin>
2.1 --- a/ko/archetype/src/main/resources/archetype-resources/src/main/java/DataModel.java Thu Jan 23 20:03:25 2014 +0100
2.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/java/DataModel.java Tue Feb 04 09:32:27 2014 +0100
2.3 @@ -25,7 +25,21 @@
2.4 @Function static void turnOn(Data model) {
2.5 model.setOn(true);
2.6 }
2.7 - @Function static void turnOff(Data model) {
2.8 - model.setOn(false);
2.9 +
2.10 + @Function static void turnOff(final Data model) {
2.11 + confirmByUser("Really turn off?", new Runnable() {
2.12 + @Override
2.13 + public void run() {
2.14 + model.setOn(false);
2.15 + }
2.16 + });
2.17 }
2.18 +
2.19 + /** Shows direct interaction with JavaScript */
2.20 + @net.java.html.js.JavaScriptBody(
2.21 + args = { "msg", "callback" },
2.22 + javacall = true,
2.23 + body = "alert(msg); callback.@java.lang.Runnable::run()();"
2.24 + )
2.25 + static native void confirmByUser(String msg, Runnable callback);
2.26 }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/JsInteractionTest.java Tue Feb 04 09:32:27 2014 +0100
3.3 @@ -0,0 +1,103 @@
3.4 +package ${package};
3.5 +
3.6 +import java.io.Closeable;
3.7 +import java.io.Reader;
3.8 +import java.net.URL;
3.9 +import java.util.ArrayList;
3.10 +import java.util.List;
3.11 +import javax.script.Invocable;
3.12 +import javax.script.ScriptEngine;
3.13 +import javax.script.ScriptEngineManager;
3.14 +import javax.script.ScriptException;
3.15 +import org.apidesign.html.boot.spi.Fn;
3.16 +import static org.testng.Assert.assertEquals;
3.17 +import org.testng.annotations.AfterMethod;
3.18 +import org.testng.annotations.BeforeMethod;
3.19 +import org.testng.annotations.Test;
3.20 +
3.21 +/** Tests for behavior of @JavaScriptBody methods. Set your JavaScript
3.22 + * environment up (for example define <code>alert</code> or use some
3.23 + * emulation library like <em>env.js</em>), register script presenter
3.24 + * and then you can call methods that deal with JavaScript in your tests.
3.25 + */
3.26 +public class JsInteractionTest {
3.27 + private Closeable jsEngine;
3.28 + @BeforeMethod public void initializeJSEngine() throws Exception {
3.29 + jsEngine = Fn.activate(new ScriptPresenter());
3.30 + }
3.31 +
3.32 + @AfterMethod public void shutdownJSEngine() throws Exception {
3.33 + jsEngine.close();
3.34 + }
3.35 +
3.36 + @Test public void testCallbackFromJavaScript() throws Exception {
3.37 + class R implements Runnable {
3.38 + int called;
3.39 +
3.40 + @Override
3.41 + public void run() {
3.42 + called++;
3.43 + }
3.44 + }
3.45 + R callback = new R();
3.46 +
3.47 + DataModel.confirmByUser("Hello", callback);
3.48 +
3.49 + assertEquals(callback.called, 1, "One immediate callback");
3.50 + }
3.51 +
3.52 + private static class ScriptPresenter implements Fn.Presenter {
3.53 + private final ScriptEngine eng;
3.54 +
3.55 + public ScriptPresenter() throws ScriptException {
3.56 + eng = new ScriptEngineManager().getEngineByName("javascript");
3.57 + eng.eval("function alert(msg) { Packages.java.lang.System.out.println(msg); };");
3.58 + }
3.59 +
3.60 + @Override
3.61 + public Fn defineFn(String code, String... names) {
3.62 + StringBuilder sb = new StringBuilder();
3.63 + sb.append("(function() {");
3.64 + sb.append(" return function(");
3.65 + String sep = "";
3.66 + for (String n : names) {
3.67 + sb.append(sep).append(n);
3.68 + sep = ",";
3.69 + }
3.70 + sb.append(") {\n");
3.71 + sb.append(code);
3.72 + sb.append("};");
3.73 + sb.append("})()");
3.74 +
3.75 + final Object fn;
3.76 + try {
3.77 + fn = eng.eval(sb.toString());
3.78 + } catch (ScriptException ex) {
3.79 + throw new IllegalStateException(ex);
3.80 + }
3.81 + return new Fn(this) {
3.82 + @Override
3.83 + public Object invoke(Object thiz, Object... args) throws Exception {
3.84 + List<Object> all = new ArrayList<Object>(args.length + 1);
3.85 + all.add(thiz == null ? fn : thiz);
3.86 + for (int i = 0; i < args.length; i++) {
3.87 + all.add(args[i]);
3.88 + }
3.89 + Object ret = ((Invocable)eng).invokeMethod(fn, "call", all.toArray()); // NOI18N
3.90 + return fn.equals(ret) ? null : thiz;
3.91 + }
3.92 + };
3.93 + }
3.94 +
3.95 + @Override
3.96 + public void displayPage(URL page, Runnable onPageLoad) {
3.97 + // not really displaying anything
3.98 + onPageLoad.run();
3.99 + }
3.100 +
3.101 + @Override
3.102 + public void loadScript(Reader code) throws Exception {
3.103 + eng.eval(code);
3.104 + }
3.105 + }
3.106 +}