How to add a custom parameter in a standard Magnolia publication workflow

Magnolia CMS workflow can be hook with ease (read more here and here) setting in few minutes standard Magnolia commands where you can whatever your application need.
Now lets go further.
The sample ContextLoggerCommand writes the same lines (of course, with a different execution context or parameter values), both when hooked on workflow launch or on workflow complete command:


2015-05-07 23:55:12,303 INFO  info.magnolia.commands.MgnlCommand                : Logging command parameters: 
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param repository: website
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param recursive: false
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param path: /demo-features
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param modifiedOnly: false
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param uuid: babb5315-f417-4083-9cf1-714bb304742f
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param comment: This is a comment
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param publicationDate: 2015-05-07T23:54:00
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param version: 1.1
2015-05-07 23:55:12,304 INFO  info.magnolia.commands.MgnlCommand                : param requestor: superuser

What is the meaning of those parameters?

  • repository: this is the activating Node repository (could be website, dam, …)
  • recursive: true | false, it tell the activation command if a recursive publishing has been asked by the requestor
  • path: this is the activating Node path (something like /demo-project/my-page)
  • modifiedOnly: true | false, it tells something about the status of the node on public instance. It is a brand new node or an existing node just modified?
  • uuid: this is the activating Node uuid, like “babb5315-f417-4083-9cf1-714bb304742f”
  • comment (optional): this is the requestor comment
  • publicationDate (optional): this is the scheduled date (2015-05-07T23:54:00 as a String representation
  • version (optional): this is the Node version number (1.1, 1.2..)
  • requestor: this is the username of the user that initiated the workflow

NB: these parameters refer to activation command only. Deactivation command is similar but with some differences..

Why 3 parameters for detecting a Node?

Interesting question.. normally, you can identify a JCR Node using only 2 parameters: repository + identifier or repository + path. Usually, the first pair is used (repo + id), but in Magnolia CMS a Node path, expecially if on website repository, is also a content URL: since the Node position (page URL) is available as a Context parameter, you don’t have to access the database to perform path-based actions.

In parameter list, 2 of them are special: comment and publicationDate. They are filled by the requestor on page activation dialog window:

workflow-07

The first one is only something that “enrich” the publication workflow. But the second one is read by activation workflow to understand if activation needs to be scheduled in the future: in this scenario, Magnolia reads a editor-generated content to act differently.

Perfect! That’s exactly what I need! Ask editors parameters is something we learned since the first Java HelloWorld, so.. I feel at home!
But.. how to do this?

Let us assume this scenario: I want to create a notification system that sends an email to users subscribed to website page updates. So, when a new page is activated on public instance, I need to intercept the command and send an email. But.. what happen if an editor updates the same page more than once a day? Subscribed users will be notified for any update. No good. I would like that any editor could say: “Hey, don’t alert subscribed users, this updates is only a typo-fix publication!”. In this way, intercepting command will check for the presence of a well-known parameter and in that case, it will skip the syndication.

Add a dialog field
The first step is to add a new field in pages activation dialog. This can be done as adding a standard field in a component dialog.
But.. where is the dialog? Let’s start from the origin. When editor clicks on “publish” button in the Magnolia sidebar or in context menu, a “pages” action is executed.

Pages activate action configuration
Pages activate action configuration

That action is overwritten by workflow module when installs, so that action is actually this one (the “schedulePublicationAction”):

Workflow activate action
Workflow activate action

The “schedulePublicationAction” uses a standard dialog:

Standard workflow activation dialog
Standard workflow activation dialog

Now, we can add a new custom field here: since a TextField and a DateField are already there, our choice is a CheckboxField:

A personalized dialog for workflow activation action
A personalized dialog for workflow activation action

And that’s it. Now, if you try to activate a page, you will see something like this:

A personalized dialog for workflow activation action (editor view)
A personalized dialog for workflow activation action (editor view)

Awesome. But if you try to log again what happen when workflow is launched, you won’t see that parameter: it has only been added to a dialog, without a server-side part that handle its storage. You don’t trust me? See what is saved in Tasks repository:

A standard Task data set
A standard Task data set

Now, the tricky side of the story begins.

Since we are dealing with a standard Magnolia Content App and we are inside a Action (invoked by our dialog), we need to instruct that action about the new “alert” parameter:

In this way, the action knows the type of the new param
In this way, the action knows the type of the new param

Now, we need to store that value in Task bag. We need to override a ParameterResolver class, and.. honestly, I don’t like this step, since Magnolia does not allow an easy way to do that. Anyway, create your class and bind it here:

How to add a custom Parameter Resolver
How to add a custom Parameter Resolver

Now, before reading the code, a little comment. The right thing would have been to add that parameter to HumanTask class. But that class is quite nested, inner.. there is another injection point: Magnolia stores its parameter in a “content” node inside the Task. And that node is stored as a Map (String – Object), so.. we can store whatever we want inside!
Here the code (partially hidden, since it is part of EE source code):

Now, let’s have a look at Tasks repo:

Our new parameter is now stored in Task data
Our new parameter is now stored in Task data

And this is the log (4th line):

2015-05-13 22:35:27,813 INFO  info.magnolia.commands.MgnlCommand                : Logging command parameters: 
2015-05-13 22:35:27,813 INFO  info.magnolia.commands.MgnlCommand                : param repository: website
2015-05-13 22:35:27,814 INFO  info.magnolia.commands.MgnlCommand                : param recursive: false
2015-05-13 22:35:27,814 INFO  info.magnolia.commands.MgnlCommand                : param alert: true
2015-05-13 22:35:27,814 INFO  info.magnolia.commands.MgnlCommand                : param path: /demo-features
2015-05-13 22:35:27,814 INFO  info.magnolia.commands.MgnlCommand                : param modifiedOnly: false
2015-05-13 22:35:27,814 INFO  info.magnolia.commands.MgnlCommand                : param uuid: babb5315-f417-4083-9cf1-714bb304742f
2015-05-13 22:35:27,814 INFO  info.magnolia.commands.MgnlCommand                : param comment: This is a comment (with alert!)
2015-05-13 22:35:27,814 INFO  info.magnolia.commands.MgnlCommand                : param version: 1.9
2015-05-13 22:35:27,814 INFO  info.magnolia.commands.MgnlCommand                : param requestor: superuser

Yeah! Finish! Uhm.. not completely.. one last clean part, let’s put that parameter available to publishers in their MessageView:

Expose a new parameter in publishers  MessageView
Expose a new parameter in publishers MessageView

Please have a look at how the parameter name is changed: since we decided to use the “content” storage bag of a Task, now our “alert” param is inside a content node called “content”.. this leads to a render name of “content.alert”. And here is the final result:

A custom parameter in Publishers MessageView
A custom parameter in Publishers MessageView

And.. done!
Few considerations:

  1. This is a hack. It is not intended to be a “standard” way to approach a customization. But for sure, it will save you (much) time.
  2. Magnolia does not expose a comfortable hook to inject logics, I needed to copy part of the code of a superclass!
  3. The overall changes are quite heavy to add a simple checkbox in a dialog. I hope that in future this can be facilitated.

Latest articles

Matteo Pelucco Written by:

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *


5 − one =