How to create Friendly URL for Liferay portlet

You might have seen long urls of links / forms of portlets created by liferay. These urls are called Portlet URLs and they are generated dynamically at run time when we place the portlet on Liferay page. 

In this article we will see how to shorten these URLs in portlet so that it’s more user friendly. (That’s why we are calling it friendly url). In other word Friendly URL is  the process to make shorter Portlet URLs.

Let’s see how this long URLs is created run-time. For easy understanding, I have created Spring MVC portlet. You can refer this blog to create friendly url for Liferay MVC portlet too. This portlet will have one filed called Name and one submit button which will submit this name. 


I would recommend looking at index page ‘A Complete Liferay Guide‘ to browse all topics about liferay.

Please refer my previous blog
How to create Spring MVC Porltet to create Spring MVC portlet. Give the project name as ‘friendly-url‘ so that eclipse will append -porltet so that it will look like as below screenshot.
How to create Friendly URL for Liferay portlet - project structure

I would like to further recommend to visit by blog on How to create Render and Action methods

I have set the controller class name as FriendlyUrlController and the package name is com.opensource.techblog.controller

open FriendlyUrlController.java class and add following methods so that it will looks like below snippet.


Explanation:-

  • We have simply added Default Render(handleRenderRequest) method and action (addUserName) method with key “addUserName“.
  • In the action method(addUserName) we are getting request parameter userName with the help of Liferay utility class ParamUtil and printing it to console ( by logger) to just make sure whatever we enter username is reaching in controller.
Now, add the code to view.jsp so that it will looks like below snippet.

 

Explanation:-

  • In view.jsp, we have created portlet:actionURL  with param action set to addUserName which is having matching key with action method in controller.
  • Then we have created form with one text box(name) and submit button.
Once this is done then build and deploy the portlet. When we deploy the portlet, it will be looks like below screenshot.
How to create Friendly URL for Liferay portlet - portlet-render
When we observe the form url in firebug console as per below screenshot, it will be look like 
form-url-in-firebug
and the url will be 
 
http://localhost:8081/web/guest/test?p_auth=R9q2yoCH&p_p_id=friendlyurl_WAR_friendlyurlportlet_INSTANCE_dkW6&p_p_lifecycle=1&p_p_state=normal&p_p_mode=view&p_p_col_id=column-1&p_p_col_count=1&_friendlyurl_WAR_friendlyurlportlet_INSTANCE_dkW6_action=addUserName
Let us understand what each parameter mean for in this URL.
 
Note that each parameter in url is separated by & 
  • http://localhost:8081 :- is the protocol and host address + port
  • /web/guest/test :- There are 3 parts. 1) /Web 2) /guest and 3) /test. /test is a friendly url of Liferay public page test. Since its public page, /web is added. While /guest is a friendly url of guest community.
  • p_auth=R9q2yoCH:- is the authentication token generated by liferay for security purpose and it will be changed on each submit.
  • p_p_id :- is portlet Id (friendlyurl_WAR_friendlyurlportlet_INSTANCE_dkW6 in our case) which will be derived from the name of the portlet (defined in portlet.xml file)
  • p_p_lifecycle=1 :- which shows the life cycle phase of current request. Since we are calling action method,’1‘ denotes that the current request is in action phase. Apart from action phase, portlet have render, resource and even phase. 
  • p_p_state :- denotes Liferay page’s window state. There are 3 possible values 1)Normal 2)Maximize and 3) Minimize. We are currently normal state. You can change the state by clicking Maximize / Minimize button at right side top bar of portlet.
  • p_p_mode :- shows the mode of portlet. there are various mode of portlet like view, edit, help etc. Currently we are in view mode.
  • p_p_col_id :- This is reference ID of the column in liferay template. there are various out of the box layout template available (like one column, two column(30-70) etc). So this parameter will show the id of the column where our portlet resides. 
  • p_p_col_pos :- This parameter is not present in the URL because we have used one column layout. If layout having more than one columns then this parameter will be added to URL. Its showing the position of column in which our portlet is placed.
  • p_p_col_count:- This parameter shows the no of columns in current layout. Currently we have only one.
  • [p_p_id]_action :- Any parameter in this URL which is prefixed with portlet Id ( friendlyurl_WAR_friendlyurlportlet_INSTANCE_dkW6 in our case) is the parameter set by that portlet. In our case we have used action parameter to pick corresponding action method.(we have passed action parameter by <portlet:param name=”action” value=”userName”></portlet:param> )

