Assets remote publishing enhancement in Liferay portal

December 31, 2011 By Jonas Yuan

The portal provides remote staging and publishing capability through which the users can select subsets of pages and data, and transfer them to the live site of the remote portal instance. By this feature, we can export the selected data to the group of a remote portal instance or to another group in the same portal instance. The LAR export and import features are used for remote staging and publishing. These features are implemented in the PortletDataHandler API. As mentioned earlier, the intent of this API is to import and export application content to and from the portal in a database agnostic fashion for the portal core assets and custom assets.

The following diagram depicts an overview of remote staging and remote publishing. The Staging has a set of portal core assets, custom assets and groups of users. First, the portal will export related portal core assets and custom assets based on current user’s permission as a LAR zip file. And then the portal transfers this LAR zip file to the Live through tunnel-web http or https call. The Live will import related portal core assets and custom assets, as a LAR zip file, based on same user’s permission.

Abstracted from the Liferay development cookbook: Liferay Portal Systems Development (for liferay portal 6.1 or above version)

The staging and publishing are based on a page (a set of portlets).  Portlets that are check-marked will be Staged called staged portlets. This means that their data is published automatically whenever a page containing them is published.  The following is a list of staged portlets:

  • Blogs (*)
  • Bookmarks (*)
  • Calendar (*)
  • Documents and Media (*)
  • Documents and Media Display
  • Dynamic Data Mapping (*)
  • Knowledge Base (Admin) (*) - or any custom plugins which have LAR import and export configuration.
  • Message Boards (*)
  • OpenSocial Gadget Publisher
  • Page Comments
  • Page Ratings
  • Polls (*)
  • Polls Display
  • RSS
  • WSRP (*)
  • Web Content (*)
  • Web Content Display (*)
  • Wiki
  • Wiki Display 

These portlets which are disabled and check-marked are always automatically exported even if they aren’t on the page. These which are disabled and not check-marked are never automatically published. Note that Collaboration portlets, such as Blogs, Message Boards and Wiki are excluded from being Staged by default as their data typically originates in Live.

As you can see, the staging and publishing capabilities are portlet-based. If the staged portlet contains one asset, that asset will get published. For example, the portlet Web Content Display portlet can display web content a time.  If the staged portlet contain many assets, these assets will get published, filtered by the the range (like All, From Last Publish Date, Date Range, Last, etc).. But in real cases, it would be nice to have a feature to remotely publish assets directly in asset-level.

This article will address following remote publishing enhancement.

  • Add asset-level remote-publishing capability  (LPS-17235)
  • keep the category UID same AS IS when importing or remote publishing (LPS-22092)
  • Keep asset UID same AS IS when importing or remote publishing (LPS-17550)

Asset-level remote-publishing

Currently remote publishing feature is page-based. It would be nice to have a feature to remotely publish assets directly in asset-level. In fact, it would be cool that remote-publishing feature would support both layout-level and asset-level scheduling and publishing.

Use case

  • create a web content articles A1, A2 and A3 by user A and / or User B
  • schedule to publish A1 immediately by user A
  • chedule to publish A2 in 10 min by user A
  • schedule to publish A1 in 30 min by user B
  • schedule to publish A3 in 60 min by user B

This feature could be implemented by a plugin – called asset-remote-publish-portlet.

List screenshots of the plugin implementation

Assets creation, using web content as an example

Assets selection

Remote publishing settings - reuse default portal settings

Publish selected assets - from the Stage to the Live

As you can see, you can publish one or many assets one time based on selection.

Keeping the category UID same AS IS

This feature (keeping the category UID same AS IS when importing or remote publishing) should be available for vocabularies, categories and tags.

Use case:

  • There are two environments - the stage and the remote Live.
  • In the stage, create Journal Article A1 (C11) and B1 (with categories C22). And C11 and C22 are same level categories (siblings) of the vocabulary V1.
  • Push the article A1 and B1 to the remote Live. The remote Live should have V1, C11 and C22. Both C11 and C22 belong to the Vocabulary V1, and C11 and C22 are siblings.
  • In the Stage, update C11 and C22, let C22 becomes child category of the C11.
  • Push the article A1 and B1 to the remote Live. The remote Live should have V1, C11 and C22. Both C11 and C22 belong to the Vocabulary V1, and C22 should be the child of C11. No new categories related to C11 and C22 should be created, and relationship of C11 and C22 should be updated automatically.

