Monday, February 24, 2014

Recycle Bin for your Custom Portlet in Liferay 6.2

Now It's almost around 4 months since Liferay 6.2 is released with complete makeover and including many power packs like Responsive Design using Bootstrap, Mobile friendly support, WCM improvements, ADT(Application Display Template), Recycle Bin & others. For more details visit What's new in Liferay 6.2.

Among all of these today I would like to talk about Recycle Bin in Liferay 6.2 & how you can plug it with your Custom portlet.

Recycle Bin

Think of a situation where you are working on Production site and while deleting multiple content you've also deleted a content which is being used on a Site Home page !! Now you don't have way to quickly revert your delete action and restore deleted content.

Now going forward from Liferay 6.2, No need to worry about such circumstances as you'll have a option to restore accidentally deleted content using Recycle Bin feature. It's been added for all important Liferay asset types.

  • Blogs
  • Bookmarks
  • Documents and Media
  • Message Boards (and attachments)
  • Web Content
  • Wiki (and attachments)

But what if you want Recycle Bin for your Custom Portlet which is as important as other Liferay assets. Well Good News is, Liferay has made this in generalize way so that it can be used with custom portlet as well.

Recycle Bin can be configured from Site Configuration. You can turn on/off Recycle Bin and also change the Max Age(in number of days) for content being kept in Recycle Bin for specific Site.
Recycle Bin Configuration
Recycle Bin Configuration

And we can get all the content that is moved to Recycle Bin from Site Administration - Content - Recycle Bin.
Recycle Bin in Site Administration
Recycle Bin in Site Administration

So far we've seen how it will be useful and how to configure it to be able to use it with Liferay OOTB assets. But what if you want this feature for your custom asset(portlet) ?

Well today I'm going to share the steps that I've followed and be able to add Recycle Bin for a Custom Portlet.

Sample Recycle Bin Portlet

Here for reference I'm using a Simple Service Builder Portlet which does CRUD operation (add/update/delete records from Database). Here I am not going in deep on how to create Service Builder portlet.
Below is the service.xml for the same.
Add Event - Sample Recycle Bin
Add Event
View Events with Delete Action
View Events with Delete Action
Now we'll replace "Delete" with "Move to Recycle Bin" by plug Recycle Bin capabilities in this portlet.

Service.xml Changes

First we are going to make changes in service.xml

Enable Trash
We need to add "trash-enabled="true" in order to tell service builder that particular entity will be using Trash(Recycle Bin).
Build service after enabling trash for a entity. Service builder will auto generate some methods for entity model which will be later required.

Add Status Columns
Next we need to add columns required by Trash in order to maintain the logs of events occurred while moving assets from/to Trash.

Adding some finders in service.xml.

We also need to add TrashEntry reference.
Build service after this changes in service.xml

Trash Handler

Next we need to add trash-handler & asset-renderer-factory in liferay-portlet.xml. Here I've added com.opensourceforlife.portlet.samplerecyclebin.EventTrashHandler as a trash-handler & com.opensourceforlife.portlet.samplerecyclebin.EventAssetRendererFactory as asset-renderer-factory.

Create a class EventTrashHandler which extends BaseTrashHandler and override it's unimplemented methods. Complete class can be found here.
public class EventTrashHandler extends BaseTrashHandler
Create EventAssetRendererFactory extends BaseAssetRendererFactory and override it's unimplemented methods. Complete class can be found here.
public class EventAssetRendererFactory extends BaseAssetRendererFactory
We also need to create EventAssetRenderer which is being used by EventAssetRendererFactory.

Change Delete Action

Now we are going to replace "Delete" button to "Move to Recycle Bin" in actions. For this we'll need to change Delete action in jsp.
Here first we are passing Command be either 'delete'or 'move_to_trash'. So if Recycle Bin is enabled for a particular Site it will pass 'move_to_trash' else 'delete' as usual.
Next we've changed icon based on the command which will be available. As shown we've a attribute 'trash' which will be true if Recycle Bin is enabled for a site and respectively it will change UI for a particular event.

Deploy your portlet after these changes and you'll see "Move to Recycle Bin" option if Recycle Bin is enabled for your site.
Recycle Bin action for a Event
'Move to Recycle Bin' action for a Event
Upon clicking on 'Move to Recycle Bin' will not work as expected yet. As still we'll have to write a logic for moving event to Recycle Bin and option to restore it back.

Controller Changes

Let's changes deleteEvent in our controller so that based on command(delete or move_to_trash) we'll get in controller, we can perform respective actions.

For 'delete' command we'll perform normal delete action but for 'move_to_trash' we'll be executing EventLocalServiceUtil.moveEntryToTrash(userId, eventId). That we need to implement in and we'll see that in next steps.

Service Implementation Changes

Next we need to make changes in Event Service Implementation to leverage trash logic mainly for moving event to Trash and restoring it back from Trash. Here you'll need to take extra care if you are Indexing your data in lucene OR you've workflow enabled for your plugins portlet.

Here we will write a logic to move Event to Trash. This we'll call when user will click on 'Move to Recycle Bin' option from Event actions.

As name suggest, it will take care of restoring Event back from Trash to Event portlet.
When any move anything to Trash we can either Restore it or Permanently Delete it.
Recycle Bin Options
Recycle Bin Options
So we'll add a logic to remove entry from trash upon actually deleting a Event either directly from Event(when Recycle Bin is not enabled) or from Recycle Bin.
We'll need to change logic which is fetching List of events to not include events already moved to trash. It uses finder method that we've created earlier by adding finders in service.xml

Trash Handler Changes

Finally we'll make changes in EventTrashHandler that we've created earlier. And will change restoreTrashEntry & deleteTrashEntry methods. Here deleteTrashEntry will make actual call to Delete Event and restoreTrashEntry will call method 'restoreEntryFromTrash' from EventLocalServiceUtil that we've implemented in EventLocalServiceImpl.

That's it !! Just deploy your portlet and you are done with Recycle Bin plugged in for your Custom Portlet.
Hope this is helpful if you would like to have Recycle Bin for your plugins portlet.


Packaged War
Packaged war ready to use can be download here(sample-recycle-bin-portlet-*.war).

Source Code
Source code can be download OR fork Sample Recycle Bin Git Repository.

Feel free to provide your valuable feedback. You can reach out to me at admin{at} for any query/issue.

Best Regards,
Tejas Kanani
Senior Consultant @ CIGNEX Datamatics


  1. Hey Tejas,
    Great post and very detailed explanation.


  2. Thanks Nilang for your feedback :)

    Best Regards,