Configurable custom cron in asset publisher subscriptions

Using regular expressions to send subscriptions

Check spanish version here

A few weeks ago we had the need to set a specific time for sending an email with the new content generated in a asset publisher through the subscription functionality.

This led us to investigate whether it was feasible to carry out this modification in a simple way.

What is running and how?

The first step was to access the Liferay administration and check if there was an OOTB way in the system or instance configuration to set a regex for sending subscriptions:

As it is clearly detailed in the "Check interval" field information, this configuration only allows to set a number of hours. So that we decided to carry out the following steps:

1. Identify the method that runs the check for new assets on an asset publisher. In this case, shown in the following image, the "guilty" is the "CheckAssetEntryMessageListener" component.

2. Within the previous class, you can see how a trigger is created through the number of hours established as the asset publisher's system configuration through the "Check interval" field and the time unit, which in this case were HOURS.

Trigger trigger = _triggerFactory.createTrigger(className, className, null, null, assetPublisherWebConfiguration.checkInterval(), TimeUnit.HOUR);

To summarize, this component checks for new content every X hours, where X is the value set in the "Check interval" field.

Let's go!

Now, once the problem has been identified, what we need is to know how to modify this behavior and make it as less intrusive and simple as possible. For that:

1. Following the same logic proposed in the "CheckAssetEntryMessageListener" component, if we look at the parameter passing options that the "createTrigger" method allows, we see how a regular expression (cron expression) can be used:

2. Add the "CheckAssetEntryMessageListener" component to the black list, as we will do is to create a similar custom component but modifying the input parameters of the "createTrigger" method. For this we will use the configuration file "com.liferay.portal.component.blacklist.internal.ComponentBlacklistConfiguration.config", located in the path "@liferay_home@/osgi/configs" with the following content:

blacklistComponentNames=[ \
  "com.liferay.asset.publisher.web.internal.messaging.CheckAssetEntryMessageListener", \
  ]

3. Once we have blacklisted the "CheckAssetEntryMessageListener" component we need to create our custom component.

3.1. We create an API type module, for example, which is one of the most basic.

3.2. We add the required dependencies in the "build.gradle" file, paying special attention to these 5 additional ones:

compileOnly group: "com.liferay", name: "com.liferay.asset.publisher.api"
compileOnly group: "com.liferay", name: "com.liferay.asset.publisher.web"
compileOnly group: "com.liferay", name: "com.liferay.petra.string"
compileOnly group: "com.liferay", name: "com.liferay.portal.configuration.metatype.api"
compileOnly group: "biz.aQute.bnd", name: "biz.aQute.bndlib", version: "3.1.0"

3.3. We create a new class inside the new module, for example "CustomCheckAssetEntryMessageListener", and copy the code of the main component "CheckAssetEntryMessageListener".

3.3.1. Now we need to modify three key points so that our custom component is 100% functional and does not depend on the main component:

3.3.2. ConfigurationPid: We create a new configuration class (eg "CustomAssetPublisherWebConfiguration") in which we are going to establish a field to add the regular expression that we will later use to create the trigger and launch the check for new assets. Once created, we set this configuration as the configurationPid of our new component:

3.3.3. Retrieve the custom configuration: After creating the new configuration and adding it to the properties of our new component, it is necessary to refer to it and retrieve it to obtain the regular expression that will be set as the system configuration. To do this, just change in the first lines of the "activate" method the AssetPublisherWebConfiguration class used by the main component for our new CustomAssetPublisherWebConfiguration configuration or whatever you have called it.

3.3.4. CreateTrigger method: Finally, it would be necessary to modify the parameter passing for the createTrigger method to pass it a regular expression instead of using the number of hours and the time unit.

4. The next step would be to compile and deploy the component to check that everything has gone correctly .............. OH WAIT!!. We see that when deploying the module and trying to start it, logs indicate that there is a dependency on an internal class "com.liferay.asset.publisher.web.internal.messaging.AssetEntriesCheckerUtil" which is actually in charge of obtaining the assets. How can we solve this?

Well, to solve this error we are going to read a very interesting post written by David H Nebinger in which he indicates how to proceed to export / expose the necessary package "com.liferay.asset.publisher.web. internal.messaging" within the "asset-publisher-web" module to resolve the error. For more information on how to perform this step:

https://liferay.dev/blogs/-/blogs/fixing-module-package-access-modifiers

5. Finally, and once the "fix" of the error for the internal package of the asset-publisher-web module has been deployed, we will deploy our module again and once started, by accessing the system configuration, we will be able to establish our custom regular expression.


 

Conclusion

In this way we can establish the sending of subscriptions at a precise time that any user with access permissions to the system configuration can establish through a regular expression.

Thank Jorge Díaz for his great support and management work to include this functionality in future versions:

Yes! In Liferay 7.4, it will be possible to schedule the sending of notifications for asset publisher subscriptions OOTB.
Blogs