How
to create Friendly URL for Liferay portlet (ServeResource URL) Which will give
a JSONFeed File as response .
My  goal in this article will be to
show you how to shorten the URL in portlet so that its more user friendly.
Actually
I have a requirement where I have written a ServerResource()   on a link of the portlet .Once User clicks
on the link ,a Json feed file would popup as a download with SAVE or OPEN options.
Generally
its similar to Web Services ,I will share a link(Lengthy) with client ,who can
consume my feeds and who can share it with other teams .But I am not using any
webservices here ,as I want it to be as simple as possible.
Note:
There is no change on the state of the portlet , only a popup to save/open is
showed.
Here
is how I have done it.
I
have used simple Liferay MVC portlet .
Where
I have a Portlet Controller class as show below.

This is
under a package com.client.nci.topstory.admin.controller
Now
here the code for creating a Ajax link (serverResource)  inside view.jsp
<portlet:resourceURL var="jsonUrl"> </portlet:resourceURL>
<a
href='<%=jsonUrl %>'>json feed link</a>

If you see the link Url ,i.e. 
http://localhost:8080/web/guest/topicpage1?p_p_id=topstorytopicpage_WAR_NewTopStoryportlet&p_p_lifecycle=1&p_p_state=normal&p_p_mode=view&p_p_cacheability=cacheLevelPage&p_p_col_id=column-1&p_p_col_count=1
So when ever User clicks on the below link  a popup whould appear as show below 

Here is my code in the portlet class .i.e.
controller class (ServerResource())
/*
 * This is for passing Json File for outside
Users
*/
 public void serveResource(ResourceRequest
request, ResourceResponse response)
               
throws PortletException, IOException {
                   ThemeDisplay themeDisplay =
(ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
              
String portalUrl = themeDisplay.getPortalURL(); 
                    TopStoryAdminServiceImpl topStoryService = new
TopStoryAdminServiceImpl();
//service
method call which will return me my JSON FEED 
 Map<String,TopStoryAdminBean>
topStoryMap = topStoryService.fetchHomePageTopStories(count,portalUrl); 
String
jsonMap ="";
 // Json Conversion 
jsonMap =
topStoryService.buildJsonFeedString(topStoryMap);
//Logic to
send responce as Json File  to User 
 response.setContentType("text/json");
 OutputStream outPut =
response.getPortletOutputStream();
 outPut.write(jsonMap.getBytes());
 outPut.flush();
             }
Hope everyone understood what I am trying to do
out here.
Now the part from my business logic ,whats
important is the URl link ,what I have shared with client ,is very lengthy and
not user friendly to remember.
So I gone through some links which suggested me to
use different Url redirect techniques .
But I liked Liferay’s User Friendly Urls concept
,as the link which is shared is to a  3rd
party users and important thing here is I Don’t know in which page my portlet
is place to handle the such  request.
So I achieved the solution as below 
Created a simple xml file called  friendly-url-router.xml and placed it under same
package where my portlet class is written.
NOTE: If you try to place this xml
file under any other folder then Classes (any sub folders of classes) .It will
throw an Class loader Exception..

Here is my friendly-url-router.xml 
<?xml version="1.0"
encoding="UTF-8"?>
 
<!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>/json</pattern>  
<implicit-parameter name="p_p_id">topstorytopicpage_WAR_NewTopStoryportlet</implicit-parameter>  <implicit-parameter name="p_p_lifecycle">2</implicit-parameter>  
<implicit-parameter name="p_p_state">normal</implicit-parameter>  
<implicit-parameter name="p_p_mode">view</implicit-parameter>  
<implicit-parameter name="p_p_cacheability">cacheLevelPage</implicit-parameter>  
<implicit-parameter name="p_p_col_id">column-1</implicit-parameter>  
<implicit-parameter name="p_p_col_count">1</implicit-parameter>  
  
</route>  
 </routes> 
If you note ,I have given all the above parameter
values from the existing server resource Url i.e. 
 will change
to :  localhost:8080/web/guest/topicpage1/-/topstory-feed/json
Now you have defined your friendly Url xml , all
you need to do is register it with your portlet ,by adding a small piece of
code  in your liferay-portlet.xml file as
shown below.
<portlet>
<portlet-name>topstorytopicpage</portlet-name>
<icon>/icon.png</icon>
<friendly-url-mapper-class>com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper</friendly-url-mapper-class>  
<friendly-url-mapping>topstory-feed</friendly-url-mapping>  
<friendly-url-routes>com/client/nci/topstory/admin/controller/friendly-url-router.xml</friendly-url-routes>  
………………….………….
………………………………….
</portlet>
NOTE: In the above two file I have marked
<patter> and <friendly-url-mapping<friendly-url-mapping > RED in
colour .
Because these to will merge and
generate a Friendly URL  as shown below
/-/topstory-feed/json
Now this URL string when appended on any page of
the portal ,will call your portlet serveResource() and generate a JSON Response
file.
localhost:8080/web/guest/topicpage/-/topstory-feed/json
localhost:8080/web/guest/home/-/topstory-feed/json
You can try it on Any page .
That’s it ..
I have not gone in details about the parameter we
have written in FriendlyURLRouter Xml file .If you wish you want to understand
them here are the links I have gone through .