Skip to content
Nedelcho Delchev edited this page Aug 21, 2017 · 6 revisions

API v3.x Guidelines

Since version 3.0 the Javascript API supports also V8 engine. This requires redesign of the API itself, because the Java objects from the JVM are not directly accessible and manageable from the Javascript engine as it is the case for the Rhino and Nashorn engines.

API developers have to follow the rules below when introducing new APIs, which require communication with the JVM underneath:

Static Facades

  1. From the Java side a "facade" has to be implemented with public static methods, which are supposed to be called by the Javascript engine.
  2. It is highly recommended the facade's methods to have input and output parameters only as primitives.
    ...

    public static final String getAttribute(String name) {
		HttpServletRequest request = getRequest();
		if (request == null) {
			throw new InvalidStateException(NO_VALID_REQUEST);
		}
		return request.getAttribute(name) != null ? request.getAttribute(name).toString() : null;
    }

    ...
  1. In case of complex parameters needed, a serialization and deserialization to/from JSON have to be considered.
    ...

    public static final String getAttributeNames() {
		HttpServletRequest request = getRequest();
		if (request == null) {
			throw new InvalidStateException(NO_VALID_REQUEST);
		}
		List<String> list = Collections.list(request.getAttributeNames());
		return GsonHelper.GSON.toJson(list.toArray());
    }

    ...
  1. It is highly recommended the the Java facade and Javascript API module to relate to each other as 1:1
  2. The Javascript modules must be placed in repositories in the GitHub's DirigibleLabs organization following the naming convention "api-v3-XXX" where the XXX is the particular name of the API group of modules e.g. core, http, utils, etc.

e.g. https://github.com/dirigiblelabs/api-v3-http

  1. The repository should have a root folder named in the same way as the API group part of the repository following the subfolder "v3". All the modules in this group should be placed under "v3" subfolder and below.
  2. A separate module in the main Eclipse Dirigible repository have to be created under the "content" subfolder containing all the "webjars" modules.

e.g. https://github.com/eclipse/dirigible/tree/3.0-poc/content/api-http

  1. The API which is used in this case is call() of the built-in java module.
    ...

    exports.getAttribute = function(name) {
	var attr = java.call('org.eclipse.dirigible.api.v3.http.HttpRequestFacade', 'getAttribute', [name]);
	return attr;
    };

    ...

    exports.getAttributeNames = function() {
	var attrNamesJson = java.call('org.eclipse.dirigible.api.v3.http.HttpRequestFacade', 'getAttributeNames', []);
	var attrNames = JSON.parse(attrNamesJson);
	return attrNames;
    };

    ...
  1. The necessary test cases have to be introduced in the "dirigible-api-tests" module https://github.com/eclipse/dirigible/blob/3.0-poc/modules/api-tests/src/main/java/org/eclipse/dirigible/api/v3/test/AbstractApiSuiteTest.java, to guarantee the compatibility between the Javascript engines.

e.g. https://github.com/eclipse/dirigible/tree/3.0-poc/modules/api-tests/src/main/resources/http/v3

Object Instantiation

  1. In case it is required (e.g. for performance reasons) to instantiate an object from the Javascript engine side in the JVM side, it can be used the function instantiate() in the java module
  2. To call a method of such an object can be used the invoke() function.
  3. To deallocate the resources in the JVM when the object is no more needed, can be used free() function.
    this.setDate = function(index, value) {
		if(value!==null && value!==undefined) {
			var dateInstance = java.instantiate('java.sql.Date', [value.getTime()]);
			try {
				java.invoke(this.uuid, 'setDate', [index, dateInstance.uuid]);
			} finally {
				java.free(dateInstance.uuid);
			}
		} else {
			this.setNull(index, this.SQLTypes.DATE);
		}
	};
  1. In case you expect the return type of the method call to be an Object instance, additional parameter deep have to be added. It is available in the call() as well as in the invoke() functions.
    exports.getConnection = function(databaseType, datasourceName) {
	var instance = java.call('org.eclipse.dirigible.api.v3.db.DatabaseFacade', 'getConnection', [databaseType, datasourceName], true);
	var connection = new Connection();
	connection.uuid = instance.uuid;
	return connection;
    };

    /**
     * Connection object
     */
    function Connection() {
	
	this.prepareStatement = function(sql) {
		var statementInstance = java.invoke(this.uuid, 'prepareStatement', [sql], true);
		var statement = new Statement();
		statement.uuid = statementInstance.uuid;
		return statement;
	};

    ...