Implementation:

when exporting / importing categories, keep the category UID (and vocabulary UID) same AS IS.

Keeping asset UID same AS IS

This feature (keeping asset UID same AS IS when importing or remote publishing) should be available for any asset (core asset like Document and Media Library document, Web Content artcile, or custom asset like Knowledge Base article) which has UID field.

Scenario I:

  • There are two environments – the stage and the Live.
  • In the stage, create Journal Article A1 and B1, and B1 is associated to A1 - Apply className-classPK pattern to JournalArticle.
  • publish A1 and B1 from the Stage to the Live
    • A1 UID and B1 UID should be maintained same in the Live as that of the Stage
    • Association of A1 and B1 should be maintained same in the Live as that of the Stage

Scenario II:

  • An editorial prepares release article with friendly URL http://${stage.domain.name}/release/${uid}/${article.title} in the Stage
  • Before remote-publishing the release, he / she sends the release with expected friendly URL http://${live.domain.name}/release/${uid}/${article.title} to the mail-list
  • Once remote-published the release, everyone should get the same URL for the release: http://${live.domain.name}/release/${uid}/${article.title}, for example, /feature/626347/2011-Year-in-Review-Collaboration; /feature/626323/2011-Year-in-Review-Core-Networks

Implementation:

When exporting / importing assets, keep the asset UID same AS IS.

More expected staging and publishing features

  • WCM Staging: Synchronize Comments with production (LPS-11213)
  • WCM Staging - UX Check boxes remain checked when publishing to Live after subsequent visits (LPS-12392)
  • WCM Publishing - Option to disable approval process for articles (LPS-10456)
  • WCM Video Publishing - Embedding on Asset Creation and Linking (LPS-13683)
  • WCM Staging - Version/Reversions Publishing and Point in Time Previews (LPS-13562)
  • Ability to remotely publish assets based on versions (LPS-17395)

Download URLs

6.0.12

6.1 CE
 

Indexer post processor hook in Liferay 6.1

November 30, 2011 By Jonas Yuan

Hooks are a feature to catch hold of the properties and JSP files into an instance of the portal, as if catching them with a hook. Hook plugins are more powerful plugins that come to complement portlets, themes, layout templates, and web modules. A hook plugin can, but does not have to, be combined with a portlet plugin or a web plugin. For instance, the portlet called so-portlet is a portlet plugin for Social Office with hooks; a hook plugin can simply provide translation or override JSP page. In general, hooks would be very helpful tool to customize the portal without touching the code part of the portal, as shown in the following diagram. In addition, you could use hooks to provide patches for portal systems or social office products.

In general, there are several kinds of hook parameters in order:

  • portal-properties (called portal properties hooks),
  • language-properties (called language properties hooks),
  • custom-jsp-dir (called custom JSPs hooks),
  • custom-jsp-global (applying custom JSPs hooks globally or locally),
  • indexer post processors (called indexer hook),
  • service (called portal service hooks) – including model listeners and service wrappers,
  • servlet-filter and servlet-filter-mapping (called servlet-filter hooks),
  • struts-action (called portal struts action hooks)

As you can see, JSPs hooks can set a custom-jsp-dir that will overwrite portal JSPs. You can also add <custom-jsp-global>false</custom-jsp-global> (default to true) so that JSPs hooks will not apply globally but only to the current scope. Each site (or organization) can choose to have that hook apply just for that site (or organization).

In addition, Liferay allows portal JSPs to be overloaded by theme templates – this pattern will require that within the theme's templates folder the complete path to the original JSP be maintained with the file extension replaced to match that of the theme's chosen template language.

Abstracted from the Liferay development cookbook: Liferay Portal Systems Development (for liferay portal 6.1 or above version)

The indexer hook allows building a post processing system on top of the existing indexer, therefore plugin hook developers could be able to modify the search summaries, indexes, and queries. Refer to LPS-15811.

This article will show how to build sample indexer post processor hook. Let’s consider use case. As you know, the version 6.1 adds a lot of CMS (Documents and Media) features like

  • Capability to manage different document types: basic document, image (Image Gallery is merged into Document Library), video, audio, etc.
  • Providing Dynamic Data List (DDL) and Dynamic Data Mapping (DDM) - see blogs Dynamic Data Lists I and Dynamic Data Lists II

