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

Tuesday, 26 May 2015

How to use Liferay's FriendlyURL Mapper

Advantage: of FriendlyURL mapping is that it removes unwanted parameters from the URL and makes the URL very simple.

There are simple 3 steps to configure Liferay's FriendlyURLMapper in custom portlet

1) Configure friendly URL details inside "liferay-portlet.xml" file
2) Create Friendly URL routes mapping file
3)     Create Liferay URL in JSP
4)     Build your portlet & deploy it again and see URL being generated

Lets see in detailed what entries we need to specify for configuration:

1) Configure friendly URL details inside "liferay-portlet.xml" file

We need to specify 3 things as mentioned below:

<friendly-url-mapper-class>com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper</friendly-url-mapper-class>
<friendly-url-mapping>my-mapping</friendly-url-mapping>
<friendly-url-routes>com/mypage/portlet/my-portlet-friendly-url.xml</friendly-url-routes>

In most of the cases we will keep "DefaultFriendlyURLMapper" for the friendly-url-mapper-class.
"my-mapping" name after which all the custom parameters will be appended. For more details please see sample URL(step - 4) which gets generated.
"my-portlet-friendly-url.xml", this is the file in which we need to specify all the mapping configuration.

2) Create Friendly URL routes mapping file

<?xml version="1.0"?>
<!DOCTYPE routes PUBLIC "-//Liferay//DTD Friendly URL Routes 6.0.0//EN" "http://www.liferay.com/dtd/liferay-friendly-url-routes_6_0_0.dtd">
<routes>
<route>
<pattern>/{myPageName}</pattern>
<generated-parameter name="myJsp">/{myPageName}.jsp</generated-parameter>
</route>
</routes>

3) Create Liferay URL in JSP

<portlet:actionURL var="getMyPageDetails" name="getMyPageDetails" >
<portlet:param name="myJsp" value="/sample.jsp"></portlet:param>
</portlet:actionURL>  

Make sure that parameter passed in Lifery URL in our case "actionURL" must match the "generated-parameter" name value of Friendly URL mapping file.

4) Build your portlet & deploy it again and see URL being generated

Here is the Sample URL:

Eariler (Before using Friendly URL):
http://localhost:8080/web/student/course?p_p_id=MyPage_WAR_MyPageportlet&p_p_lifecycle=1&p_p_state=normal&p_p_mode=view&p_p_col_id=column-3&p_p_col_count=4&_MyPage_WAR_MyPageportlet_myJsp=%2Fsample.jsp&_MyPage_WAR_MyPageportlet_javax.portlet.action=getMyPageDetails

After applying Friendly URL changes:
http://localhost:8080/web/student/course/-/my-mapping/sample?p_p_lifecycle=1&_MyPage_WAR_MyPageportlet_javax.portlet.action=getMyPageDetails


We are done!

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics

Friday, 1 May 2015

How to use Liferay portlet namespace inside script tag

There are two ways available to use <portlet:namespace/> inside script tag / js file

1) Take hidden variable inside JSP and store value of portlet name space in it
2) Use script tag inside your JSP file and directly use <portlet:namespace/>

1) Take hidden variable inside JSP and store value of portlet name space in it

    <input type="hidden" name="nameSpaceValue" id="nameSpaceValue" value='<portlet:namespace/>' />

    Once it is declared like this inside .js file we can use portlet name space like this,
   
    var nameSpaceVal = document.getElementById('nameSpaceValue').value;
   
    document. + nameSpaceVal + fm.action = {some action}
   
2) Use script tag inside your JSP file and directly use <portlet:namespace/>

    function getStudentDetail() {
    document.<portlet:namespace/>fm.action='<%=getStudentDetails%>';
    document.<portlet:namespace/>fm.submit();
    }  


For debugging purpose, you can check the value of the function(getStudentDetail()) and how the values are getting formed for the lines

document.<portlet:namespace/>fm.action='<%=getStudentDetails%>';
document.<portlet:namespace/>fm.submit();

Cheers!
Henal Saraiya
(Senior Consultant)
CIGNEX Datamatics