You might have tired to understand each parameters and its value. Don’t you feel that this URL should be small enough to remember easily. Well because of the limitation of the portal context, the URL will be generated run-time only and there is no direct way to make is shorter.

Friendly URL

Fortunately Liferay provides a way to achieve this.( to get Smaller – user friendly URL).
Let us see how to achieve this.
create one xml file called friendly-url-router.xml under the package com.opensource.techblog.controller (Its absolutely not required to have same name and location for this file I have created. You may take any appropriate name and location for that.)and add the following code so that it will looks like below snippet.


Explanation at little later in this blog.

In next step, add entries in liferay-portlet.xml file after <icon> element.


Explanations:- (For liferay-portlet.xml file)

  • We have added 3 elements. 1)friendly-url-mapping-class 2)friendly-url-mapping and 3)friendly-url-routes
  • friendly-url-mapping-class is the the class which will help us to get friendly url. This class is provided by Liferay.
  • The value of friendly-url-mapping will be used in url. Its kind of key that will map the friendly url with the actual portlet url at server side.
  • friendly-url-routes will be path of the xml file that we have defined. This xml file is called router.
  • entry of these elements should be same order as I have defined and they must be placed just immediate after <icon> element.
Explanations:- (For  friendly-url-router.xml file)
  • This is router file and it defines the parameters that were there in URL if we not implemented friendlyURL.
  • The first element is <pattern> and it will be used to generate the pattern of friendly URL. We have simply gave /add so it will be part of generated friendly URL.
  • Rest are implicit variables which were in URL if we have not implemented friendly URL.
Next, build the portlet and refresh the page where this portlet is placed. This time you will observe the form URL in firebug console as below
 
http://localhost:8081/web/guest/test/-/submit-name/add?p_auth=R9q2yoCH
 
Cool…… !!! isn’t it ? Now let me explain how its done
This url will be same as previous one till /web/guest/test
  • Liferay then will add – (dash)
  • Next is submit-name which is same as <friendly-url-mapping> element’s value. It means whatever value we give to this element, will be appended after – (dash) in final friendly URL
  • Next to it is /add which is nothing but the pattern value in router (friendly-url-router.xml) file.
  • The last is p_auth parameter. Since we have not defined it in implicit variable(because its dynamic) in router xml, its showing explicitly in URL.

Important Notes:-

  • In this example we have used instanceable portlet. Because of this its generating the p_p_id as friendlyurl_WAR_friendlyurlportlet_INSTANCE_dkW6
  • In this p_p_id the last 4 characters are instance key and it will only be generate when we place portlet on page. So that they are dynamic
  • It means If I place the portlet on page then let say the instance Id generated is pkd5 and when I remove the portlet from page and again if I place it then this time its not necessary that the same instance Id is generated.
  • This create the problem as you can see that we have given p_p_id in router xml as implicit parameter.
  • So the best practice is that make portlet non-instanceable (by setting instanceable element false in liferay-portlet.xml file) while generating its friendly URL.
  • You also have observed that I have defined the action implicit variable, which is nothing but the corresponding action method key so this url will

So far we have created one action URL and created friendly URL for that. But what if we have to create multiple friendly URL. Let us see how to do it.

I would like to further recommended to visit by blog on How to create Render and Action methods

To explain it better, I am adding 2 render methods in controller class so that it will looks like below snippet.


Explanation:-

  • I have added 2 render method which will just display different JSP files. These render method will be called based on matching keys( viewUser and editUser)
  • We also have to create corresponding JSP (viewUser.jsp and editUser.jsp) at the same path where we have defined view.jsp (inside /WEB-INF/jsp folder)