For the document type “Image”, we are going to add searchable keyword “Image”; while for the document type “Video”, we are going to add searchable keyword “Video”. Thus whenever you search by keyword “Image” or “Video”, you would be able to find out documents from document type “Image” or “Video”.

Implementation

You can build sample indexer post processor hook plugin in following steps.

  • Create a hook project, for example, sample-indexer-post-processor-hook
  • In liferay-hook.xml, add following lines

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.1.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd">
<hook>
    <portal-properties>portal.properties</portal-properties>
    <indexer-post-processor>
        <indexer-class-name>com.liferay.portlet.documentlibrary.model.DLFileEntry</indexer-class-name>
        <indexer-post-processor-impl>com.liferay.hook.indexer.SampleIndexerPostProcessor</indexer-post-processor-impl>
    </indexer-post-processor>
</hook>

As you can see, you can set indexer-class-name as a model entity like DLFileEntry: com.liferay.portlet.documentlibrary.model.DLFileEntry; and set the indexer-post-processor-impl as com.liferay.hook.indexer.SampleIndexerPostProcessor, which must implement the interface com.liferay.portal.kernel.search.IndexerPostProcessor.

  • In web.xml, add following lines

<web-app>
    <display-name>sample-indexer-post-processor-hook</display-name>
    <listener>
        <listener-class>com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.liferay.portal.kernel.servlet.HookContextListener</listener-class>
    </listener>
</web-app>

  • Create sample indexer post processor class: com.liferay.hook.indexer.SampleIndexerPostProcessor

public class SampleIndexerPostProcessor implements IndexerPostProcessor
{
    public void postProcessContextQuery(BooleanQuery arg0, SearchContext arg1)
            throws Exception {       
        if(_log.isDebugEnabled())
            _log.debug("called postProcessContextQuery()");       
    }

    public void postProcessDocument(Document document, Object object)
            throws Exception {       
        DLFileEntry dLFileEntry = (DLFileEntry) object;       
        if(_log.isDebugEnabled())
            _log.debug("called postProcessDocument(): uuid=" + dLFileEntry.getUuid() +
                    " title=" + dLFileEntry.getTitle() +
                    " dLFileEntryId=" + dLFileEntry.getFileEntryId());       
        String text = "";       
        try {           
            long fileEntryTypeId = dLFileEntry.getFileEntryTypeId();           
            DLFileEntryType dLFileEntryType = DLFileEntryTypeLocalServiceUtil.getDLFileEntryType(fileEntryTypeId);
             // add your logic here
            text = dLFileEntryType.getName();           
        } catch (Exception e) {}       
        if(text.length() > 0)
            document.addText(Field.URL, text);       
    }

    public void postProcessFullQuery(BooleanQuery arg0, SearchContext arg1)
            throws Exception {       
        if(_log.isDebugEnabled())
            _log.debug("called postProcessFullQuery()");       
    }

    public void postProcessSearchQuery(BooleanQuery arg0, SearchContext arg1)
            throws Exception {       
        if(_log.isDebugEnabled())
            _log.debug("called postProcessSearchQuery()");       
    }
    public void postProcessSummary(Summary arg0, Document arg1, Locale arg2,
            String arg3, PortletURL arg4) {       
        if(_log.isDebugEnabled())
            _log.debug("postProcessSummary()");       
    }   
    private static Log _log = LogFactoryUtil.getLog(SampleIndexerPostProcessor.class);
}

As shown in the above code, you would be able to add your own logic for summary, search query, context query and document. That’s it.

Results

search by keyword "Image"

Search by keyword "Video"

Download URL

Sample indexer post processor hook Liferay 6.1 with source code.

What’s next?

The next post would be: sample servlet-filter and servlet-filter-mapping hook in Liferay 6.1.
 

Liferay development cookbook: Liferay Portal Systems Development

November 12, 2011 By Jonas Yuan

Liferay Portal Systems Development

Build dynamic, content-rich and social systems on top of Liferay

  • Use Liferay tools (CMS, WCM, collaborative API and social API) to create your own Web sites and WAP sites with hands-on examples
  • Customize Liferay portal using the JSR-286 portlets, hooks, ext plugins, themes, layout templates, webs plugins and diverse portlet bridges
  • Build your own web sites with kernel features like indexing, workflow, staging, scheduling, messaging, polling, tracking, auditing, reporting and more

In Detail

