Wednesday, December 3, 2014

[Liferay] How to use Liferay Caching Mechanism using MultiVMPoolUtil

Most often, we need to use some kind of caching for our portlets. Whether it is weather data or stocks or some news feed we get from other sites. For each user who loads the web page we don't want to go to weather/stocks/news services and get new data each time. We rather cache the data for some time lets say 10 minutes and then renew whenever a user requests after 10 minutes.

So, how we should use the cache.

We have MultiVMPoolUtil which is a utility class to access MultiVMPool.
We need the above two methods (either one of them) to store our data.
All we need is a name under which the data should be stored, a key to store data and value which holds the actual data. So it is just a name, and a key-value pair. value is usually an object and name and key are strings.

How can we form name and key and How should we.. ?
We store data for some context it can be for portlet or spread over multiple portlets. Suppose my project short name is RE (short for Reporting Engine) and I need to store data for 5 reports objects which I collected from some other place. That some other place may be can named as ABC. I might keep name as reReportDataABC. I might be collecting finance report for ABC so I can choose key as ABC-finance or ABC:finance assuming there might be other types as well. ABC:staff, ABC:annual etc.. purely depends on your requirements. Last, the value would be just the object whatever holds the data. It can be a list or just an object.

So, we would need to make a call as -

public static final String RE_REPORT_DATA_ABC = 'reReportDataABC';
MultiVMPoolUtil.put(RE_REPORT_DATA_ABC, 'ABC:finance', reportsDataList);

And to get the data again
Object reportsObject = MultiVMPoolUtil.get(RE_REPORT_DATA_ABC , 'ABC:finance');

So the final code would be like this-

Now there is a catch -
The approach above will work just fine if there is just one user and user sits idle for 10 minutes and cache gets clear in the time defined (time to live : ttl), suppose that was 10 minutes. But what if there are 1000 users and cache does not get clear. The code above is not going to get live data because it was being access regularly and no idle time reaches 10 minutes.

In this case, we could just add one more key for time. See the code below.
I hope its clear now and works fine as expected.

Until next time, keep caching.. :P :)




Friday, November 28, 2014

[Liferay] [Maven] [Service Builder] Building Liferay Service using Maven - "The Correct Way"

I found many posts which explain and show the way to build services using maven by modifying the pom.xml and ask you to include plugins with groupId : org.codehaus.mojo and artifactId : build-helper-maven-plugin.
Even though that works just fine, I could not take it as a right way to do. So what maven and liferay actually offer in this case?

We know that our portlets just use the service jar file they need. That makes service an independent project. That's exactly what maven makes it..

Try this with me.. lets build a brand new portlet. Portlet name is : mvn-service-builder-portlet [You could just name as mvn-service-builder. By mistake, I added portlet to artifactId and now portlet comes two times in the project name.]

1. mvn archetype:generate

2. You will now see a folder named mvn-service-builder-portlet but inside there would be two more folders

3. Now you can load these two projects in eclipse and see there is a service.xml file in mvn-service-builder-portlet-portlet > src > main > webapp > WEB-INF. In short where it should be :) 

4. Add your services.

5. Now navigate to the folder inside mvn-service-builder-portlet using command prompt. You can now run the commands to build service
mvn clean liferay:build-service install

6. liferay:build-service is going to build service and install is going to install the jar file to m2 repository in your local machine. 

7. If you see below error in eclipse or any other IDE where you imported the projects-
The hierarchy of the type 'Class name' is inconsistent

Then make sure the version of your service in pom of service is same as in portlet pom. If they are different, change the version to be the same. Usually it is ${pom.version}which you can replace to e.g. 1.0.0.0 or a version of your choice.

Now also choose a proper namespace for your service builder.

After this, re-run the service builder and install again. Refresh the project in IDE and you're done.

You don't need to add plugins manually to your pom.xml, this I feel the clear and correct way to develop services in portlets :)

Hope this helps someone.

Get the source here Maven Service Builder Sample Portlet Project

Until next time.. keep building services and enjoy :)

Tuesday, November 25, 2014

[Liferay] Data Migration Tab Loading Issue Fix


If you have many files in document library of Liferay portal, this problem will occur. Data migration tab will not get loaded. Each uploaded/updated file creates entries to DLFileEntry and DLFileVersion tables in database.

