Guide to Using JavascriptService
Updated at 1775056778000JavascriptService is the bridge between JavaScript source code and Java beans in EzyPlatform. When a script is submitted, the system does not execute it as raw text directly. Instead, it goes through a clear pipeline: the JavaScript source is passed into JavascriptService, the service builds a JavaScript scope, injects parameters, properties, and the beans that have been exposed, then hands execution over to the JavaScript engine, which is Mozilla Rhino. After the script finishes running, the result is returned to Java for further processing.How it works
flowchart LR
A["JavaScript source code"] --> B["Call JavascriptService execute"]
B --> C["Load parameters from Java"]
B --> D["Load properties from beanContext"]
B --> E["Load beans to expose"]
E --> E1["Beans included in plugin code"]
E --> E2["Beans from javascript_service_bean_names setting"]
C --> F["Create JavaScript scope"]
D --> F
E1 --> G["Map javaBeanName to jsBeanName"]
E2 --> G
G --> H["Get beans from beanContext"]
H --> F
F --> I["JavaScript executor Mozilla Rhino"]
I --> J["Run script"]
J --> K["Return result to Java"]
Step-by-step flow
- The developer prepares the JavaScript source code as a string.
- Java code calls
JavascriptService.execute(...), or usesAdminJavascriptServiceorWebJavascriptServicedepending on the runtime environment. -
JavascriptServicecreates a new JavaScript scope. - The service injects all
parametersfrom Java into the scope so the script can use them directly. - The service also injects the
propertiesvariable frombeanContext.getProperties(). - The service collects beans to expose from two sources:
- Beans included in code through
includeBeanName(...) - Beans configured dynamically through the
javascript_service_bean_namessetting
- Beans included in code through
- For each bean mapping, the service gets the actual bean from
beanContextand exposes it into the JavaScript scope using the configured JavaScript alias. - Once the scope is ready, the service passes the script to the JavaScript executor, Mozilla Rhino.
- Rhino runs the script and returns the result back to Java.
- If the result is
nullorundefined, the service returns an empty string. If a value exists, the default execution flow converts it to a string.
Using it in admin and web
In practice, developers usually do not inject
JavascriptService directly. Instead, they use the runtime-specific wrapper:- Use
AdminJavascriptServicein admin - Use
WebJavascriptServicein web
These two classes share the same execution mechanism. The main difference is the setting context used in each runtime.
How to expose Java beans to JavaScript
There are two main ways to expose Java beans into the JavaScript scope.
Option 1: Include beans directly in plugin code
This is the recommended approach when your plugin always needs a fixed set of beans.
Example in an admin plugin:
@EzyConfigurationAfter @AllArgsConstructor public class AdminEzySeoJavascriptConfig implements EzyBeanConfig { private final AdminJavascriptService javascriptService; @Override public void config() { javascriptService.includeBeanName( "adminPostService", "postService" ); javascriptService.includeBeanName( "adminProductService", "productService" ); } }
After including them this way, your JavaScript code can use:
postService productService
instead of the original Java bean names.
Option 2: Include beans through the javascript_service_bean_names setting
If you want dynamic configuration without changing plugin code, you can define the mapping in the admin setting as JSON:
{
"adminPostService": "postService",
"adminProductService": "productService",
"adminUserService": "userService"
}
Meaning:
- The key is the Java bean name in the system
- The value is the variable name exposed to JavaScript
When the script runs, the service reads the cached setting and exposes the corresponding beans into the scope.
Setting-based configuration flow
flowchart TD
A["Developer updates javascript_service_bean_names setting"] --> B["Save JSON mapping"]
B --> C["Update last updated time"]
C --> D["SettingService detects the change"]
D --> E["Refresh cache"]
E --> F["JavascriptService reads updated cache"]
F --> G["Expose updated beans into JavaScript scope"]
Example usage in admin
Example bean inclusion:
javascriptService.includeBeanName(
"adminUserService",
"userService"
);
Then execute a script like this:
Object result = javascriptService.execute(
"String(userService.getUserByUsername(username).username)",
Collections.singletonMap("username", username)
);
The actual JavaScript is:
String(userService.getUserByUsername(username).username)
Here:
-
usernamecomes fromparameters -
userServicecomes from the included bean - The result is returned back to Java
Important note about setting cache
JavascriptService does not read the raw setting value every time a script runs. Instead, it uses the cached value of javascript_service_bean_names and watches the setting’s last updated time to know when the cache should be refreshed.So when you update this setting in admin, do not forget to check the box
Last update time of this setting. If you do not check it, the new mapping may not be picked up by the cache immediately, and it may look like your configuration is not working.In short:
- Update
javascript_service_bean_names - Check
Last update time of this setting - Save it so the cache can refresh properly
Priority when configurations overlap
If the same bean is defined in both places:
- Included in plugin code
- Configured in the
javascript_service_bean_namessetting
then the value from the setting overrides the one included in code.
This makes it possible to change the JavaScript alias in a live environment without rebuilding the plugin.
A few notes when writing scripts
- Variables in
parametersare injected directly into the JavaScript scope - The
propertiesvariable is always available in the script - If a bean does not exist in
beanContext, it will not be exposed into the script - If the script returns
nullorundefined, the service returns an empty string
When to use each approach
Use plugin-code inclusion when:
- Your plugin always needs that bean
- You want the configuration to be explicit, readable, and easy to review
Use the
javascript_service_bean_names setting when:
- You want to change mappings quickly without modifying code
- You want to add or rename aliases in a live environment