Tuesday, 30 June 2015

How to modify/override default value of Liferay's property

Liferay controls many things via properties and it supports to override the value of the portal.properties file.
There are two ways available to override portal.properties file.
1) Using portal-ext.properties
2) via Hook.

Lets see how can we override liferay properties via hook.

There are three simple steps to achieve it:

1)  Modify "lieray-hook.xml" to provide support for "properties" file
2)  Create the "portal.properties" file inside "src" folder of the Hook project
3)  Deploy and verify changes

Lets look at the steps in detailed:

1)  Modify "lieray-hook.xml" to provide support for "properties" file
    <hook>
        :
        <portal-properties>portal.properties</portal-properties>
        :
    </hook>
 
    We have specified the file which should be used to override existing liferay properties
 
2)  Create the "portal.properties" file inside "src" folder of the Hook project

Lets say we like to call perform some action before user logs in. That is being controlled by the property called "login.events.pre".

Here is the entry you need to write inside "portal.properties" file.
login.events.pre=com.student.CheckRegistration

So "CheckRegistration" will be called before student/user logs in.

 
3)  Deploy and verify changes

    Once changes are done we need to deploy our Hook project and upon next time login your custom class will be triggered before student login.
 
Note:
   1) If you like to know what all properties can be override using Hook you need to check "liferay-portal-src-6.*\definitions\liferay-hook_6*.dtd"
   2) If you like to know what is the default value of the property you override you can check it on location "\liferay-portal-src-6*\portal-impl\src\portal.properties"
 
 
Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics

Monday, 29 June 2015

How to override custom JSP using Liferay Hook

Many a times we like to make a minor changes on the existing OOTB portlet's JSP. Liferay allows to override / modify existing JSP using Hook.

There are three simple steps to achieve it:

1)  Modify "lieray-hook.xml" to provide support for custom jsps (Assuming you have Hook project with JSP Hook created)
2)  Copy the mirror path (JSP name along with folder structure) from  "liferay-portal-[version]/tomcat-6.*/webapps/ROOT"
3)  Deploy and verify changes


Lets look at the steps in detailed:

1)  Modify "lieray-hook.xml" to provide support for custom jsps  (Assuming you have Hook project with JSP Hook created)
    <hook>
        :
        <custom-jsp-dir>/custom_jsps</custom-jsp-dir>
        :
    </hook>
   
    We have specified the custom JSP path inside which all the overridden JSPs will reside
   
2)  Copy the mirror path (JSP name along with folder structure) from  "liferay-portal-[version]/tomcat-6.*/webapps/ROOT"

Lets say we like to override error page which resides inside "webapps\ROOT\errors\404.jsp".

In this case we need to create the folder "errors" inside "/custom_jsps" and copy and paste the 404.jsp file inside "errors".

So after copy our folder structure would look like this "docroot\custom_jsps\errors\404.jsp".
Open the JSP file and make your changes in it.
   
3)  Deploy and verify changes

    Once changes are done we need to deploy our JSP hook project. Once hook is successfully deployed move onto the below path
   
    "liferay-portal-[version]/tomcat-6.*/webapps/ROOT/errors/" and see that now there would be two JSPs.
   
    1)  404.jsp (your overridden changes)
    2)  404.portal.jsp (original JSP)
   
    Note: If you undeploy your JSP hook at that time liferay will delete 404.jsp and rename "404.portal.jsp" with 404.jsp to bring original file back.
   
   
Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics

Sunday, 28 June 2015

How to create Singleton class in Java (Design Pattern)

Singleton Design Pattern needs to be used when :

    1)  Application needs one, and only one, instance of an object
    2)  Provide a global point of access to the object
   
Here are the thumb rule for creating singleton class

1)  Create private constroctor
    -   This is required so that no one can create instance directly using "new" keyword"
2)  Create "static" method to return Singleton class's object (Lets say method is "getInstance()")
    -   This method is used to create and return object of "Singleton" class
    -   This method will make sure that only one object is available
    -   Since constructor is private in that case we can not create object and access method hence we need a static method which can be
        accessed directly with the "Class" name
3)  Create method "getInstance" as "synchronized"
    -   To avoid creating two objects accidently in case of multi threading environment
4)  Create "private" data member of "Singleton" class
    -   So that datamember can't be accessed directly


Here is the code snippet for the quick reference:

class Singleton
{
private static Singleton instance;
private Singleton() {
//Private constructor, because we don't allow object to be created using new keyword
}

public static synchronized Singleton getInstance()
{
   //Checks if object is not created then only it will go and create next time onwards it will return already created instance
   //keeping this method synchronized is very important where multiple threads gets executed in parallel
if (instance == null)
instance = new Singleton();

return instance;
}
}


Now, you can access/create object of a "Singleton" class like this.

