Note: there is now a new version of the messaging library available.
How it worksA portlet may have any number of inputs, and any number of outputs. It refers to these inputs and outputs using a local name in the portlet code (eg "person_name", "item_id"). Mappings of input/output names to global message boxes are defined externally to the portlet code - in the portlet preferences. A message box can hold only one message at a time: sending a new message to it will overwrite the old one. The messages never expire, as we cannot know whether the interested portlets no longer need them (actually, this implementation stores them in the session, so when the user session expires they will be cleaned up). Messages can be any sort of Object, though it may be wise to make them Serializable. A message input is mapped to a source message box, from which it reads its message. A message output always sends its message to a local (namespaced to its own portlet instance) message box of the same name, but it may also publish it to any number of additional global message boxes. LimitationsThe current implementation is limited to messaging between portlets in the same portlet webapp. This is because the messages are stored in the session, and portlets in different webapps have different sessions (according to spec). If this is not good enough, you can have a go at coding an alternative message storage system. Caching of portlet views is a problem: if you want the view of another portlet to update because an input message has changed, but the portlet is cached, the portal won't call its 'doView' and you have no way of forcing it to - that I know of, anyway(?). If you have enabled caching like this, I guess you'll have to add a 'refresh' link to the portlet so that the user can force a reload. However this isn't very user-friendly - another option which works is to disable view caching entirely by setting <expiration-cache>0</expiration-cache> for your portlets in portlet.xml. You will then need to ensure that your 'doView' is as lightweight as possible, as it will be called every time the page loads. This is not critical, but something to be aware of: Portlets only 'register' their mappings when they first load. The provided mapping configuration form (for use in a portlet's Edit mode) lists message boxes available as sources or targets, but it will only be able to 'see' those that have already been registered in the current session's MessageCentre. So if you haven't visited a portlet's page, its message boxes won't appear yet in another portlet's Edit mode. How to use it:
What's the Portlet ID?Lots of the functions and classes in this messaging system require a portlet ID. For the messages to get to the right places, we clearly need a unique ID for each portlet instance. However I haven't yet found a consistent way of retrieving a portlet instance id that works across different portals (if there is one, please tell me!). For example, I've seen a suggestion to add a portlet parameter containing an id in the portlet.xml - but that will end up being the same on all instances of that particular portlet, so you still can't distinguish between them. Some portals have their own functions for retrieving an instance id, but then you'd be locked to using that particular portal. I've settled for randomly generating portlet instance id's, and storing them in the local portlet's session. The function to do this is MessageHelper.getPortletID - you can use this, or implement your own solution; as long as each portlet instance has a unique ID, it can be any String. Alternative MessageCentre implementationsThe provided MessageCentreImpl stores the messages in the session, which means that it can't be used for communication between different portlet applications. However, the source is all here and if you want to implement a version of MessageCentre which stores the messages in a more globally accessible place, feel free - and I'd appreciate it if you want to send me a copy! You should be able to just make a class that implements MessageCentre, and modify MessageHelper.getMessageCentre to create an instance of your new class rather than MessageCentreImpl. |
![]() Messaging model: Message Centre keeps track of all the mappings between local message names and global message names, allowing dynamic reconfiguration of message 'routes' by the administrator or the portal user. ![]() Three messaging portlets ![]() Multiple instances of the same portlets: they have different mappings, defined in their parameters ![]() Dynamically mapped portlets: initial state ![]() Dynamically mapped portlets: all in Edit mode ![]() Dynamically mapped portlets: sent message from 1st to 2nd ![]() Dynamically mapped portlets: sent message from 2nd to 3rd ![]() Dynamically mapped portlets: changed 3rd to read from author_name ![]() Dynamically mapped portlets: 3rd now does search using author_name |