This article is also available on Liferay Blog

IPC - Inter Portlet Communication

Inter Portlet Communication (IPC) is a way of exchange the data between portlets. In Liferay there are different ways we can achieve this. One of them is the client-side IPC that is supported by LIMS. In other words, you may e.g. open a conversation or read user presence from your own portlet. There is only one limitation. Since the communication is client-side LIMS needs to be on the page together with your portlet.

Enable IPC in Admin Area panel

By default the IPC is turned off. To turn it on go to the Admin Area panel (you need to be an omni admin) and enable it.

Sample IPC for LIMS Messenger

Before we start the tutorial take a look at the Sample IPC for LIMS Messenger project available on Github: https://github.com/marcelmika/sample-lims-ipc. Especially the main.js file that contains the main client-side IPC logic. The WAR file is available here. If you deploy the sample portlet and drag it to the page you should see something similar to this:

You also need to refresh the page before you start using the portlet because the lims:ready event may already be called.

List of Events

  Event ID Since Type Input Output Errors
Portlet Ready lims:ready v1.2 subscribe      
Create Conversation lims:createConversation v1.2 publish [userId] {conversationId} 4000 - wrong input
4002 - conversation with yourself
5000 - server error
5001 - IPC disabled
Open Conversation lims:openConversation v1.3 publish {conversationId} {conversationId} 4000 - wrong input
4003 - not allowed
4004 - conversation not found
5000 - server error
5001 - IPC disabled
Send Message lims:sendMessage v1.3 publish {conversationId,message} {conversationId,message} 4000 - wrong input
4003 - not allowed
4004 - conversation not found
5000 - server error
5001 - IPC disabled
Read Presence lims:readPresence v1.2 publish [userId] [{userId,presence}] 4000 - wrong input
4001 - more than 100 presences
5000 - server error
5001 - IPC disabled
Presence Updated lims:presenceUpdated v1.3 subscribe   [{userId,presence}]  
Read Last Conversations lims:readLastConversations v1.3 publish   composed response 5000 - server error
5001 - IPC disabled
Unread Messages Count Updated lims:unreadMessagesCountUpdated v1.3 subscribe   {count}  

Portlet Ready since v1.2

As we mentioned before, the communication with LIMS can be established only if the portlet is rendered on the page and ready to go. LIMS will fire the lims:ready event when it's ready to listen for the IPC calls. Thus you should always wrap your IPC communication to the following code:

Liferay.on('lims:ready', function () {
    // Call IPC
});

As you can see all the request are going to be called on the Liferay global object. Thanks to this approach all portlets on the page can listen to events. Also take a look at the lims: prefix which is used to avoid collisions with other portlets using IPC as well.

Create Conversation since v1.2

If you want to create a conversation, call the lims:createConversation event.

// Create IPC request
Liferay.fire('lims:createConversation', {

        // Input data is an array of users ids with whom you want to create the conversation.
        // If you pass one id a Single User Chat (SUC) conversation will be created. If you
        // you pass more than one id a Multi User Chat (MUC) conversation will be created.
        data: [10434, 10567],

        // Called on request success
        success: function (response) {
            // Your code called on success
        },

        // Called on request failure
        failure: function (code, reason) {
            // You may want to show an error message or do something else.
            // Code contains error code and reason contains human readable reason of the failure
        }
});

Note that if you pass just your own id (e.g. 10434) LIMS will detect it and doesn't let you create a SUC with yourself. However, if you pass two ids where one is your own (e.g. 10434, 10567) a SUC with user 10567 will be created. Similarly, if you pass three ids (e.g. 10434, 10567 and 10789) a MUC with user 10567 and 10789 will be created. Note that you don't need to pass your user id if you want to create MUC conversation. LIMS always adds creators of the conversation to the participant list.

Success

If the conversation is successfully created a response object is passed as a parameter of the success function.

response = {
    conversationId: "jane.austen_woody.allen"
}
Failure

If anything fails, the failure method is called. This method will provide you with the error code and the human readable reason of failure. Possible failures are:

code: 4000 - you provided wrong input
code: 4002 - you wanted to create SUC conversation with yourself
code: 5000 - server returned error, take a look on the reason message for further info
code: 5001 - IPC is not enabled. You can enable it via Admin Area panel or via portlet.properties file

Open Conversation since v1.3

If you want to open an existing conversation, call the lims:openConversation event.

// Create IPC request
Liferay.fire('lims:openConversation', {

    // Pass the conversation ID
    data: {
        conversationId: conversationId
    },

    // Called on request success
    success: function (response) {
        // Your code called on success
    },

    // Called on request failure
    failure: function (code, reason) {
        // You may want to show an error message or do something else.
        // Code contains error code and reason contains human readable reason of the failure
    }
});

By calling this event, LIMS will open the particular conversation panel and sets the focus to the message text field. Thanks to that the user can start typing immediately (this works for non-mobile devices only).

Success

If the conversation is successfully opened a response object is passed as a parameter of the success function.

response = {
    conversationId: "jane.austen_woody.allen"
}
Failure

If anything fails, the failure method is called. This method will provide you with the error code and the human readable reason of failure. Possible failures are:

code: 4000 - you provided wrong input
code: 4003 - you are not allowed to open this conversation (i.e. user is not a participant in the conversation)
code: 4004 - conversation with such conversationId was not found
code: 5000 - server returned error, take a look on the reason message for further info
code: 5001 - IPC is not enabled. You can enable it via Admin Area panel or via portlet.properties file

Send Message since v1.3

If you want to send a message to an existing conversation, call the lims:sendMessage event.