Singleton singleton = null;
singleton = Singleton.getInstance();


Note: Singleton design pattern ensures that one object is available per JVM, in case of clustering environement where more than one JVM are available at that time as many objects would be created as many JVMs.  

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics 

Thursday, 25 June 2015

How to provide multilingual support in Liferay custom portlet

Providing multilingual support in Liferay is very easy. Just need to follow few simple steps and we are all done.

Here are the steps needs to be performed:

1)  Modify portlet.xml file to specify the resource bundle entry
2)  Create properties file for the locate we need to support
3)  Use liferay-ui tld to show message
4)  Deploy and verify changes

Here are the detailed steps:

1)  Modify portlet.xml file to specify the resource bundle entry

    Add the entry "<resource-bundle>content.Language</resource-bundle>" inside the portlet tag. Tag specifies the location of the
    language file.
   
2)  Create properties file for the locate we need to support

    Need to create a key=value pair of properties file based on the locale.
   
    Ex: Language_es.properties
        Language.properties
   
    If we select a region whose corresponding file is not exist then value available inside "Language.properties" will be default as default.
    If we select "Spanish" then the value of the key available inside "Language_es.properties" will be shown to user.
   
3)  Use liferay-ui tld to show message

    On JSP we need to import "liferay-ui" taglib as shown below
   
    <%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
   
    Once tablib import is done we can use "liferay-ui" to show messages to the user. So label will be fetch from the language property file based
    on the locale selected.
   
    Here is the code snippet to use message:

    <liferay-ui:message key="message1" />  
   
   
4)  Deploy and verify changes  

    Yupee! we are done from the configuration part. Lets build and deploy latest war and check the JSP where we have used "liferay-ui" to show
    message. Add the Language portlet on the page and change the language(locale) to "Spanish" you will see value against the key mentioned inside "Language_es.properties"
    file.
   
    Ex: Here are the entries inside
    1)  Language_es.properties
        message1=I am spanish
    2) Language.properties
        message1=I am Default Message

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics    

Wednesday, 24 June 2015

How to do Liferay IPC using Public Render Parameter

How to share data among Liferay Portlets. Liferay provides multiple ways to share the data between more than two portlets. IPC (Inter Portlet Communication) is one of the ways.

Lets see how can we share data using Public Render Parameter:

There are three simple steps available

1)  Modify portlet.xml file and add variable to be shared
2)  Modify controller class to add / access shared variable
3)  Redeploy portlet and verify changes

Here are the detailed steps for doing same:

1)  Modify portlet.xml file and add variable to be shared 

  Here is the code snippet for portlet.xml file
   
    <portlet-app>
    <portlet>
       <portlet-name>FirstPortlet</portlet-name>
        :
        :
        <supported-public-render-parameter>studentName</supported-public-render-parameter>
   </portlet>
   <portlet>
       <portlet-name>SecondPortlet</portlet-name>
        :
        :
        <supported-public-render-parameter>studentName</supported-public-render-parameter>
   </portlet>

<public-render-parameter>
        <identifier>studentName</identifier>
        <qname xmlns:x="http://www.liferay.com/public-render-parameters">x:studentName</qname>
       </public-render-parameter>
        </portlet-app>

    We have used two portlets FirstPortlet and SecondPortlet. Both the Portlet's <portlet> tag contains attribute "<supported-public-render-parameter>"
    where we need to add entry of the parameter shared parameter. If we dont specify "<support..." entry that portlet will not be able to access shared variable.
   
    Outside the <portlet> tag we need to specify "<public-render-parameter>" which specifies the list of all the shared parameters. In our case
    we have provided "x:studentName" as the shared parameter.
   
2)  Modify controller class to add / access shared variable    

        We have two portlets. First and Second. In below snippet we can see that FirstPortlet sets the shared variable inside processAction method.
        Second portlet reads the shared variables value inside render phase.
   
        FirstController
actionResponse.setRenderParameter("studentName", "Test");
       
        SecondController
        String name  = ParamUtil.getString(renderRequest, "studentName");
LOGGER.info("Details -> " + name);

3)  Redeploy portlet and verify changes

    Now lets build the portlet and deploy it. Drop both the portlets on the same portal page. Perform some action on FirstPortlet so that value of "studentName" gets set.
    During render method of the SecondPortlet read the value and print the value on console.

Here is the Output we can see in console:        
        06:53:16,062 INFO  [SecondPortlet:42] Details -> Test

Cheers! You are done.

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics

Tuesday, 23 June 2015

How to use Liferay SessionError to show error message in custom portlet

Many a times people are confused that how to show error message in the custom portlet. Liferay allows to show custom error messages on the JSP inside custom portlet.

There are two simple steps available to configure it:

