Last two months Liferay Connected Service (LCS) team spent testing system for upcomming changes related to subscription management. It should allow enterprise customers more flexible license management and elastic subscription mode.

I guess now I have enough time to put some news for all of you who follow LCS progress.

in the next release of LCS system we will stop support and development for all 6.1.x platforms

browseable page metric history have been available since April 2016

notifications/alerts improvements were deployed early in May 2016

LCS system is tested and ready for incoming family of 7.0 portal based solutions

I hope you will find time to explore and evaluate the leatest LCS features soon.

Recently LCS team had really hard time with writing integration tests for service builder generated classes. Arquillian test patterns written for core portal plugin simply didn't work for our case and mocking service layer was pointles. As time passed by and code base grow we simply got angry and decided to stop with all development untill we are not able to run test as any other decent software engineer in the world.

Here I'll write exact steps we did in our EE PLUGINS SDK 6.2 and Liferay Portal EE 6.2 SP10 to make Arquillian tests work for us. Of course without help from awesome core engineering team which filled some gaps in the SDK infrastructure even this wouldn't be possible.

Step 1 - unzip new tomcat

I do this from my portal's source home directory:

ant -f build-dist.xml unzip-tomcat

Step 2 - manager webapp

Once you have fresh, clean tomcat in bundles directory (or whatever directory you use), you have to make sure there is manager webapp present. Arquillian uses manager application to deploy your plugin so it is required. I usually go to tomcat download site, download archive, and extract manager app from it.

Step 3 - modifiy setenv.sh

Go to TOMCAT_HOME/bin directory and add this line after original CATALINA_OPTS definition:

Step 5 - prepare database and compile portal

Dedicate new database instance (ieg. lportalee62x_test) for your integration tests and set it in portal-ext.properties and run from portal source home directory:

ant all

After ant task is completed you have portal environment ready for tests. You may wonder why I do all this like idiot? Well, because each time some plugin or some setting either destroys attempt of testing either wastes couple hours of my time until I find the problem. So each time I run tests in completely fresh environment.

Step 6 - Initalize portal infrastructure

Start portal once to initalize DB, download market-place plugin etc. Once you are surre everything is there deploy portlet plugin you want to test (you may need to deploy other dependencies also). After your plugin initalizes its own DB space, undeploy it. Again, you will question yourself if everything is OK with me - yes, don't worry, you will avoid million unexplainable issues if you follow this steps.

Optionally, you can download lcs-portlet from lcs.liferay.com and deploy to your test portal. If correctly connected to LCS system, it would stream service statistics to LCS where you would be able to analyse it. More about it read in Marko's blog on how to monitor user expirence.

Hi all, recently our team finished the first real-world OAuth case, so I'll share with you code and knowledge you would probably need if you choose Liferay OAuth Plugin.

Architecture

Our case requires two kind of portals:

Liferay Service Portal - further in text LSP - EE 6.1.x portal - this is central point where resources and services are being served from. Here we have resource administrator users, and end users (mostly "consumer" portal administrators). Here OAuth Portlet was deployed.

Liferay Client Portal - further in text LCP - any EE/CE 6.1.x/6.2.x portal - this is portal instance that consumes particular resource (imagine it like your portal instance accessing Marketplace to fetch an portlet, but with more resources and services). Here OAuth Client Portlet was deployed

LCP instances are consumers, consuming resources and services provided by LSP. Consuming is done with simple portlet (we refer to it as OAuth Client Portlet) whose threads wait in the background and from time to time does some work with LSP. Each request for service or resource must be authorized, but without human interference.

Note that I use term OAuth Portlet which is portlet plugin that makes particular portal instance OAuth friendly, and term OAuth Client Portlet which is portlet plugin that performs authorized requests using OAuth principles.

Authorization problem

LCP instances need way to authenticate and authorize its actions at LSP. It could be done using username/password with each request, but no one administrator wants his username and password in properties or database (even encrypted).

As we already have OAuth Portlet which setups an Liferay Portal to be OAuth friendly, we decided to go further with OAuth.