// Create IPC request
Liferay.fire('lims:openConversation', {

    // Pass the conversationId and message
    data: {
        conversationId: conversationId,
        message: message
    },

    // Called on request success
    success: function (response) {
        // Your code called on success
    },

    // Called on request failure
    failure: function (code, reason) {
        // You may want to show an error message or do something else.
        // Code contains error code and reason contains human readable reason of the failure
    }
});

By calling this event, LIMS will send a message to the particular conversation. Note that the conversation doesn't need to be opened but it needs to be already created. If you call this event the conversation will not be automatically created nor opened.

Success

If the message is successfully sent a response object is passed as a parameter of the success function.

response = {
    conversationId: "jane.austen_woody.allen",
    message: "Hello World!"
}
Failure

If anything fails, the failure method is called. This method will provide you with the error code and the human readable reason of failure. Possible failures are:

code: 4000 - you provided wrong input
code: 4003 - you are not allowed to send a message to the conversation (i.e. user is not a participant in the conversation)
code: 4004 - conversation with such conversationId was not found
code: 5000 - server returned error, take a look on the reason message for further info
code: 5001 - IPC is not enabled. You can enable it via Admin Area panel or via portlet.properties file

Read Presence since v1.2

If you want to read user presence, call the lims:readPresence event.

// Create IPC request
Liferay.fire('lims:readPresence', {

    // Input data is an array of users ids of whom you want to read the presence.
    data: [10434, 10567],

    // Called on request success
    success: function (response) {
        // Your code on success. The response object contains an array of objects with user id and presence.
    },

    // Called on request failure
    failure: function (code, reason) {
        // You may want to show an error message or do something else.
        // Code contains error code and reason contains human readable reason of the failure
    }
});

Note that you can read up to 100 user presences at once. If you want to read more you will need to call the event multiple times.

Success

If the presences are successfully read a response object is passed as a parameter of the success function.

response = [{
        userId: 10434,
        // Possible values are:
        // ACTIVE - user is online (green)
        // AWAY - user is busy (yellow)
        // DND - user is unavailable (red)
        // OFFLINE - user is offline or turned off the chat (gray)
        // UNRECOGNIZED - such user doesn't exist or he/she hasn't logged into the portal yet
        presence: "ACTIVE"
    }, {
        userId: 10567,
        presence: "DND"
}]
Failure

If anything fails, the failure method is called. This method will provide you with the error code and the human readable reason of failure. Possible failures are:

code: 4000 - you provided wrong input
code: 4001 - you wanted to read more than 100 presences
code: 5000 - server returned error, take a look on the reason message for further info
code: 5001 - IPC is not enabled. You can enable it via Admin Area panel or via portlet.properties file

Presence Updated since v1.3

If you want to be notified about presence changes of the users in the portal subscribe to the lims:presenceUpdated event.

// Subscribe to the IPC event
Liferay.on('lims:presenceUpdated', function (event) {

    // The list of users and their updated presences is located
    // in the event.users property
    var users = event.users;
});

LIMS calls the function you provide as a second parameter when any of the users changes their presence. Thanks to that you don't need to call the lims:readPresence event periodically to read the current presence.

response = [{
        userId: 10434,
        // Possible values are:
        // ACTIVE - user is online (green)
        // AWAY - user is busy (yellow)
        // DND - user is unavailable (red)
        // OFFLINE - user is offline or turned off the chat (gray)
        // UNRECOGNIZED - such user doesn't exist or he/she hasn't logged into the portal yet
        presence: "ACTIVE"
    }, {
        userId: 10567,
        presence: "DND"
}]

Read Last Conversations since v1.3

If you want to read last conversations of the user, call the lims:readLastConversations event.

// Create IPC request
Liferay.fire('lims:readLastConversations', {

    // Called on request success
    success: function (response) {
        // Your code on success. The response object contains an array of conversations.
    },

    // Called on request failure
    failure: function (code, reason) {
        // You may want to show an error message or do something else.
        // Code contains error code and reason contains human readable reason of the failure
    }
});

The event will provide you with an array of last conversations. The number of conversations can be changed via the conversation.list.max.messages property in portlet-ext.properties file.

Success

If the conversations are successfully read a response object is passed as a parameter of the success function.

response = [{
    conversationId: 10434,
    title: "Jane Austen",
    unreadMessagesCount: 2,

    // SINGLE_USER - single user chat conversation (user to user)
    // MULTI_USER - multi user chat conversation (group chat)
    conversationType: 'SINGLE_USER',

    // Last message in the conversation
    lastMessage: {
        // REGULAR - default message type
        // ADDED - user was added to the MULTI_USER conversation
        // LEFT - user left the MULTI_USER conversation
        type: "REGULAR",
        body: "Hello World!"
    },

    // List of participants
    participants: [{
        userId: 10434,
        screenName: "woody.allen",
        fullName: "Woody Allen"
    }, {
        userId: 10435,
        screenName: "jane.austen",
        fullName: "Jane Austen"
    }]
}];
Failure

If anything fails, the failure method is called. This method will provide you with the error code and the human readable reason of failure. Possible failures are:

code: 5000 - server returned error, take a look on the reason message for further info
code: 5001 - IPC is not enabled. You can enable it via Admin Area panel or via portlet.properties file

Unread Messages Count Updated since v1.3

If you want to be notified about the total number of unread messages changes subscribe to the lims:unreadMessagesCountUpdated event.

// Subscribe to the IPC event
Liferay.on('lims:unreadMessagesCountUpdated', function (event) {
    // The number of currently unread messages is located in the event.count variable
    var count = event.count;
});

LIMS calls the function you provide as a second parameter when the total number of unread messages changes.

response = {
    count: 10
}