Next, we will add entry in router xml as below snippet.
 


Explanation:-

  • Now we have added 2 more entries. one is for view and second is for edit pattern.
  • Note that this time we have defined p_p_lifecycle=0 means its for render phase/lifercycle
  • Also we have set the action parameter same as key of render methods in controller.
  • This action parameter in this router xml will also be matched with the action parameter while creating render url in jsp
Next to it add two render url and its link to JSP as per below snippet.

 
You can observe that I have added 2 more render url with action parameters (matched with key of render method in controller and implicit variable in router xml file.
We can differentiate different friendly URL by pattern attribute in router xml file.
Now build the portlet and refresh the page. you will observe the link something like 

For /view pattern the url is :- http://localhost:8081/web/guest/test/-/submit-name/view
For /edit pattern the url is :- http://localhost:8081/web/guest/test/-/submit-name/edit

Summing Up

  • Friendly URL is a technique to make short portlet URL.
  • To make friendly URL, we need to define router xml for that portlet.
  • In this router xml, we can define various parameters (implicit , explicit etc).
  • We can define multiple friendly URL for same portlet.
  • Additional information can be find from this link.
And that all done. You may do some more practice to get this concept clear. Feel free to ask any question. I will try my best to answer it.

I would recommend looking at index page ‘A Complete Liferay Guide‘ to browse all topics about liferay.
Download Source
Download Source

Share This Post

41 Comments - Write a Comment

  1. Hi Nilang,
    I am using Spring mvc portlet and friendly url mapping for liferay 6.2 but in my url i am unable to hide mvcPath parameter with render url. If i mention implicit parameter in xml, then it is not redirecting to another jsp.
    Can you please help me regarding this.

    Reply
    1. Hello Kinjal,

      You need to give mvc path in router xml as below.
      /{jspPage:\S+}/ /html/path/{jspPage}.jsp

      You can pass jps name while constructing your url which would be then considered as generated parameter. Try this and let me know if you still face any trouble.

      Regards
      Nilang

      Reply
      1. I tried as you suggested and my url is changing but desired jsp page is not rendered.
        My code in routes.xml :

        /{action}
        {action}
        {mvcPath}

        and in jsp i have :

        and in controller :
        @RenderMapping(params =”action=addEvents”)
        public String addEvents(RenderRequest request,RenderResponse response,Model model){
        return “addEvents”;
        }

        Please suggest if I am missing something.

        Reply
        1. Hello Kinjal,

          Welcome to Techblog. Make sure about following things.
          1) put some debug points in your this render mapping method and make sure atleast control goes there.
          2) make sure addEvents.jsp file present (double check with spell mistake).

          Regards
          Nilang

          Reply
    1. Hi Pradnya,
      Welcome to Techblog

      ‘submit-name’ in my example, is the value of tag defined in liferay-portlet.xml file which I believe used to separate friendly url mapper xml for each different portlet. Just check by removing element and see if that works ? Please let me know the result.

      Regards
      Nilang

      Reply
  2. Hi Nilang

    I was created Friendly URL By following code.

    <a href="” >MORE

    In My liferay-portlet.xml file I have Configured below properties.

    com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper
    article
    article-url-router.xml

    And I have created one file article-url-router.xml and put below configuration.

    /view
    article_WAR_articleportlet
    0
    normal
    view
    viewArticle

    the Url is generated below like
    http://localhost:8080/web/guest/-/article/view?_article_WAR_articleportlet_articleCategory=CATEGORY&_article_WAR_articleportlet_articleId=12345

    In Url Parameter also append.Is there any way to pass the parameter with out appending in URL and i also want to create dynamic Friendly URL like category is entertainment,
    http://localhost:8080/web/guest/-/article/view/entertainment

    So is this possible,Can you Please help me?
    Thanks in Advance

    Reply
  3. Hi Nilang,

    Just wanted to know, in case of when we are using multiple portlet in a single portlet then will this work ? if yes do i need to create seperate xml’s for every portlet ?

    Reply
    1. Hi Ravi,

      Welcome to Tech blog and thanks for writing. Friendly url will work even if you have multiple portets in single plugin project. If you observe, when WAR is deployed, there will be separate folder created for each portlet in plugin project. (However there will be only one WAR) For different portlet, you no need to create separate xml file but you need to add entry in portlet.xml, liferay-portlet.xml file. You can refer my another blog :- http://www.opensource-techblog.com/2012/12/how-to-create-multiple-portlets-in.html

      Let me know if you need any further help.

      Regards
      Nilang

      Reply
  4. Hi Nilang,

    Thank you for your time.
    I have studied it from your blog.But when i am using action URL p_auth is appearing in URL while in render URL , URL is ok as i want to create it .I want to remove it from URL when i am using action URL also

    Reply
  5. Hi,

    I was able to make friendly url the way you have explained but i need something like host/username …

    like creating a profile page with dynamic content .. eg: facebook.com/username …

    can we create such url structure in liferay?

    Reply
    1. Hi Nikhil,

      Welcome to Tech blog. In Liferay the friendly url mean for reducing parameters in url. If you observe, if we don’t put the parameter in xml file, they will be visible in URL. So from Liferay point of view, friendly url is concept to reduce parameters appending into URL. In your case, its depend upon what parameters are used while creating render or action URLs. You can also append custom parameters in xml file if they are fixed for that page or portlet. Hope this explanation answers your questions.
      Feel free to ask questions / give suggestions.

      Regards
      Nilang

      Reply
  6. Hello Nilang,

    I have a requirement of creating an actionurl and then sendredirect to another website. When the user clicks a button on third party site, they will append couple of tokens to actionUrl i have sent and call redirect so that it will come into my portlet action.

    RenderResponse, ResourceResponse has createActionurl() methods and ActionResponse has sendRedirect(url) method.

    How can i make those calls one after another in same method.

    Thanks,
    Nandi.

    Reply
    1. Hello Nandi,

      Really sorry for late responding. I understand from your problem is that you want the user when press the link, will hit actionurl, and when it reach to page, it should be redirected to some thirdparty website.

      This can be achieve by javascript. When the next page (jsp) open you can put redirect to third party website by calling JS function window.url(<>).

      Let me know if this work for you.

      Regards
      Nilang I Patel

      Reply
  7. Nicely explained and well written, I will def refer your blog to others who want to explore liferay.

    Thought of sharing this as I have not found it here.Lifecycle value for resource url is 2.
    2

    Regards,
    Shashant

    Reply
  8. Hi Nilang,
    I need your help. Have you tested your liferay portlets. If yes, what kinda tests have you used.
    For my project I am using unit tests and selenium tests. Is it also possible to do any another tests.
    Any information would be really helpful for me

    Reply
    1. Hi Tanaji,

      It seems that you have to add the parameter action (for addUserName) in router xml like
      <implicit-parameter name=”action”>editUser</implicit-parameter>

      Try this and let me know if you face any trouble.

      Regards
      Nilang

      Reply
    2. Hi Tanaji,

      Few updates, I refer your code and created the similar portlet. The change is required in router xml

      1) You need to change the DTD version. Because it seems that you are using Liferay 6.1 but the DTD version of router xml is 6.0. You need to change it.
      2) instead of action parameter for /add , just try putting javax.portlet.action. I have sent my router xml to you over mail (check your mail).

      Just try it and test and let me know if you still having any issues.

      You may wonder that for render method why its just work for “action” parameter. but for action url its required javax.portlet.action as actions’ value.

      The reason is, for actionUrl, portlet will put the parameter called javax.portlet.action in url. While for renderUrl, there is no such parameter is placed. The reason its showing action parameter in renderurl is you have passed explicetly. You can just remove the action paramtere in renderUrl (in view.jsp) . Also you can remove the action implicite prametere in router.xml

      I guess you are confused with SpringMVC porlet and Liferay MVC portetl. Because in my blog I gave example for Spring MVC portlet and you send me the LiferayMVC portlet.

      I gave this solution for Liferay MVC porltet only.

      Reply

Post Comment