Liferay portal is one of the most mature portal frameworks in the market, offering many key business benefits that involve personalization, customization, content management systems, web content management, collaboration, social networking and workflow. If you are a Java developer who wants to build custom web sites and WAP sites using Liferay portal, this book is all you need.

Liferay Portal Systems Development shows Java developers how to use Liferay kernel (version 6.1 or above) as a framework to develop custom web and WAP systems which will help you to maximize your productivity gains. Get ready for a rich, friendly, intuitive, and collaborative end-user experience!

The clear, practical examples in the sample application that runs throughout this book will enable professional Java developers to build custom web sites, portals, and mobile applications using Liferay portal as a framework. You will learn how to make all of your organization's data and web content easily accessible by customizing Liferay into a single point of access. The book will also show you how to improve your inter-company communication by enhancing your web sites and WAP sites so that you can share content with colleagues.

What you will learn from this book

  • Provide complete coverage of Liferay Portal 6.1 for both the commercial and open source versions within real example Knowledge Base portlet
  • Build basic and advanced MVC portlets with the Service-Builder and RBAC permissions, helping you to build enterprise-ready Java web sites
  • Use Ext plugins and Hooks, allowing you to perform custom actions on your portal
  • Manage images, documents, videos, audios and records using the Document and Media Library and record management
  • Build web content and web forms using the WYSIWYG editors, Custom Attributes, assets tagging and classification, and Dynamic Data List
  • Create collaborative and social API complete with Ratings, Comments, Subscriptions, Collaboration, Social Equity, Asset Links and OpenSocial
  • Improve your portal with staging, scheduling, remote publishing, caching, clustering, indexing, search and workflow.
  • Build WAP mobile-based applications and leverage diverse portlet bridges like JSF, Struts, and Spring MVC
  • Use the common API for monitoring and auditing, tracking, scripting, reporting, messaging, and more, helping you to build dynamic web sites smoothly

Approach

This book focuses on teaching by example. Every chapter provides an overview, and then dives right into hands-on examples so you can see and play with the solution in your own environment.

Who this book is written for

This book is for Java developers who don't need any prior experience with Liferay portal. Although Liferay portal makes heavy use of open source frameworks, no prior experience of using these is assumed.

Table of Contents

Chapter 1: Liferay Enterprise Portal

Chapter 2: Service Builder and Development Environment

Chapter 3: Generic MVC Portlets

Chapter 4: Ext plugin and Hooks

Chapter 5: Enterprise Content Management

Chapter 6: DDL and WCM

Chapter 7: Collaborative API and Social API

Chapter 8: Indexing, Search and Workflow

Chapter 9: Staging, Scheduling, Publishing and Cache Clustering

Chapter 10: WAP and Portlet Bridges

Chapter 11: Common API

 

Building federated search indexer against diverse data sources on top of Liferay

November 1, 2011 By Jonas Yuan

In brief, OpenSearch allows publishing of search results in a format suitable for syndication and aggregation. Federated search is a simultaneous search of multiple online databases or web resources, and it is an emerging feature of automated, web-based library and information retrieval systems. The portal implemented federated search based on OpenSearch standard.

Abstracted from the Liferay development cookbook: Liferay Portal Systems Development (for liferay portal 6.1 or above version, coming out soon)

This article will address an approach – building federated search indexer against diverse data sources on top of Liferay. First of all, let’s consider a use case. A capital group manages many companies (each company has many users as members), hundreds-million accounts (the entity Account) and hundreds-million related documents (meta-data and real content).

The following diagram shows ER models of the current enterprise database (DB2 for example). In one row, the entity Seller could have many Portfolio; the entity Portfolio could have many Account associated; the entity Account could have many Document associated. In another row, the entity Company could have many User; the entity User could have many DcoumentType associated; the entity DocumentType could have many Document associated.

The following is a list of main requirements:

  • Keep the current enterprise database running AS IS for different existing applications;
  • Leverage the portal for user registration and membership management;
  • Leverage the portal RBAC for authorization;
  • Search documents based on accounts’ info and document meta-data
  • Audit users’ activities, track downloads and send update notifications

Solution overview

The following diagram shows an example: DB2 has database schema I and schema II; the portal has its own database and database schema. The schema I will be mapped into the Plugin I in the portal; while the schema II will be mapped into the Plugin II in the portal.

The schema status will be used to store updated results – that is, whenever system updates account and / or document meta-data, record the status as a row. This schema is mapped into the plugin status in the portal.