We had deployed OAuth Portlet at LSP portal and registered our OAuth Client Portlet as OAuth Application to obtain CONSUMER KEY and CONSUMER SECRET. With consumer credentials we were ready to implement clent side. Further in text you can read how we did it, and what are limitations related to current OAuth Portlet implementation (don't panic we are working on improvements).

OAuth Client Portlet Implementation

There are so many code examples at Internet on how to use OAuth. Here I'll describe how we did it in portlet and what was different comparing to some other cases (for example if you build mobile application).

OAuth Client Library

We choose Scribe as OAuth library of our choice. Simply because it is available in portal and you can easily include it in your plugin by refering it from liferay-plugin-package.properties:

In latest version of Scribe you will need to implement getAuthorizeToken method also. It is starting step for client accessing OAuth platform the first time, and here it is implemented in OAuthUtil class. By implementing this we provide Scribe with informations about OAuth platform we are accessing. It is very important to say that OAuth Portlet protocol URLs are defined in portal.properties and liferay-hook.xml. Defaults are

and in our example we use them as they are. At an LSP you are connecting these might be modified, so in your case consult with provider portal administrator if these properties were modified. We use portlet.properties to set all OAuth related constants:

Please take moment and stop at method String getAuthorizeURL(String callbackURL, Token requestToken). This method is very related to CALLBACK URI parameter you are obligatory to provide during registration of an OAuth Application. CALLBACK URI is uri where user will be redirected by LSP once user is authenticated and access authorized. For an mobile application, or 3rd party web application with known domain we can use CALLBACK URI as my-android-app://main-activity or http://www.consumersite.com/registered. In our example, consumer portal domain in build time is unknown, or LCP portal could be behind firewall and admin referrs to it via IP or internal alias when performing OAuth authorization. To support case, we need to override CALLBACK URI and hopefully we can do it with additional oauth_callback parameter as shown in example. Remeber this if you plan your own OAuth case.

Authentication

If accessing OAuth platform first time, portlet needs UI to start OAuth cycle which would result in ACCESS TOKEN and ACCESS SECRET. Those are credentials we will store for further usage. Portlet will use them each time we are accessing LSP (in combination with CONSUMER KEY and CONSUMER SECRET). Our front end code works this way:

if there are ACCESS TOKEN and ACCESS SECRET show threads activity status

After Authorize button is clicked, user is taken to OAuth Provider where he is authenticated and asked to authorize Portlet to access resources and services on his behalf.

Click to authorize

On success, OAuth platform redirects user back to CALLBACK URL (where you want your portlet to continue with process). In our case it is portlet action setupOAuth where we will extract and persist access token and access secret.

Liferay OAuth Portlet Limitations

Please DON'T consider this case as ultimate one. This can be pattern for most projects where client is built for known Liferay Portal Platform (let's say Liferay.com, or any other amoung our respected customers). If you build Portlet Plugin or Mobile Application for "Any Liferay Portal" OAuth won't work for you. It won't work for you since you will need to feed your code with CONSUMER KEY and CONSUMER SECRET which in "Any Liferay Portal" case will be known after "Any Liferay Portal" was installed and OAuth Plugin is deployed. For mobile applications downloaded from Play, App Store or Marketplace it will be very hard to fetch these in easy and secure way.

Please, prior considering using OAuth Portlet take note that current OAuth Portlet implementation relys to standard portal permissions. That means if user Europa authorizes portlet Atlass to access LSP portal resources, portlet Atlass will be able to do what ever Europa can do. In next version of OAuth Portlet, we will engage Access Control API where consuming applications would be forced to declare which resources will access, and OAuth Portlet would check it.

This is The End (of blog article)

At the end, I hope it will be very easy to get your OAuth clients to life. Also I expect lot of critics mostly because of limitations, but hey, we are working to improve it.

Hi all, I'll share with you our latest progress made with supporting OAuth authorized requests. I'll make example with android application since I'm familiar with it (enough to display button).

OAuth server support comes as OAuth 1.0a spec based portlet plugin with application registration UI, user authorization approval and secure filter that checks validity of oauth credentials (thank you Tomas for the filter, and Ivica for all hours we spent together). OAuth is very pratical since it moves authentication actions to platform side (Liferay Portal), and application doesn't need handle security issues regarding credentials storing. If you are application developer, and want your application to access Liferay portal resources this could be a way to do it:

1. Go to OAuth admin

2. Register application

3. Get yours consumer key and secret

Now... You should take an OAuth api (scribe or signpost) and make your consumer application. My application is simple android application whic would do nothing awesome, but will make authorized document library access:

- make oauth request token and bring user to Liferay portal application authorization page. If user is not signed in, he/she would be asked to do it.

- Once user is signed in authorization page will be shown. After user confirms he/she grants access to her/his liferay resources Liferay redirects user to defined redirect URL (not clear from screenshots, but as a redirect I'm using my-application://www.liferay.com/something so that android browser knows where to pass redirect).

- user acces token and token secret are being stord in application properties, an I'm able to query portal (I'll grab some folders and display it):

Hi all, I want to share with you something that is pretty cool for me and I found it super useful. It is shared type of Liferay SDK plugin we use to generate jar entry that can be referred by your other plugins as its library entry.

To show how shared plugin is useful lets just mention that liferay-plugin-package.properties already supports some widely used dependency declarations:

dependency to Liferay Portal jars can be declared using

portal-dependency-jars - during compile phase it will use portal-dependency.jar but it will be excluded from created archive

portal-dependency-tlds

dependency to other plugins auto-generated *-service.jar entry you declare using:

required-deployment-contexts - during compile phase it will fetch required-deployment-context-service.jar and include it in created archive

Why shared plugin?

Once in your life, your system design will assume more than one interdependent plugin (and even simple Liferay integration cases can't avoid it). Your team will end up with common code used in each plugin such are various utilities and own APIs. Good starting point for refactoring it is creation of shared type of plugin, extracting common code to it and declaring dependency to it in all other plugins code was used. I'll demonstrate it using always funny batman plugin invented by my coleague Igor:

Once you're inside your SDK go to shared folder and create structure for your new plugin:

In this article I'll try to list workflow and service context content for some common asset types. You can use this information later when you build your notification templates or refer to it. When accessing variables I marked with "!" (like taskComments or transitionName) make sure they are present since its presence depends on workflow activity.

You will notice that I separated serviceContext since its keys depend on asset type.

In one of my previous blogs I wrote about how to setup email settings and configure Web Content notifications triggered by workflow.

Liferay portal 6.1 relays to external workflow engine Kaleo which also has ability to send notifications. As our intention is to centralize workflow related code in Kaleo and users workflow definitions, eventually we will remove legacy workflow notifications (such those in web content managment). So to prepare you for things that are comming check this blog.

Kaleo

To constrain your business process with some rules, you need:

rules

language to describe those rules to mchine

workflow engine

assets and resources aware of workflow engine

people who want to play by the rules

Kaleo and Liferay give us 1*, 2, 3, 4*. Once you have idea what are yours company rules, you will ask somebody to write definition in an xml like language. Than you will run those rules in portal and apply it to you asset and resources.

1* kaleos default rules are very generic and may be good as starting point. Depending to your company business you will probably need your own rules writen as definition.

4* by default those assets are workflow aware: Blogs Entries, Web Content, Comments, Message Boards Messages, Wiki Pages and Page Revisions (when you do staging). Your and any other assets you want in game must implement workflow interfaces.

What is interesting you will probably want some actions performed to asset to trigger messages to get users attention. You want to notify user there is job to do, he done great job or there is awful escalation that needs immediate intervention. As part of workflow definition you will be able to create some actions eather real scripted actions or notifications. Notifications can be emails, instant messages or private messages. In the rest of blog I will focus on email notifications.

Kaleo email notifications

As kind of action we form notifications as part of process state or tasks. Triggering of notification is done in a three ways:

on assignment - when task is assigned to user

on entry - when asset enters some state or is ready for an task within state

on exit - when asset leaves the state or all job required by the task is done by particular user

At the end we must choose do we need some simple messages in our email or we want to build more specific messages aware of business and workflow context. Kaleo definitions will allow you to write messages as plain text but in most cases that wouldn't be enough. also for advanced users there is possibility to do that in freemarker or velocity.

Write your own notifications

For example I'll existing default single-approver-definition.xml notification defined for review task. New notification will use new email subject and will include some data related to asset that is being workflowed. My new notification related to review task is following:

<notification>

<name>Review Notification</name>

<description>New Submission Is Ready For Review</description>

<template>

<![CDATA[

<#assign comments = taskComments!"">

<!-- email body -->

<p>

Please review the ${entryType} waiting for you in your workflow tasks.

<#if comments != "" >

<br />Assignment comment says: <strong>${comments}</strong>

</#if>

</p>

<!-- signature -->

<p>Sincerely,<br /><strong>Liferay Portal Workflow</strong></p>

]]>

</template>

<template-language>freemarker</template-language>

<notification-type>email</notification-type>

<execution-type>onAssignment</execution-type>

</notification>

Now, lets go step by step:

node name - it will just define notification identification name

node description - it serves as description, but kaleo will populate an email subject field with its value so be as more creative when you setting this value

template - there are two things to note. First it is assignment of variable comment:

<#assign comments = taskComments!"">

expression taskComments!"" will take value from freemarker context variable taskComments and if it is null en ampty string will be returned. We have to do that because when initaly enters review task, it is done by engine so there won't be available taskComments. In moment when manager assigns task to user he will be prompted to set comment so we will be able to display comment inside email message.

Second thing is use of freemarker context variable entryType. Expression ${entryType} will be evaluated as asset type like Web Content, Comment or Wiki.

My goal here will be to explain influence of pop.server.subdomain setting to setup external email server and enable Liferay 6.1 Message Boards to process email replies and post them to correct MessageBoards thread. For me, this feature is extremly handy because I can post to MessageBoards from my smart phone without need to sign in to portal.

pop.server.subdomain=events will cause that liferay builds Message Boards email notifications to have reply-to attribute like mb_message.NNNNN.NNNNN@events.mydomain.com. If your email server is not setup to handle emails to events.mydomain.com domain, replys will be rejected from destination email server with an error: The error that the other server returned was: 550 550 5.1.1 <mb_message.12204.12405@events.mydomain.com>: Recipient address rejected: User unknown in virtual mailbox table (state 14). If you set pop.server.subdomain property to empty string, portal would turnoff this feature. In that case reply-to email attribute would be set to email address set in your portal preferencies settings.

STEP 4 - Setup Email Subdomains

To make use of subdomains funcionality we will configure our email server to use virtual email inbox. That is needed bacause Liferay Portal will compose email notification messages such way that you will be replying your emails to generic unexisting users that will be later decoded to correct message boards threads. To achive that our users will be virtual and configured with regular expressions.

Use your domain admin tools to define mx record for mydomain.com and its aliases. In my case I have:

Hi all! As workflow for Liferay 6.1 sligtly changed from workflow in Liferay 6, I'll spent some time to provide ways to setup it and use it. My idea here is describe how fast you can setup and apply Liferay workflow to your business. I'll to write series of blogs with cases describing how to apply workflow in publishing, banking or city government.

Before I start hassle with problems you are realy interested in I'll describe how to configure and test basic modules neccessary to achieve the final one. Yes it is technical stuff, but we must "build crane to build a crane".

Setup Email Notification and test it with Web Content Management

For purposes of this demonstration we will need:

two users + administrator

email accounts for both users (example is done with gmail accounts - I'm using my private and companys email)

existing built in Liferay site,

installed kaleo web plugin

STEP 1 - Create users

User1: Clark Kent that will be able to add web Content scoped to Liferay site

User2: Loise Lane that will be given Site Content Reviewer Role

STEP 2 - setup email server to enable notifications

I will use gmail to demonstrate email services setup as most of us have gmail account.

Go to Control Panel

In left menu go to Server section and click Server Administration

Choose Mail tab

Incoming POP Server set to pop.gmail.com and port to 995

Check Use Secure Network Connection

Username set to your email address (eg. clark.kent@gmail.com)

Outgoing SMTP Server set to smtp.gmail.com and port to 465

Check Use Secure Network Connection

Username set to your email address (eg. clark.kent@gmail.com)

When setting Outgoing SMTP Server be aware that some ISPs will prevent you to use your custom email server as outgoing server (even via secure connection). So you will need to set this attributes according ISP rules.

portal-ext.properties that have to be set are:

pop.server.notifications.enabled=true

pop.server.notifications.interval=1

STEP 3 - Kaleo workflow

Now we will activate workflow for Web Content Management so before make sure you have deployed Kaleo Web plugin. (developers: go to your liferay-plugins repository, position to webs/kaleo-web and type ant deploy; other: download plugin and copy it to liferays deploy folder)

Go to Control Panel

In left menu go to Portal section and click Workflow

Choose Definitions tab

Make sure you have listed Single Approver workflow model and if not add it

Activate Single Approver workflow

In Control Panels left menu make sure Liferay site is in the scope. In Liferay section click Workflow Configuration

For Web Content from drop down at the right choose Single Approver (Version 1) and click Save

STEP 4 - setup Web Content Notifications

It is good to know that WCM notifications are optional and in current 6.1 relese. If you enable it you will receive both Kaleo and WCM notifications.

If you have no workflow enabled for Web Content Management, tabs in Configuration screen related to workflow notifications wont be available.

Now, when Kaleo is ON, we will setup user notifications for Review Request for reviewer and Article Granted notification for author.

Go to Control Panel

Make sure that in left menu scoped site is Liferay

In Liferays site section click Web Content

In the right side of opened page click Options icon and choose Configuration to open Web Content Configuration pop-up

Email From Tab - fill in Name (Workflow Liferay) and Email address (workflow@liferay.com) that will show up as notification email sender. Click Save.

Useful links

Have you ever faced github pull request bug which manifests in a way that list of peopole you want to send pull request to doesn't contain that person?

I did, in moment when pull request should be sent ASAP. So same moment I got a workaround link but my happyness went away from my windows user smiled face when I noticed that .sh and .py endings. OK, house is burning, what is next step? Install pyton for windows? Install cygwin? Instal vmware and call friend to give you some ready linux image....

No, I do it better way also known as harder way. When you are in github and you selected Pull request you will be able to select person you want to send pull request to from drop down list. If person is not in a list do following:

make sure you are browsing github from latest version of Google Chrome

acquire target person github username (lets say ivicacardic)

select branch you want to send pull request for, click Pull Request, click Change Commits to bring up form with drop down for target user selection

right click to dropdown, choose Inspect element what will bring up chrome developer tools window

expand html select element and position to any of option nodes eg. <option value="igorbeslic/liferay-portal">igorbeslic/lifera...</option>

right click to value attribute and chose Edit Attribute

now change value to starts with github username of person you are sending pull request like value="ivicacardic/liferay-portal"

go back to page select igor beslic from drop down and than click Update Commit Range