Java bridge

Contents

JavaScript developers may directly invoke and use Java-based code, since the XP runtime builds on the JVM.

The __ object

In Enonic XP, there is a global object named __ (double underscore), accessible from any serverside JavaScript code, which provides a way to wrap Java objects in a JavaScript object. The __ object has functions that allow JavaScript to communicate with Java classes. The newBean function will wrap the Java object named in the parameter, for instance:

var bean = __.newBean('com.enonic.xp.lib.io.IOHandlerBean');

This line is from the lib-io library, which is a good example of how this is used. In the Java IOHandlerBean class, there are several methods, like the readLines method:

public List<String> readLines( final Object value )
  throws Exception
    {
      final CharSource source = toCharSource( value );
      return source.readLines();
    }

This method is now accessible as a function on the JavaScript bean and may be invoked from JavaScript, like this:

exports.readLines = function (stream) {
  return __.toNativeObject(bean.readLines(stream));
  };

This results in a global JavaScript function readLines. This example also shows the use of the toNativeObject method, which in this case, converts a Java String array to a JSON object.

Java objects constructed by newBean may, but not required to, implement com.enonic.xp.script.bean.ScriptBean interface. ScriptBean::initialize is used to inject com.enonic.xp.script.bean.BeanContext object, which can be used to access the application and resource keys, as well as current Request, Context and XP Java API Services.

Passing parameters to Java

There are 2 ways to pass parameters to a Java method, from JavaScript:

  • Passing the parameters in the method call

  • Setting the parameters as properties in the Java object, and then calling the method without parameters

The first one is recommended when there are few parameters (1 or 2) and of simple types. The second one is better when there are multiple parameters, or some of them are optional.

exports.doSomething = function (param1, param2) {
    var bean = __.newBean('com.enonic.lib.mylib.MyClass');

    return bean.execute(param1, param2);
};

exports.doSomethingElse = function (params) {
    var bean = __.newBean('com.enonic.lib.mylib.MyClass');

    bean.text = __.nullOrValue(params.text) || '';
    bean.size = __.nullOrValue(params.size) || 250;

    return bean.execute();
};
When passing values that might be null or undefined it is recommended to filter them using the __.nullOrValue built-in function. This function converts any value that is null or undefined in JavaScript to null in Java. Otherwise returns the input value without changes.

To be able to set property values as in the 2nd example above, the Java object must implement a setter method for each field.

The Java class used in the example above looks like this:

package com.enonic.lib.mylib;

public final class MyClass {
    private String text;
    private Long size;

    public String something( String param1, Long param2 ) {
        return "Parameters: " + param1 + " " + param2;
    }

    public String somethingElse() {
        return "Parameters: " + this.text + " " + this.size;
    }

    public void setText( String text ) {
        this.text = text;
    }

    public void setSize( Long size ) {
        this.size = size;
    }
}

Parameter conversions

There are some type conversions that are made when calling from JavaScript to Java:

  • when passing a JavaScript string, the Java method should expect a Java String

  • when passing a JavaScript boolean, the Java method should expect a Java Boolean

  • when passing a JavaScript number, the Java method should expect a Java Long, Integer or Double

  • when passing a JavaScript array, the Java method should expect a Java List

  • when passing a JavaScript object, the Java method should expect a Java Map<String, Object>

Returning results from Java

When returning simple values from Java to a JavaScript caller, the same type conversions applies.

To return complex object values, you should create a specific Java class to make the mapping. This class should implement the MapSerializable interface. It will implement the serialize method, which allows generating a JSON object.

Serialization example
package com.enonic.lib.mylib;

import java.util.Map;

import com.enonic.xp.script.serializer.MapGenerator;
import com.enonic.xp.script.serializer.MapSerializable;

public final class ExampleObjectMapper
    implements MapSerializable
{
    private final String text;

    private final Object[] array;

    private final Map<String, Object> object;

    public ExampleObjectMapper( String text, Object[] array, Map<String, Object> object )
    {
        this.text = text;
        this.array = array;
        this.object = object;
    }

    @Override
    public void serialize( MapGenerator gen )
    {
        gen.value( "text", text );
        gen.array( "arrayValues" );
        for ( Object value : array )
        {
            gen.value( value );
        }
        gen.end();

        gen.map( "objectValues" );
        for ( String key : object.keySet() )
        {
            gen.value( key, object.get( key ) );
        }
        gen.end();
    }
}

Finally, for returning values of type binary stream from Java, it should be wrapped on a ByteSource object. This is required by XP to allow returning it from an HTTP request, or add it as a content attachment.

Functions

disposer

Add a disposer that is called when the app is stopped.

Parameters

Name Kind Details

func

Function to call

Returns

void

newBean

Creates a new JavaScript bean that wraps the given Java class and makes it’s methods available to be called from JavaScript.

Parameters

Name Kind Details

name

Classname for bean to create

Returns

void

nullOrValue

Converts a JavaScript variable that is undefined to a Java null object. If the JavaScript variable is defined, it is returned as is.

Parameters

Name Kind Details

value

Value to convert

Returns

void

registerMock

Registers a mock

Parameters

Name Kind Details

name

Name of mock

value

Value to register

Returns

void

toNativeObject

Converts arrays or complex Java objects to JSON.

Parameters

Name Kind Details

value

Value to convert

Returns

void

toScriptValue

Converts JSON to a Java Map structure that can be used as parameters to a Java method on a bean created with newBean.

Parameters

Name Kind Details

value

Value to convert

Returns

void


Contents

Contents