Writing native JavaScript code with @j2sNative

the @j2sNative is perhaps the more important @j2s directive of all. It allow the java programmer to replace a java block or method body with native javascript code.

Let's take simple example: you want to get current browser name in your java code. Java doesn't provide with such functionality, so we must to do it with native JavaScript code. (Remember that in javascript we can get the full browser name with the statement navigator.userAgent). For doing this we will use the @j2sNative JavaDoc annotation for embbeding native javascript code inside the java code. In the following example, notice the java comment with the @j2sNative string and the javascript code before the empty java block {}:


String fullBrowserName = null;                            (1)

/**                                                       (2)
 * @j2sNative                                             (3)
 * fullBrowserName = navigator.userAgent;                 (4)
 */{}                                                     (5)
 
System.out.println("Full browser name is : "+fullBrowserName);
(1)
Define a java String variable named fullBrowserNamefor storing the Browser name
(2)
Here starts JavaDoc that will be use for embbeding native javascript in our java code
(3)
we use the annotation @j2sNative for indicating to the Java2Script compiler that the next java block must be replaced with þe javascript code that follows this annotation ( fullBrowserName = navigator.userAgent; ).
(4)
This is the native javascript code that will replace the next java block of code. Notice that the "*" characters in the javadoc are ommited and that the native code goes from after the @j2sNative annotation to the end of the JavaDoc. Also notice that in this case we are assigning the value of the native string navigator.userAgent to the java variable fullBrowserName
(5)
This is the java code block that the @j2sNative directy will apply to. The body of this java block will be replaced by the native javascript code inside the javadoc.

The above code will be translated to the following javascript code:


var fullBrowserName = null;
{fullBrowserName = navigator.userAgent;}
System.out.println ("Full browser name is : " + fullBrowserName);

Notice how the empty java code block has been filled with the native javascript code that we introduced inside the @j2sNative JavaDoc.

Since this compiler directive is so important and has several usage scenarios, we will discuss its usage in detail in a separate chapter Chapter 9.

A more complex example that shows all use cases. Read the javadocs for info about each of them.


package net.sf.j2s.tutorial.debug;

public class HelloJ2SNative {
  /**
   * For java native methods, if Java2Script native codes are given, the
   * native method will be generated when Java2Script compiler is enabled
   *
   * @j2sNative
   * var styleCSS = "position:absolute;left:150px;top:5px;width:100px;height:40px;" 
   *    + "text-align:center;font-weight:bold;color:yellow;background-color:blue;" 
   *    + "border:1px solid red;";
   * var hiEl = document.createElement("<div style=\"" +  styleCSS + "\"></div>");
   * document.body.appendChild(hiEl);
   * hiEl.appendChild (document.createTextNode ("Hi!"));
   */
  native static void sayHi();
  
  /**
   * For java native methods, if you did not define Java2Script native codes,
   * the method will be simply ignored when generating the JavaScript codes.
   */
  native static void sayWell();
  
  /**
   * When j2sNative is defined fro a method, the method body will be overrided
   * with the given native JavaScript codes.
   *
   * @j2sNative alert ("Hello, JavaScript");
   */
  static void sayHello() {
    System.out.println("Hello, Java");
  }
  
  static void sayHei(String name) {
    if(name != null) 
    /**
     * For a normal block, inert j2sNative Javadoc before the brace will
     * replace the inner block body.
     *
     * @j2sNative alert ("Hei, " + name); 
     */
    {
      System.out.println("Hei, " + name + ", how are you?");
    } else
    /**
     * @j2sNative alert ("Hei.");
     */
    {
      System.out.println("Hei, how are you?");
    }
  }
  
  static void saySomething() {
    /**
     * Insert JavaScript only codes with an empty brace block.
     *
     * @j2sNative alert ("En, things will go fine.");
     */ 
    {}
  }
  
  public static void main(String[] args) {
    /*
     * When running from Java, the following line must be commented, as
     * there are not implemented native codes for the native method #sayHi
     */
    sayHi();
    sayHello();
    sayHei("Josson");
    saySomething();
  }
}

And the following is the generated javascript code. We indicate mark with 2 new lines where the native code embbeded with @j2sNative is for each directive call.


Clazz.declarePackage ("net.sf.j2s.tutorial.debug");
c$ = Clazz.decorateAsClass (function () {
Clazz.instantialize (this, arguments);
}, net.sf.j2s.tutorial.debug, "HelloJ2SNative");
c$.sayHi = Clazz.defineMethod (c$, "sayHi", 

function () {
var styleCSS = "position:absolute;left:150px;top:5px;width:100px;height:40px;"
+ "text-align:center;font-weight:bold;color:yellow;background-color:blue;"
+ "border:1px solid red;";
var hiEl = document.createElement("<div style=\"" +  styleCSS + "\"></div>");
document.body.appendChild(hiEl);
hiEl.appendChild (document.createTextNode ("Hi!"));
});
c$.sayHello = Clazz.defineMethod (c$, "sayHello",
 
function () {
alert ("Hello, JavaScript");
});
c$.sayHei = Clazz.defineMethod (c$, "sayHei", 
function (name) {
if (name != null) {

alert ("Hei, " + name);
} else {

alert ("Hei.");
}}, "String");
c$.saySomething = Clazz.defineMethod (c$, "saySomething", 
function () {
{

alert ("En, things will go fine.");
}});
c$.main = Clazz.defineMethod (c$, "main", 
function (args) {
net.sf.j2s.tutorial.debug.HelloJ2SNative.sayHi ();
net.sf.j2s.tutorial.debug.HelloJ2SNative.sayHello ();
net.sf.j2s.tutorial.debug.HelloJ2SNative.sayHei ("Josson");
net.sf.j2s.tutorial.debug.HelloJ2SNative.saySomething ();
}, "Array");