In summary, the solution would be able to provide following feature.

  • Enhancement of  the Service-builder for diverse data sources in plugins
  • Read-only approach –  data lookup
  • The Pull/push approach using the trigger to update the indexer
  • Scheduling  – check update status by the scheduler
  • Federated search indexer
  • Audit users' activities, records downloads and set up email notification

Diverse data sources support in plugins through the service-builder

First of all, let’s see how to support diverse data sources in plugins through the service-builder. Wiki articles (Connect to a Database with Plugins SDK and Extend Tables in Another Database) have addressed how to connect different database with plugins SDK manually. Here we are focusing on how to support diverse data sources in plugins through the service-builder directly.

This new feature and the fix patch have been addressed at the ticket "Ability to connect different data sources in plugins through the service-builder".  The following steps show the main idea.

  • Predefine a file with JDBC settings like jdbc.properties
  • Predefine template file spring-ext-xml.ftl in order to generate the Ext spring configuration ext-spring.xml
  • Update the class ServiceBuilder.java to generate jdbc.properties and ext-spring.xml in plugins.

After applying the fix patch, the service-builder now supports diverse data sources in plugins.

Example

Let’s have a deep look on a real example. The portal (6.0.6 for examle, you can use 6.1 or 6.0 EE) uses MySQL as its default database. In DB2, there is an entity called DocumentType. Now need to bring data of document types into the portal.

  • Apply the fix patch in the portal
  • Build service xml in a plugin as follows

<service-builder package-path="com.liferay.mdb">
<namespace>MDB</namespace>
<entity name="DocumentType" table="DOCUMENTTYPE" uuid="false" local-service="true" remote-service="true" data-source="mdbDataSource">
<!-- PK fields -->
<column name="documentTypeId" type="long" primary="true" />
<!-- Other fields -->
<column name="name" type="String" />
<column name="description" type="String" />
</entity>
</service-builder>

  • Use the service-builder to generate all services.
  • Configure the target database (through jdbc.properties) in the plugin

## DB2
jdbc.mdb.driverClassName=com.ibm.db2.jcc.DB2Driver
jdbc.mdb.url=jdbc:db2://192.168.2.138:50000/mcm:deferPrepares=false;fullyMaterializeInputStreams=true;fullyMaterializeLobData=true;progresssiveLocators=2;progressiveStreaming=2;
jdbc.mdb.username=lportal
jdbc.mdb.password=lportal

  • Deploy the plugin
  • Manually create database table DOCUMENTTYPE and insert sample data in the DB2

CREATE TABLE DOCUMENTTYPE (
    documentTypeId bigint not null primary key,
    name VARCHAR(512),
    description VARCHAR(512)
);
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1001,'Type A', 'Type A');
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1002,'Type B', 'Type B');
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1003,'Type C', 'Type C');
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1004,'Type D', 'Type D');
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1005,'Type E', 'Type E');
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1006,'Type F', 'Type F');
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1007,'Type G', 'Type G');
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1008,'Type H', 'Type H')
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1009,'Type I', 'Type I');
insert into DOCUMENTTYPE (documentTypeId, name, description) values (1010,'Type J', 'Type J');

The following screenshot shows the results of the plugin in the portal.

The pull/push data approach

The entities DocumentType and Company have hundreds rows. Thus these rows could be retrieved by the Liferay API directly. For example:

int count = 0;
List<DocumentType> list = Collections.synchronizedList(new ArrayList<DocumentType>());
try {
    count = DocumentTypeLocalServiceUtil.getDocumentTypesCount();
    list = DocumentTypeLocalServiceUtil.getDocumentTypes(0, count);
} catch (Exception e) {}

This is the beauty of the service-builder.

The entities Account and Document have hundreds-million rows. Thus these rows could be retrieved by the Liferay API for first-time indexing only, not for checking updates.  Whenever Account and Document got updated in the DB2, trigger the updates in the table status.

In the portal, define a scheduler in the plugin – check the update of the table status regular base (for example, in one minute).  Whenever found rows in the table status, retrieve these rows (and related entities like Account and Document) from the DB2, update the same in the indexer of the portal, and then remove these rows from the table status.

Building federated search indexer

Based on the entities Seller, Portfolio, Account, Company, User, Document Types, Document and View permission in the portal, build federated indexer for the plugin. From now on, you could be able to search documents via the portal default search engine.

Since all entities (from the DB2) got mounted into the portal, you can audit user activities; record downloads and set up email notification whenever in need.