1)  Modify JSP to use liferay-ui taglib
2)  Modify controller class to add the error key inside SessionError

Here are the detailed steps:

1)  Modify JSP to use liferay-ui taglib

    Here is JSP snippet
    <%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
 
    <liferay-ui:error key="error" message="Error occured while processing your request!" />
    <liferay-ui:message key="sucess" />

    Here we have used "liferay-ui" tablib. Upon loading the JSP key will be compared with the key available inside the "SessionError" if matching key is
    found then the message written under "message" will be shown on the JSP else not.


2)  Modify controller class to add the error key inside SessionError
 
    public void getFirstStudentDetails(ActionRequest actionRequest,
    ActionResponse actionResponse) throws IOException, PortletException {
        try {
            //Perform Some Action            
        } catch(Exception e) {
            //Add "error" key inside SessionError
            SessionErrors.add(actionRequest, "error");
            throw e;            
        }
        //Default success message
        SessionMessages.add(actionRequest, "message");        
    }

Now, build and deploy your portlet. Next time when "getFirstStudentDetails" is called and if any error comes then inside "catch" blok
error key i.e. "error" will be added inside "SessionErrors" and during rendering of the JSP below line will show the error message to the user.
<liferay-ui:error key="error" message="Error occured while processing your request!" />

Cheers! You are done.

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics

Sunday, 21 June 2015

How to implement cron job/scheduler in Liferay custom portlet

Many a times people like to execute specific job on a particular time interval. Liferay provides support for same.

There are three simple steps availbale to do same:

1)  Add entry inside liferay-portlet.xml file
2)  Write class which will be triggered on a specific time interval
3)  Redeploy your portlet and verify

Here are the detailed steps:

1)  Add entry inside liferay-portlet.xml file

    Here is the quick reference of liferay-portlet.xml file

<scheduler-entry>
<scheduler-description>Student Result</scheduler-description>
<scheduler-event-listener-class>com.test.PublishResult</scheduler-event-listener-class>
<trigger>
<cron>
<cron-trigger-value>0 0/5 * 1/1 * ? *</cron-trigger-value>
</cron>
</trigger>
</scheduler-entry>

In above code

"<scheduler-event-listener-class>" is the class name whose "receive" method will be triggered as and when the "<cron-trigger-value>" event occurs.
"<cron-trigger-value>" will be triggered every five minutes.



2)  Write class which will be triggered on a specific time interval

Here is the sample class entry which we specified inside liferay-portlet.xml file under "<scheduler-event-listener-class>"

package com.test;

import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.messaging.Message;
import com.liferay.portal.kernel.messaging.MessageListener;
import com.liferay.portal.kernel.messaging.MessageListenerException;
import com.liferay.portal.kernel.util.StringPool;

public class PublishResult implements MessageListener{

private static final Log LOGGER = LogFactoryUtil.getLog(PublishResult.class);

@Override
public void receive(Message message) throws MessageListenerException {
// TODO Auto-generated method stub
//System.out.println("Student Result Published");
LOGGER.info("Published Result");
}

}

3)  Redeploy your portlet and verify

    To see the LOGGER.info statement inside catalina.out, you need to redeploy your portlet.
    Wait for five minutes and you will see a statement like this in output.
   
    "06:40:02,421 INFO  [PublishResult:20] Published Result"
   

Cheers! You are done.

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics

Thursday, 18 June 2015

How to debug specific condition using Liferay Developer Studio

Many a times I have seen people strugle debugging a lenghty code unnecessarily. When you want to debug and check specific conditions then no need to iterate through each element while debug your code. You can put conditional check point and straigh away check your peace of functionality/condition.

There are two simple steps to do same.

1) Add conditional break point on the line where you like to break
2) Start server in debug mode and execute your functionality

Let's see both the steps in detailed.

1) Add conditional break point on the line where you like to break

i)    Inside Liferay developer studio add break point in your code
ii)   Right click on the break point and go for "Breakpoint properties"

iii)  New popup will be opened up tick mark "Conditional"

iv)  Inside content area write your specific condition
v)   Click on "Ok" button

2) Start server in debug mode and execute your functionality

Start your server in the debug mode. Refer blog "Start liferay tomcat in a debug mode"
(http://technoknowledgespread.blogspot.com/2014/09/start-tomcat-in-debug-mode.html)
If you are having a java stand alone project you can directly right click on the project and go for "Debug As" -> "Java Application"


Note: I have used the stand alone java application to demonstrate "conditional break point" feature of Liferay Developer Studio. You can use for web application as well. I have added break point for "IN" so in "console" output you can see that before "IN" all country code have been displayed and break point has directly stopped on the "IN" condition.

Cheers! You are done.

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics

Friday, 5 June 2015

How to use Liferay's Portlet Session with different scopes


Many times I have seen that people get confused between Portlet Session and its scope. Liferay allows 2 scopes for the "PortletSession" in which data can be stored.

Here are they:

 1) PortletSession.APPLICATION_SCOPE
    -   Data is shared across all the portlet which are under SAME war file
 2) PortletSession.PORTLET_SCOPE
    -   Data is shared among multiple request for PARTICULAR portlet only (Not even with the portlets which are in the same war file)
   