When we load data migration tab in Control Panel > Server Administration > Data Migration, Liferay tries to get all the ConvertProcess types which can be used to migrate data. One of which is com.liferay.portal.convert.ConvertDocumentLibraryExtraSettings for which the query below runs. This query takes a lot of time to complete and depends on number of rows in both tables. This query may take almost 10 minutes for just 10000+ documents in your document library.

Usually the result is zero and the method call convertProcess.isEnabled() returns false. And if it is false, ConvertDocumentLibraryExtraSettings is not going to appear in the dropdown which lists all available conversion process. In this case, it should be safe to use this hook.

We do not have opportunity to always change the db and optimize indexes and queries. This query is in Liferay core code and we can not modify this. The good thing is that we do not always load ConvertDocumentLibraryExtraSettings to migrate data and if you can skip that, you are free to use this hook.


Once the hook is deployed, it will always load properly the Data Migration tab.

Hope this helps someone in need :)

[Liferay] Ajax with JQuery, AUI with Action URL / Resource URL

Though its pretty simple and has been there for a long time now, I am writing this post to help new users.

Check the code below with three links. We will use these links to call our data using ajax calls.

To make an ajax call using JQuery with actionURL

To make an ajax call using JQuery with resourceURL

To make an ajax call using AlloyUI and resourceURL

Hope this helps someone in need.

You can get the source of the portlet here on github
Ajax JQuery Portlet
This portlet is for 6.1.20 version of Liferay and for previous versions you can check here.
Ajax JQuery Portlet

Until next time. Keep Ajax -ing :-)

Wednesday, November 19, 2014

[Liferay] [Hook] Fix for Special Characters in Friendly URL of Web Content

Friends,

In the last post [Liferay] Show Web Content in a different page using Asset Publisher we learned how to use asset publisher to display web content in specific portlet and make it a fit for most of the requirements.

That time, I also mentioned that a problem exists if we use special characters in title of web content, it creates some problem. Problem is that, Liferay replaces most of the special characters while generating unique url for the web content but fails to recognize all. That leads to existence of special characters in title and Liferay fails to show that web content in specific portlet.

Solution was simple, replace all special characters which Liferay code missed. Liferay takes care of these characters in FriendlyURLNormalizerImpl.
Changing FriendlyURLNormalizerImpl was not easier as per our project requirements so I fixed JournalContentLocalServiceImpl instead. I created a service wrapper hook and changed the code for addArticle(...)
This code replaces the special characters from existing title and updates article. This hook must be present before we create a web content.

That's it for now.

Until next time. :)

Tuesday, November 18, 2014

[Liferay] Show Web Content in a different page using Asset Publisher

Guys,

Sometimes, we get requirements to list all news on one page and then if clicked on title, show their details on another page. We can surely do this using Asset publisher. Simple steps below.

  1. Create a Page for listing - Suppose that page is News.
  2. Add Asset Publisher to the page. In the configuration of Asset publisher - Set "Asset Link Behavior"  to  "View in a Specific Portlet

  3. Now create a new page for details - Suppose that page is News Details
  4. Add Asset publisher to the page. In the configuration of Asset Publisher - Check "Set as the Default Asset Publisher for This Page".

  5. Make sure you select Display style as Full content.
  6. Now create a web content. 
  7. In the create screen, add a display page. In the list of display pages, you should be able to see News Details page enabled.
  8. News Details page appears because we followed step 4.

And that should be it. Now go to your news page and click on title of newly created web content. It should display the web content in news details page. You should be able to see the friendly url in browser navigation bar.

That's it for now. Next post will cover a problem with the above. We could not use special characters in title of web content because then friendly url will contain that special character and browser won't understand where to redirect, so it would either go to home page or stay on the same page.

Until next time. :)

Friday, October 10, 2014

[Liferay] [Apache] Setting up Apache as web server in front of Liferay using mod_proxy


Setting Apache as web server for Liferay front is so easy. Thanks Alpesh Sir ji for help.

Once Apache is installed, open httpd.conf and add the lines like below-


Make sure you enable mod_proxy and mod_proxy_http before starting apache.
Piece of cake. Isn't it?

Until next time.

[Liferay] Setting up Liferay 6.2 on vFabric TC Server 2.6

Sometimes, Tomcat is not enough to run Liferay- reasons may include performance, client's wish etc.

So here are the steps on how to configure Liferay instance on tc server 2.6. Same steps can be followed for liferay version below 6.2, at least for 6.1 I have verified.