Summary

The approach – building federated search indexer against diverse data sources on top of Liferay – would be useful when integrating existing enterprise database, while keeping the existing applications running. And the new feature (LPS-22552) would be nice in order to improve the functions of the service-builder.

Auditing document-downloads via Document Library Record plugin

September 9, 2011 By Jonas Yuan

As you have been noticed, the version 6.1 adds a lot of CMS (Document Library) features. The following is a list of these features, not the full list.

  • Capability to manage different document types: basic document, image (Image Gallery is merged into Document Library), video, audio, etc.
  • Providing Dynamic Data List (DDL) and Dynamic Data Mapping (DDM) - see blogs Dynamic Data Lists I and Dynamic Data Lists II
  • Ability to mount different repositories via CMIS (see blogs Mounting Multiple CMIS Repositories on Liferay 6.1)
  • Capability to define custom document types in the runtime
  • Capability to define custom meta-data of document types in the runtime
  • Ability to make custom document types and their meta-data searchable
  • Ability to apply Workflow on document-type-level
  • Ability to set up asset-links among assets (like Blogs Entry, Comments, Message Boards Message, Web Content, Calendar Event, Document Library Document, Wiki Page)
  • And more.

This article will introduce an additiona feature: tracking who downloaded documents in Liferay portal 6.1 via Document Library Record plugin.

Use cases

The plugin (Document Library Record plugin) will consider following use cases.

  • Audit document-downloads: who downloaded the document and when the document got downloaded.
  • Define resources to be audited:  only defined resources will get audited
  • Distinguish auditing condition: trace non-signed-in required resource and trace sign-in required resource 
  • Report document-downloads: reporting by group, by user, by resource instance, by document-type, by date (weekly, monthly, yearly).

Abstracted from the book: Liferay Portal Systems Development (A Liferay cookbook for developers using version 6.1 or above)

Possible implementation

The plugin could be implemented in the following steps

  • Specify two entities for Document Library Record: DLRecord and DLRecordLog.

The entity DLRecord is defined as follows.

<!-- PK fields -->
<column name="definitionId" type="long" primary="true" />
<!-- Audit fields -->
<column name="folderId" type="long" />
<column name="documentType" type="String" />
<column name="companyId" type="long" />
<column name="groupId" type="long" />
<column name="userId" type="long" />
<column name="createDate" type="Date" />
<column name="modifiedBy" type="long" />
<column name="modifiedDate" type="Date" />
<!-- Other fields -->
<column name="name" type="String" />
<column name="title" type="String" />
<column name="signinRequired" type="boolean" />

The entity DLRecordLog is defined as follows.

<!-- PK fields -->
<column name="logId" type="long" primary="true" />
<!-- Audit fields -->
<column name="definitionId" type="long" />
<column name="documentType" type="String" />
<column name="companyId" type="long" />
<column name="groupId" type="long" />
<column name="userId" type="long" />
<column name="createDate" type="Date" />

  • Record document-downloads.

The following is sample code.

try {
DLRecordDefinition dLRecordDefinition =
DLRecordDefinitionLocalServiceUtil.findByF_N(folderId, name);
if (dLRecordDefinition != null) {

ThemeDisplay themeDisplay =
(ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
if (dLRecordDefinition.isSigninRequired()
&& !themeDisplay.isSignedIn()) {
response.sendRedirect(themeDisplay.getURLSignIn());
}
long companyId = themeDisplay.getCompanyId();
long groupId = themeDisplay.getScopeGroupId();
long userId = themeDisplay.getUserId();

DLRecordLogLocalServiceUtil.addDLRecordLog(
dLRecordDefinition.getDefinitionId(), companyId,
groupId, userId);
}
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Results

Here I share a few screenshots from the version 6.1 (revision 88826).

Resource search

Trace definitions

List records

When downloading a document (basic document, image, video, audio, etc.), audit it.

Summary

The plugin provided capability to audit document-downloads. It did work fine in the version 6.1. Of course, the plugin did also work well in the version 6 (like 6.0.6 CE, 6.0 EE SP1, 6.0 EE SP2, etc.). In addition, I would send a ton of thanks to Liferay development team who created the draft version of Document Library Record portlet.

Download URLs

6.0.12

6.0.11

6.0.10

6.0.6

6.1.0

Showing 1 - 5 of 50 results.
Items 5
of 10