Liferay friendly URL using JSF

Goal

Implementing friendly URLs in Liferay using JSF

Description

This recipe explains the basic steps one has to take in order to implement friendly URLs for a JSF navigation model in Liferay

How to

In this recipe, we will implement a typical list/detail (of registered people in a system, for instance). The list page will present a table with the list of registered people and each table entry will have a link for its detail. We will see how to map the detail page in Liferay so that the URL will be something like -/people/person/view/1.

Before going into the recipe itself, bear in mind that we assume one single portlet named “PeoplePortlet” that will contain the functionalities to list and view the details of the registered people. In this implementation, we assume a list page named people.xhtml, and a detail page named person_detail.xhtml.

The recipe consists on the following steps:

  1. Define the Liferay friendly-url-* properties in the file liferay-portlet.xml
  2. Implement the friendly URL routes according to our needs

1 – The definition of the PeoplePortlet in liferay-portlet.xml:

<?xml version="1.0"?>
<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.1.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_1_0.dtd">

<liferay-portlet-app>
  <portlet>
    <portlet-name>PeoplePortlet</portlet-name>
    <friendly-url-mapper-class>
      com.liferay.portal.kernel.portlet.DefaultFriendlyURLMapper
    </friendly-url-mapper-class>
    <!-- The root name of the route -->
    <friendly-url-mapping>people</friendly-url-mapping>
    <!-- The file containing the routes definition -->
    <friendly-url-routes>
      com/linkare/myprojet/people/people-friendly-url-routes.xml
    </friendly-url-routes>
  </portlet>
  ...
</liferay-portlet-app>

2 – Definition of the friendly URL routes in the file people-friendly-url-routes.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE routes PUBLIC "-//Liferay//DTD Friendly URL Routes 6.1.0//EN"
"http://www.liferay.com/dtd/liferay-friendly-url-routes_6_1_0.dtd">
<routes>
  <route>
    <!-- 
         The URL we want to be used. Notice that we go to the detail page with a numeric parameter 
         named entityId which represents the primary key of the person whose details we want to see
    -->
    <pattern>/person/view/{entityId:\d+}</pattern>
    <ignored-parameter name="p_p_col_id" />
    <ignored-parameter name="p_p_col_count" />
    <implicit-parameter name="p_p_lifecycle">0</implicit-parameter>
    <implicit-parameter name="p_p_state">normal</implicit-parameter>
    <implicit-parameter name="p_p_mode">view</implicit-parameter>
    <!--
         The name of the JSF page that should be returned when we access this route
    -->
    <implicit-parameter name="_facesViewIdRender">/views/people/person_detail.xhtml</implicit-parameter>
  </route>
</routes>

And that is all we need to implement a pretty URL in Liferay using JSF.

Explanations

The most important explanations were made in place, as comments in the code. Also, the most relevant parts of the code were marked in bold. Nevertheless, notice the properties pattern and implicit-parameter with name “_facesViewIdRender” in the friendly-url-routes file, which are the most important parts. In the definition of parameters through implicit-parameters, we do not include them on the shown URL but we define its value, implicitly, leading us to the desired behaviour.

Advertisements

3 comments

  1. Hi Pablo, thanks for this recipe. I’ve a question, is entityId backingbean property or is a f:param sent from view, like as ? or how can I send this params?

    1. Hello Camilo,

      In my specific case, the entityId is a backing bean property and I have an implementation such as the following (only the most relevant details are shown here. Hope it answers your question):

      1 – the original page from which I create the link to the detail page:
      <h:link outcome=”project_detail”>
      <f:param name=”entityId” value=”#{project.projectId}” />
      <h:outputText value=”#{messages[‘button.details’]}” />
      </h:link>

      2 – The backing bean initialization code:

      @ManagedBean(name = “projectBean”)
      @ViewScoped
      public class ProjectBean implements Serializable {

      private Long entityId;

      private Project instance;

      @PostConstruct
      public void init() {
      try {
      // get long request parameter from request
      entityId = getLongRequestParameter(“entityId”);
      if (entityId == null) {
      throw new IllegalStateException(“The entity id parameter is required”);
      }
      this.instance = fetchInstance(entityId);
      } catch (Exception e) {
      throw new IllegalStateException(“Problems initializing bean”, e);
      }
      }

      @Override
      private Project fetchInstance(final Long entityId) throws SystemException {
      this.project = ProjectLocalServiceUtil.fetchProject(entityId);
      }

      public Long getEntityId() {
      return entityId;
      }

      public void setEntityId(Long entityId) {
      this.entityId = entityId;
      }

      public Project getInstance() {
      return project;
      }


      }

      And by the way, it’s Paulo, not Pablo 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s