We have D:\pFiles\LR\tc-instance\ directory where vFabric tc server is installed. And we will use D:\pFiles\LR\tc-instance\liferay62.local\ to install our lifeary instance.

  1. Lets download liferay from sourceforge
    - Liferay Portal 6.2 CE GA2
    Download portal war file - liferay-portal-6.2-ce-ga2xxx.war
    Download Dependencies - liferay-portal-dependencies-6.2-ce-ga2xxx.zip

  2. Unzip/Install tc server to a location of your wish. I installed to D:\pFiles\LR\tc-instance. This directory will be called TCSERVERHOME

  3. Now we need to create a instance of server lets say this name as liferay62. Use the following command.
    tcruntime-instance.bat create -i D:\pFiles\LR\tc-instance\liferay62 liferay62
    This will create a new instance for liferay62 in the  D:\pFiles\LR\tc-instance\liferay62.

  4. Now, lets install Liferay. Extract the dependencies files which we downloaded to
    D:\pFiles\LR\tc-instance\liferay62\liferay62\lib

    NOTE: You might want to know why liferay62\liferay62, In case you want to install multiple instances, you will need multiple data folders for each and similarly deploy folder. Now deploy and data folders will be created in liferay62\data and liferay62\deploy rather than tc-instance\data and tc-instance\deploy.

  5. We need some more files to be copied to lib directory. You can copy them from liferay tomcat bundle. Check the image below and copy those files as well. You need not to copy all the files for your db connector. Just add the one you want.
  6. Now we need to modify some configuration. For ex. memory configs etc.
    Modify the file
    D:\pFiles\LR\tc-instance\liferay62.local\liferay62.local\conf\wrapper.conf
    Change the following lines as per needed configuration
    Last 2 lines may not be present, so you can add them to the file.

  7. Create a directory in conf and add ROOT.xml
    D:\pFiles\LR\tc-instance\liferay62.local\liferay62.local\conf\Catalina\localhost\ROOT.xml


  8. Change common.loader and port number of your choice in catalina.properties file. Make sure you modify both base.jmx.port and bio.http.port 

    common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar,${catalina.home}/lib/ext,${catalina.home}/lib/ext/*.jar

  9. Extract lifeary war file to
    D:\pFiles\LR\tc-instance\liferay62.local\liferay62.local\webapps\ROOT

  10. Starting liferay as windows service, go to D:\pFiles\LR\tc-instance\liferay62.local\liferay62.local\bin and run tcruntime-ctl.bat install

Start your liferay instance, go to D:\pFiles\LR\tc-instance\liferay62.local\liferay62.local\bin and open command prompt. tcruntime-ctl.bat start

To stop server
tcruntime-ctl.bat stop

Your liferay server should be up and running at the port you configured. 

That's all for now.

Wednesday, September 24, 2014

[Liferay] Get preferences of another portlet | Get preferences of Portlet A in Portlet B

Hi,

Sometimes, we need to get preferences of a portlet into another portlet and take action appropriately.

Here is a snippet on how to do so. Suppose we have portlets A and B. We need preferences of A in B.
We can use dynamic query to get all the preferences of the portlet. From B we can use the code below. Replace myportletA with the correct porltetId.

We need to convert com.liferay.portal.model.PortletPreferences to javax.portlet.PortletPreferences to use getValue() or getValues() method.
Hope this helps someone.
Cheers!!!

Monday, September 15, 2014

[Liferay] Use Database to store Liferay documents | Use JCR Jackrabbit with Database | JCRStore

So, Simple steps to use JCR | Jackrabbit with Database..

1. Start a liferay instance with any database you need. For me its, MSSQL 2005 Express Edition.

2. That will create a repository.xml file in data/jackrabbit/ folder.

Below is a default repository.xml file.
 Change the content to include filesystem and persistence manager in this way. Use your correct username and password.
3. Now, Add the properties below in portal-ext.properties file. We need to let liferay know that we are going to store images and document in db via JCR.
com.liferay.portlet.documentlibrary.store.JCRStore is what we need to store documents via JCR.

That's it. Restart your liferay instance and you should see the files being stored in database.

Check my post below to see if database size increases when you add few files.
[SQL Server] Get size of database in SQL Server 2005 

All done.

Until next time. :)

[SQL Server] Get size of database in SQL Server 2005

Recently,

I needed to configure Liferay with SQL Server 2005 Express edition and I wanted to calculate the total database size of lportal database.

The query below gives me exact results.


Results
dbname    log_size_mb     row_size_mb      total_size_mb
lportal 1.50                   19.19               20.69

Hope this helps someone. :)

Cheers!!!

Friday, September 12, 2014

[Liferay] How to Undeploy Ext from Liferay | Undeploying ext from liferay

Recently, I had to undeploy ext plugin from Liferay

Here is what needed to be performed.

1. Delete the ext folder from webapps folder.

2. Stop the instance

3. Delete the ext service jar file from global lib. For tomcat it is in tomcat/lib
ext-*-ext-service.jar
4. Delete the ext jar files from webapps/ROOT/WEB-INF/lib
ext-*-ext-impl.jar
ext-*-ext-util-bridges.jar
ext-*-ext-util-java.jar
ext-*-ext-util-taglib.jar

5. Delete ext xml files from webapps/ROOT/WEB-INF
ext-*-ext.xml
liferay-portlet-ext.xml --will be present if any portlet was added/existing portlet was modified in a way that portlet.xml kind of changes were needed.
portlet-ext.xml --will be present if any portlet was added/existing portlet was modified in a way that portlet.xml kind of changes were needed.
tiles-defs-ext.xml

6. Delete work folder

7. Delete temp folder

8. Remove/comment any line that uses a class of ext plugin in portal-ext.properties. This can be any entry for ex. start up event, service actions etc.

So, That's it.

Cheers!!!


Friday, August 22, 2014

[Liferay] Get and Set portlet preferences in liferay | In Portlet Class and JSP

We often need to get and set preferences of a portlet. Here is few simple lines to do the job.

To get preferences of portlet, from the portlet class using actionRequest use

final PortletPreferences preferences = getPortletPreferences(actionRequest);

To get preferences of portlet, from the portlet class using renderRequest use

final PortletPreferences preferences = getPortletPreferences(renderRequest);

There are other methods as well. If we get get portletResource then to get preferences use the code below.

final String portletResource = ParamUtil.getString(portletRequest, "portletResource");

PortletPreferences preferences = null;
try {
preferences = PortletPreferencesFactoryUtil.getPortletSetup(portletRequest, portletResource);
} catch (final Exception e) {
LOG.error(e.getMessage(), e);
}

if (preferences == null) {
preferences = portletRequest.getPreferences();
}

In the JSP get the preferences using

PortletPreferences preferences = renderRequest.getPreferences();

To store preferences
preferences.setValue("key", value);
preferences.store();

Thats It! :)


Friday, June 13, 2014

[Liferay] Permission Checker : Setting a portlet to be available for Admin only..

In last post, we got all the sites, but everyone can access what we have in front end if we don't take care of Permissions. 

Permission checker comes into the picture.. 


PermissionChecker permissionChecker = PermissionThreadLocal.getPermissionChecker(); 
Boolean isUserAdmin =permissionChecker.isOmniadmin();
if(permissionChecker.isOmniadmin()){
          // Do what you want.. no user other than admin can see this.
}
Imports..
com.liferay.portal.security.permission.PermissionThreadLocal
com.liferay.portal.security.permission.PermissionChecker


That's all we need. 

Enjoy. Now you have all the sites.

Thursday, June 12, 2014

[Liferay] Get all the sites in Liferay

Its time I start posting about Liferay.. :)

Most of the times we need very small things.. code that can help us getting data from liferay.. its all there already, but we are not aware most often..

I had to load all groups/sites in a dropdown and then select one to extract some content from the document library of that group. So to make it easier, and clean It was better to provide a list of all sites to Admin and let Admin decide which one to be selected.

To get all the groups we can simply use.
List<Group> groups = GroupLocalServiceUtil.getGroups(0, GroupLocalServiceUtil.getGroupsCount());

But to get only sites we need.. to use search method.
List<Group> groups = GroupLocalServiceUtil.search(PortalUtil.getCompanyId(renderRequest), null, null,null, QueryUtil.ALL_POS, QueryUtil.ALL_POS);

Imports are..
com.liferay.portal.kernel.dao.orm.QueryUtil
com.liferay.portal.util.PortalUtil
com.liferay.portal.model.Group
com.liferay.portal.service.GroupLocalServiceUtil

Thats it.. :)