Guide to Using JavascriptService

Updated at 1781769760000
JavascriptService is the bridge between JavaScript code and Java beans in EzyPlatform. When a script is passed in, the system does not treat it as plain text. Instead, it creates a Mozilla Rhino runtime scope, injects the required objects such as parameters, properties, console, logger, beanContext, the getBean(...) function, and any pre-included beans, then executes the script.
A key update is that JavascriptService no longer only supports running a script and returning a string. It now also supports the JavascriptFunction mechanism, which allows callers to customize how a script is executed and how its result is converted. In particular, ObjectResultJavascriptFunction allows JavaScript to return an object, array, number, boolean, or string as the corresponding Java object.

General architecture

flowchart LR
    A["JavaScript source code"] --> B["JavascriptService.execute"]
    B --> C["Create Rhino Context"]
    C --> D["Create JavaScript scope"]
    D --> E["Inject parameters"]
    D --> F["Inject properties"]
    D --> G["Inject console and logger"]
    D --> H["Inject beanContext"]
    D --> I["Inject getBean(name)"]
    D --> J["Inject included beans"]
    J --> K["Run JavascriptFunction"]
    K --> L["Default: return String"]
    K --> M["ObjectResult: return Object / Map / List"]

Execution flow

When JavascriptService.execute(...) is called, the service:
  1. Opens a Rhino Context.
  2. Creates a standard JavaScript scope with initStandardObjects().
  3. Injects default variables and functions into the scope:
    • console
    • logger
    • beanContext
    • getBean(name)
    • properties
  4. Injects every entry from parameters directly into the scope.
  5. Injects beans registered through includeBeanName(...).
  6. Delegates execution to a JavascriptFunction.
  7. Returns the result to Java.

Default objects available in scripts

Inside JavaScript, you can directly use:
console.log("Hello", name);
logger.info("Running script");
properties.get("siteName");
var service = getBean("someService");
Where:
  • parameters are injected directly as named variables.
  • properties comes from the application properties.
  • getBean(name) retrieves a bean by name from the bean context.
  • beanContext is also exposed to the scope.
  • console.log(...) prints a simple log to standard output.
  • logger is the service logger.
Example:
Map<String, Object> parameters = new HashMap<>();
parameters.put("name", "EzyPlatform");

Object result = javascriptService.execute(
    "var greeter = getBean('greetingBean'); greeter.greet(name)",
    parameters
);
The script can use name directly:
var greeter = getBean('greetingBean');
greeter.greet(name)

Default string result

The simplest API is:
Object result = javascriptService.execute(
    "name + ' platform'",
    parameters
);
This uses DefaultJavascriptFunction.
If the script returns a valid value, the result is converted to a String using toString().
For example:
21 * 2
returns:
"42"
If the script is blank, returns null, or returns undefined, the service returns an empty string.

Returning objects with ObjectResultJavascriptFunction

When structured data is needed, use ObjectResultJavascriptFunction:
Object result = javascriptService.execute(
    parameters,
    new JavascriptService.ObjectResultJavascriptFunction(
        "({ id: 1, name: name, tags: ['admin', 'web'], active: true })"
    )
);
The Java result will be a Map:
{
    id: 1,
    name: "EzyPlatform",
    tags: ["admin", "web"],
    active: true
}
ObjectResultJavascriptFunction handles common types as follows:
  • JavaScript object -> Map<String, Object>
  • JavaScript array -> List<Object>
  • string -> String
  • number -> Number
  • boolean -> Boolean
  • null or undefined -> null
Nested objects and arrays are also supported.
Example:
({
    user: {
        id: 1,
        name: "admin"
    },
    roles: ["admin", "editor"],
    enabled: true
})
This is converted into a Map containing nested Map, List, String, Number, and Boolean values.

Including beans with aliases

In addition to dynamically retrieving beans with getBean(name), the service still supports including beans into the scope with fixed aliases:
javascriptService.includeBeanName(
    "sumBean",
    "calculator"
);
The script can then use:
calculator.sum(a, b)
This is useful when a plugin or runtime always needs to expose a known set of beans to scripts.
If a bean does not exist in the bean context, that alias will not be injected into the scope.

The javascript_service_bean_names setting is no longer used

In the current version, JavascriptService no longer reads bean mappings from the javascript_service_bean_names setting.
That means the following parts from the previous article are no longer accurate:
  • reading bean mappings from settings,
  • setting cache,
  • refreshing based on last updated time,
  • setting-based aliases overriding aliases included in code.
Currently, there are two main ways to access beans in scripts:
var service = getBean("javaBeanName");
or include the bean in Java first:
javascriptService.includeBeanName("javaBeanName", "jsAlias");
then use:
jsAlias.doSomething()

Usage in admin and web

In practice, developers usually use the runtime-specific wrappers:
  • AdminJavascriptService in the admin runtime
  • WebJavascriptService in the web runtime
Both services inherit the same mechanism from JavascriptService. They share the same scope creation, parameter injection, bean exposure, and Rhino execution behavior.

Example: returning API data

A useful new use case is writing a script that calls a Java service, builds a JavaScript object, and returns it to Java as structured data.
Example:
Map<String, Object> parameters = new HashMap<>();
parameters.put("requestArguments", arguments);

return javascriptService.execute(
    parameters,
    new JavascriptService.ObjectResultJavascriptFunction(
        "var userService = getBean('userService');" +
        "var user = userService.getUserById(requestArguments.getParameter('id'));" +
        "({" +
        "    id: user.getId()," +
        "    name: user.getName()," +
        "    active: user.isActive()" +
        "})"
    )
);
The script returns a JavaScript object:
({
    id: user.getId(),
    name: user.getName(),
    active: user.isActive()
})
Java receives a Map, which is convenient for returning a JSON response or further processing.

Accessing Java classes from JavaScript

Because the service uses Mozilla Rhino, scripts can access Java classes through Packages.
Example:
var JavaLong = Packages.java.lang.Long;
var value = JavaLong.valueOf("123");
You can also use Java classes to call APIs, builders, models, filters, or internal services if the runtime allows it.

Security note

Scripts run with powerful access to the application runtime:
  • reading properties,
  • calling getBean(...),
  • accessing beanContext,
  • invoking Java beans,
  • accessing Java classes through Rhino.
For that reason, scripts passed to JavascriptService must come from trusted sources, such as internal configuration or application code. Do not pass user-controlled JavaScript directly into this service.

When to use each option

Use execute(script, parameters) when:
  • you only need a string result,
  • the script is simple,
  • the result is used for text rendering or small calculations.
Use ObjectResultJavascriptFunction when:
  • you need to return an object,
  • you need to return a list,
  • you want to preserve number, boolean, and string values,
  • you want to build a JSON-style response from JavaScript.
Use getBean(name) when:
  • you need to retrieve beans dynamically inside the script,
  • you do not want to include aliases beforehand.
Use includeBeanName(...) when:
  • scripts frequently use the same bean,
  • you want a shorter and more readable alias,
  • you want explicit configuration in plugin or runtime code.

Conclusion

JavascriptService is now a flexible runtime bridge between JavaScript and Java beans. The new version is simpler in bean configuration because it no longer depends on setting-based mappings or cache refreshes, while becoming more powerful in execution through JavascriptFunction and ObjectResultJavascriptFunction.

Table Of Contents