Creating rules and listeners
As Jahia uses a Java Content repository, it uses the standard JCRObservationManager. This manager observes events on the content repository and passes them to several event listeners implementing the abstract DefaultEventListener class. In the JCRStoreService, Jahia configures several default event listeners which are necessary to make Jahia work. These event listeners are then registered in the JCRObservationManager.
One of these event listeners is the JBoss Rules Listener, which allows integrators to use rules to process events. These rules can be deployed in modules and Jahia also includes default rules.
Content events can be observed through the JCRObservationManager. However, system events (such as the login event) are not routed through the JCRObservationManager, but instead are sent and received through the system framework.
Rules
Each module in Jahia can define its own rules, extend the rule domain specific language, and add its own set of global objects.
Adding rules in a module
Just define a rules.drl file in the resources/META-INF folder of the module. Here is an example from the tasks module:
package org.jahia.modules.tasks.rules
//list any import classes here.
import org.jahia.services.content.rules.*
import org.slf4j.Logger
expander rules.dsl
//declare any global variables here
global User user
global Service service
global Logger logger
global Tasks tasks
rule "A welcome task for the new user"
when
A new node is created
- the node has the type jnt:user
then
Log "Creating welcome task for new user: " + node.getName()
Create task "Welcome to Jahia!" with description "We are glad to have you in our platform." for user node.getName()
end
rule "A notification about new group member"
when
A new node is created
- the node has the type jnt:member
The node has a parent
then
Log "Notifying members of the group '" + parent.getParent().getName() + "' about new member '" + node.getName()
Create task "New member in the group" with description "A new member was added to the group." for members of group parent.getParent().getName()
end
rule "A task has been created"
when
A new node is created
- the node has the type jnt:task
The node has a property assignee
then
Set the property state of the node with the value "active"
Assign permissions "rw-" on the node to the user property.getNode().getName()
end
This module adds some new rule consequences that are not part of the default DSL:
Create task "Welcome to Jahia!" with description "We are glad to have you in our platform." for user node.getName()
And it also defines a global object of type Tasks named tasks:
global Tasks tasks
Extending the domain specific language for rules
You only have to add a rules.dsl file in the WEB-INF/resources folder of your module. An example from the tasks module:
[consequence][]Create task "{title}" with description "{description}" for user {forUser}=tasks.createTask({forUser}, "{title}", "{description}", drools);
[consequence][]Create task "{title}" with description "{description}" for members of group {group}=tasks.createTaskForGroupMembers({group}, "{title}", "{description}", drools);
The extension made in a module will be available for all other modules. If your modules rely on a DSL from another module, you must add this module as a dependency of yours.
Here is an example of using tasks in your own module (say, Jahia RSS Feeds module). In the pom.xml we have:
<Jahia-Depends>tasks</Jahia-Depends>
And the META-INF/rules.drl file content is:
###############################################################################
package org.jahia.modules.rss.rules
#list any import classes here.
import org.slf4j.Logger
import org.jahia.services.content.rules.*
import org.jahia.modules.tasks.rules.*
expander rules.dsl
#declare any global variables here
global User user
global Service service
global Logger logger
global Tasks tasks
###############################################################################
rule "Notification about new RSS feed"
when
A new node is created
- the node has the type jnt:rss
The node has a property url
then
Log "Notifying root about new RSS feed " + property.getStringValue()
Create task "New RSS feed alert" with description "Read the newly added RSS feed, retrieved from '" + property.getStringValue() + "'" for user "root"
end
Note that the rule file must import the org.jahia.modules.tasks.rules.* package and have a definition for tasks global object, for example:
...
import org.jahia.modules.tasks.rules.*
...
global Tasks tasks
...
Adding your own global objects to your rule context for execution
You can find an example of how to register global objects using OSGi here: https://github.com/Jahia/OSGi-modules-samples/tree/master/rules-samples/src/main/java/org/foo/modules/rules
System events
To listen to events sent through the system framework, you need to implement an OSGi event handler. See the example available here: https://github.com/Jahia/OSGi-modules-samples/blob/master/system-events-samples/src/main/java/org/foo/modules/events/OsgiSystemEventHandler.java.
Login and logout events
Login and logout event can be activated, if your application needs to listen to these events. You'll have to add fireLoginEvent and/or fireLogoutEvent properties in your jahia.properties file. An event will then be sent every time a user logs in or out.
JCR Events
You can extend the org.jahia.services.content.DefaultEventListener
class to create a listener on JCR events. The event listener needs to be registered from a module using the following API call: jahiaTemplateManagerService.getTemplatePackageRegistry().handleJCREventListener(listener, register);
The jahiaTemplateManagerService
is accessible through the OSGi service registry with the following interface: org.jahia.api.templates.JahiaTemplateManagerService
See JCR documentation for details on the different event types.