Lets look at how to use both the scope

Here are the overall steps to use/verify PortletSession

1)  Create a portlet and add/store data inside PortletSession
2)  Read / Consume the data added by the another Portlet

Lets look at the detailed steps:

1)  Create a portlet and add data inside "PortletSession"

     // Sample First Portlet's controller
     public void doView(RenderRequest renderRequest,
RenderResponse renderResponse) throws IOException, PortletException {

//  Setting the values inside the application scope inside firs portlet whose value we will fetch inside second portlet (Same war file)
ps.setAttribute("fpPSValue","added value from the second portlet",PortletSession.APPLICATION_SCOPE);
    }
   
2)  Read / Consume the data added by the another Portlet  

    // Sample Second Portlet's Controller
    public void doView(RenderRequest renderRequest,
RenderResponse renderResponse) throws IOException, PortletException {

        PortletSession ps = renderRequest.getPortletSession();
String s,s1 = "";
if(ps.getAttribute("fpPSValue",PortletSession.PORTLET_SCOPE) != null) {
   // Retrieving data from the Portlet Scope
s1 = (String)ps.getAttribute("fpPSValue",PortletSession.PORTLET_SCOPE);
}
if(ps.getAttribute("fpASValue",PortletSession.APPLICATION_SCOPE) != null) {
   //  Retrieving data from the Application Scope
s = (String)ps.getAttribute("fpASValue",PortletSession.APPLICATION_SCOPE);
}

if("".equalsIgnoreCase(s1)) {
   //  If data is not available then set data in the portle scope
ps.setAttribute("fpPSValue","added value from the second portlet",PortletSession.PORTLET_SCOPE);
}    
    }

Note:
 1) In above code if we dont get the data on line
    "s = (String)ps.getAttribute("fpASValue",PortletSession.APPLICATION_SCOPE);"
    then make sure that both the portlets i.e. (First & Second) portlet are under same war file
   
2)  Data added via line
    "ps.setAttribute("fpPSValue","added value from the second portlet",PortletSession.PORTLET_SCOPE);"
    will always be consumed by the same portlet and no other portlet can ever access that data
   
   
We are done!

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics

Tuesday, 2 June 2015

How to remove Liferay custom portlet's preferences while removing portlet from page layout

There are three simple steps to remove the custom portlet's preferences

1) Add "portlet-layout-listener-class" entry inside "liferay-portlet.xml" file
2) Write custom listner which implements "PortletLayoutListener"
3) Deploy portlet and verify functionality

Here are the steps in detailed 

1) Add "portlet-layout-listener-class" entry inside "liferay-portlet.xml" file

    Here is the sample entry which needs to be configured below "<icon>" tag
    <portlet-layout-listener-class>com.student.listener.StudentLayoutListener</portlet-layout-listener-class>

2) Write custom listner which implements "PortletLayoutListener"

    This is the class which will be called and based on the user action on the frontend, specific method will be called
    Here is the sample class entry

    package com.student.listener;
    import com.liferay.portal.model.PortletPreferences;
    public class StudentLayoutListener implements PortletLayoutListener
    {    
        @Override
        public void onAddToLayout(String portletId, long plid) throws PortletLayoutListenerException {
            // Logic while adding portlet on layout            
        }
        
        @Override
        public void onMoveInLayout(String portletId, long plid) throws PortletLayoutListenerException
        {
         // Logic while moving portlet in layout            
        }
    
        @Override
        public void onRemoveFromLayout(String portletId, long plid) throws PortletLayoutListenerException
        {
         // Logic while removing portlet from the layout        
            List<PortletPreferences> portletPreferencesList = PortletPreferencesLocalServiceUtil.getPortletPreferences(aPlid,aPortletId);
                        
         //Iterate over the "portletPreferencesList" and use below method to delete preferences one by one
            PortletPreferencesLocalServiceUtil.deletePortletPreferences(portletPreferences.getPortletPreferencesId());
        }    
    }

3) Deploy portlet and verify functionality

    So configuring custom "PortletLayoutListner" is done just rebuild portlet and after deployment of the portlet verify the functionality. (i.e. remove portlet from the page)      
    [Key Note]: If custom layout listner is not getting called please make sure that Entry inside "liferay-portlet.xml" is proper with correct package structure.

We are done!

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics