Hybris Scripting Engine
Reference :https://wiki.hybris.com/display/release5/hybris+Scripting+Engine
What Can I Use Scripts For?
These are just some example applications of scripts:
Supported Languages
Scripting Engine implementation in hybris platform is based on the JSR-223 standard. At the moment, three languages are supported out-of-the-box:
- Groovy
- BeanShell
- JavaScript
It is possible to add more languages from the JSR-223 support list, see Adding New Languages.
API Overview
From the user perspective, the API is very simple. It is based on four main interfaces:
- ScriptingLanguagesService provides methods for obtaining a ScriptExecutable object.
- ScriptExecutable represents an executable object, which provides methods for executing it.
- ScriptContent represents an object that wraps script content in a specific language type.
- ScriptExecutionResult represents the script execution result.
Creating Scripts
There are three ways of creating scripts:
- programmatically
- using hybris Administration Console. For details, see Scripting Tab in hybris Administration Console - End User Guide
- using hMC. For details, see Managing Scripts in hMC
Let's create a Groovy script, which searches for all Media types that have the mime attribute empty, and sets the value of this attribute based on their realFilename attribute.
Note how the interaction with the spring context is done. You can access any Spring bean from the hybris application context by referring to a special spring global variable. This topic is covered later on in this document.
Executing Scripts
Tip
Scripts are run with the same rights that the current user has.
Warning
Scripts are not secured in any way, so you can use any language-specific structures; hence, calling System.exit(-1) is possible.
Now that you have this code sample, let's execute it directly by using the ScriptingLanguagesService. To do that, prepare a special wrapper for the real script content.
Executing Scripts from String - SimpleScriptContent
This implementation allows you to execute the script content directly as a String. Let's imagine that you have the previously mentioned script content in the String variable content:
Executing Scripts from Resources - ResourceScriptContent
Writing scripts directly in the Java code and keeping them in variables is not the most convenient way to do it. It is much better to write them in your favorite editor with syntax highlighting. Script Engine allows you to execute scripts that are resource based, stored for instance on the classpath or directly in the file system.
Executing Scripts from the File System
Assuming that our sample script is located on the disk, with the path /Users/zeus/scripts/setMimesForMedias.groovy, you can execute it as follows:
Executing Scripts by Using Classpath
Or, if you have the same script but in the classpath in the folder scripts:
Executing Scripts Stored Remotely
You can also store the script content remotely, for instance as a gist at github.com under the URL https://gist.githubusercontent.com/zeus/testMimesForMedias.groovy . In this way, it is easy to get hold of and execute:
Keep in mind that ResourceScriptContent determines the script engine name by the proper file extension, thus all scripts stored in files must have valid extensions for the language in which they are written.
Handling Exceptions
The scripting engine implementation uses only unchecked exceptions. This is a list of all exceptions that you can encounter:
Exception
|
Description
|
|---|---|
| de.hybris.platform.scripting.engine.exception.ScriptingException | Main exception class for all scripting engine related exceptions |
| de.hybris.platform.scripting.engine.exception.ScriptExecutionException | Exception thrown when the execution of a script has failed (for instance, a script contains errors in the body of the script) |
| de.hybris.platform.scripting.engine.exception.ScriptCompilationException | Exception thrown when the compilation of a script has failed. |
| de.hybris.platform.scripting.engine.exception.ScriptNotFoundException | Exception thrown when a persisted script cannot be found in the repository. |
| de.hybris.platform.scripting.engine.exception.ScriptURIException | Exception thrown when the Script URI contains an error. |
| de.hybris.platform.scripting.engine.exception.DisabledScriptException | Exception thrown when a given ScriptExecutable is disabled due to previous errors. |
Logging
To turn on logging for the scripting engine, set the logging level to debug by using the property log4j.logger.de.hybris.platform.scripting.engine=DEBUG.
Scripts Backed by Models - ModelScriptContent
hybris Commerce Suite also comes with the model-based ScriptContent that is backed by the Script type. This special type is a container for storing scripts in the database. Let's now create a Script instance that keeps the media maintenance script:
Autodisabling of Model-Based Scripts
Model-based scripts can be autodisabled. This comes in handy if a script throws an execution exception. In that case, the status of an autodisabling script changes to disabled. Otherwise, a faulty script would endlessly throw execution exceptions.
ScriptModel has two boolean properties: autodisabling and disabled . Both are by default set to false. To enable the auto-disabling feature, s et ScriptModel#autodisabling item property to true. You can also use the hMC to set Autodisabling to True.
Scripts are marked as disabled on first throw of de.hybris.platform.scripting.engine.exception.ScriptExecutionException. Each next call to ScriptExecutable#execute on a script which was already marked as disabled throws a de.hybris.platform.scripting.engine.exception.DisabledScriptException
If you want to re-enable the script for execution, go to the hMC, find the corresponding ScriptModel in Scripts section and change the flag disabled to false.
If you want to re-enable the script for execution, go to the hMC, find the corresponding ScriptModel in Scripts section and change the flag disabled to false.
Getting Script Executables by scriptURI
Playing with the ScriptContent interface for something persisted and whose exact address you know is not very handy. You always need to create a proper ScriptContent object. It is better to use the address of the script and get hold of the executable directly. Hence the concept of Script Repositories. A script repository allows you to look for a script in a particular storage - it may be a database, a local disk, or some remote storage. hybris comes with four implementations that are used internally by the ScriptingLanguagesService to resolve script addresses transparently. These are called scriptURIs and prepare appropriate ScriptContent objects behind the scenes to return a ScriptExecutable to the user.
- ModelScriptsRepository
- ClasspathScriptsRepository
- FileSystemScriptsRepository
- RemoteScriptsRepository
ModelScriptsRepository
This repository looks for scripts in the database. It supports the following type of scriptURI:
To get hold of a script using this repository, the user needs to use the ScriptingLanguagesService as follows:
ClasspathScriptsRepository
This repository looks for scripts in the database. It supports the following type of scriptURI
To get hold of a script using this repository, the user needs to use ScriptingLanguagesService as follows:
Keep in mind that scripts in this repository must contain a valid file extension according to the language they are written in.
FileSystemScriptsRepository
This repository looks for scripts in the database. It supports the following type of scriptURI
To get hold of a script using this repository, use the ScriptingLanguagesService as follows:
Scripts in this repository must contain a valid file extension according to the language in which they are written.
RemoteScriptsRepository
This repository looks for scripts in the database. It supports the following type of scriptURI
To get hold of a script using this repository, use the ScriptingLanguagesService as follows:
Scripts in this repository must contain a valid file extension according to the language in which they are written.
Executing a Script Using Arguments - ScriptExecutable and ScriptExecutionResult
So far you have seen a simple usage of ScriptExecutable that shows how to execute a script without any arguments. Let's now look at a more advanced scenario, where you want to fix all mime types in medias whose realFilename has a specific extension:
Now you can execute the script as follows (let's suppose the script is on the classpath) for all medias with a filename with the extension xml:
The example above is written in Groovy. This means that the last line of the script always affects the result. If it returns something, you get a script result Object. If it does not, the call to the ScriptExecutionResult#getScriptResult() returns null. A script may also yield some output. Let's modify the script a little bit to print at the end the number of fixed mime types in Medias:
Now the last line executes the println function, which means that it does not return anything but prints something to the standard output. Now you can read the message.
Note that ScriptExecutionResult contains two methods for getting output and error writers - getOutputWriter() and getErrorWriter(). When calling methods on ScriptExecutable both, by default, return standard StringWriter objects. If you want to pass your own Writer implementation, you may call the method
ScriptExecutable#execute(Map<String, Object> context, Writer outputWriter, Writer errorWriter)Using Returned Objects as Interfaces
It is also possible to get an object of a class from a script and call methods on it directly in the Java code. Let's rewrite our Medias-related script to something more object oriented:
Note that an instance of the class is returned in the last line of the script.
The script above defines a new Groovy class GroovyMimeFixer that implements the Java interface MimeFixer, which you have in the code base and which looks as follows:
Now you can execute this script a bit differently to obtain the object returned by the script:
Accessing Spring Beans
Accessing Spring Beans in Groovy
In all of the examples, the Spring application context was referred to using the global variable spring. This variable is available only at the top level of the script, thus you need to pass it into the classes and other structures that have a limited scope. You can also access spring beans directly by their bean names but remember that top level script scope also applies here. So the following example works:
But this one does not:
You must pass ModelService into the ScriptModelCreator class:
Accessing Beans in Javascript
Javascript is much less strict, so you can access Spring beans directly:
Note how the import of Java FlexibleSearchQuery class is done - via a special Packages object.
Adding New Languages
Adding a new language is simple, but you need to know which libraries are required in the classpath. Here you'll see how to add Ruby. JRuby implementation has built-in JSR-223 support.
First, you need to define library dependencies in appropriate
external-dependencies.xml file:
Next, declare bean of type de.hybris.platform.scripting.engine.internal.ScriptEngineType in the Spring context as follows:
Note the
c namespace in Spring file definition ( http://www.springframework.org/schema/c) - this is a handy shortcut for passing constructor arguments to the bean.
This bean generally represents a new type of the scripting engine and keeps its name, file extension, and mime.
Finally, add a new value to the existing ScriptType enumtype in the hybris type system. This one is required by the Script type mentioned above - if you need to store your scripts into a database. The value is the name of the scripting engine.
That's it - your new language is ready to use.
Methods of interface ScriptExecutable are not synchronised, so the underlying ScriptEngine must provide thread-safety. Before adding a new script language, test that the new language behaves as expected in a multithread environment.
Script Versioning
1) Let's create a simple print script with the code testScript in the Scripting Language Console in hybris Administration Console.
Save the script.
2) Now modify this script such that it prints:
Save the modified script.
3) Modify the script again:
4) Now go to the Browse tab. You can see only one instance of the testScript in the directory tree.
However, if you query the database using the following query, you will see three versions of the testScript.
You can call revision 1 of this script in the following manner:
If you do not specify any revision number, the latest version will be used.
Managing Script Versions in hMC
You can create, edit, and search for your scripts in hMC.
Searching for existing scripts only shows the latest script version. To see all versions, change the Active flag attribute to No preference.




Comments
Post a Comment