Liferay MVC Portlet Explaination
In
Liferay 6, the plugins SDK has been totally restrutctured. The ext environment
in now a plugin, and customizing( adding new fields) the core portlets of
Liferay is now not so easy as it was in LR5. The normal way most of us are
accustomed to creating a portlet was through the StrutsPortlet class which is
Liferay Struts bridge. But we cannot extend this class in the plugins SDK as
the StrutsPortlet class is packaged within the portal-impl.jar file, which is
not accessible in the plugins SDK.
Liferay has provided another
class called the MVCPortlet, which is Liferay MVC pattern class. When we create
a portlet in the Plugins SDK, the portlet that gets generated is
called the MVCPortlet. A look at portlet.xml file tells us that the
portlet class is defined as com.liferay.util.bridges.mvc.MVCPortlet. It
provides features like page management, automatic display of success messages,
automatically calling the appropriate action methods etc. and probably
many more. This class extends the LiferayPortlet class.
In order to do some useful work in our plugin, we need to create a new Portlet class that extends the MVCPortlet. The benefit of extending from MVCPortlet is that our portlet now becomes smaller and easier to work with.
In this post, we will look at how to create action methods without using annotations, how to forward to a jsp page, how to redirect to another jsp page(to prevent page refresh problems etc.,) .
Lets assume that our class is called "BookPortlet" which extends MVCPortlet.
This fact needs to be mentioned in portlet.xml file as
<portlet-class>com.bookstore.portlet.BookPortlet</portlet-class>
Creating the BookPortlet portlet class:
addBook.jsp
<portlet:actionURL name="addBook" var="addBookURL"/> A
Creating the BookPortlet portlet class:
addBook.jsp
<portlet:actionURL name="addBook" var="addBookURL"/> A
<aui:form action="<%= addBookURL.toString() %>" method="post"> B
<aui:fieldset>
<aui:input name="bookName" />
<aui:button-row>
<aui:button type="submit" />
</aui:button-row>
</aui:fieldset>
</aui:form>
<aui:input name="bookName" />
<aui:button-row>
<aui:button type="submit" />
</aui:button-row>
</aui:fieldset>
</aui:form>
BookPortlet.java
public class BookPortlet
extends MVCPortlet{
public void addBook(ActionRequest req, ActionResponse res) {
}
}
public void addBook(ActionRequest req, ActionResponse res) {
}
}
When
we click on the Submit button of the addBook.jsp page, it will automatically
hit the addBook() method of BookPortlet.
We achieve this as follows:
At (A) we create an action URL using the taglib. We assign a name to the URL using the name attribute of the <portletURL> tag. This name should correspond to the method name in the BookPortlet class.
There is no need to pass any request parameters that differentiate between various actions as we do in a Struts based portlet/ servlet, or use any annotation like @ProcessAction as we do when we inherit directly from GenericPortlet. MVCPortlet takes care of this for us.
In the addBook() method, we need to process all the input using req.getParameter("bookName"); ..and so on..and add the logic for adding the book into the database.
public class BookPortlet extends MVCPortlet{
public void addBook(ActionRequest
req, ActionResponse res) {
String bName = req.getParameter("bookName");
/* logic for adding a book*/
}
}
Forwarding to the view page:
String bName = req.getParameter("bookName");
/* logic for adding a book*/
}
}
Forwarding to the view page:
After adding any entity, we
would normally want to view the entity that we have added. This can be done as
follows using the response object.
res.setRenderParameter("jspPage","relative path to viewbook.jsp");
so our code would look like
public class BookPortlet extends MVCPortlet{
public void addBook(ActionRequest req, ActionResponse res) {
String bName = req.getParameter("bookName");
/* logic for adding a book*/
//will forward to the viewbook page
res.setRenderParameter("jspPage","relative path to viewbook.jsp");
}
}
The page management logic is handled through a render parameter called jspPage.
res.setRenderParameter("jspPage","relative path to viewbook.jsp");
so our code would look like
public class BookPortlet extends MVCPortlet{
public void addBook(ActionRequest req, ActionResponse res) {
String bName = req.getParameter("bookName");
/* logic for adding a book*/
//will forward to the viewbook page
res.setRenderParameter("jspPage","relative path to viewbook.jsp");
}
}
The page management logic is handled through a render parameter called jspPage.
The above code works fine,
but the last line does a simple forward, which has a small problem. The problem
is related to page refreshes, which can happen automatically or
accidentally. If the user adds a book and comes to the view page, and then does
a page refresh using the browser's refresh button, then a duplicate book
entity is added to the DB.
To prevent this, we need to do a redirect.
Redirection in MVCPortlet:
We perform a redirect operation, by creating a portletURL dynamically. This is done as follows.
To prevent this, we need to do a redirect.
Redirection in MVCPortlet:
We perform a redirect operation, by creating a portletURL dynamically. This is done as follows.
String portletName =
(String)actionRequest.getAttribute(WebKeys.PORTLET_ID);
(A)
PortletURL redirectURL = PortletURLFactoryUtil.create(PortalUtil.getHttpServletRequest(actionRequest),
porltetName,
themeDisplay.getLayout().getPlid(), PortletRequest.RENDER_PHASE); (B)
redirectURL.setParameter("jspPage", "relative path to viewbook.jsp");
redirectURL.setParameter("bookId", bookId);
actionResponse.sendRedirect(redirectURL.toString()); (C)
At (B), we generate the portletURL using the create() method of the class PortletURLFactoryUtil.
PortletURL redirectURL = PortletURLFactoryUtil.create(PortalUtil.getHttpServletRequest(actionRequest),
porltetName,
themeDisplay.getLayout().getPlid(), PortletRequest.RENDER_PHASE); (B)
redirectURL.setParameter("jspPage", "relative path to viewbook.jsp");
redirectURL.setParameter("bookId", bookId);
actionResponse.sendRedirect(redirectURL.toString()); (C)
At (B), we generate the portletURL using the create() method of the class PortletURLFactoryUtil.
This method signature
requires among others the portletName as a parameter. If we simply supply the
portlet name, as defined in the portlet.xml file, it does not work, as
intended. During runtime, Liferay assigns an instance ID to every portlet, and
this instance ID is suffixed to the portletName as portletName+ instanceID.
At (A), we get the portlet name + dynamic instance id stored in the variable portletName.
At (C) we call the sendRedirect method.
This will prevent the page refresh problem.
public class BookPortlet extends MVCPortlet{
At (A), we get the portlet name + dynamic instance id stored in the variable portletName.
At (C) we call the sendRedirect method.
This will prevent the page refresh problem.
public class BookPortlet extends MVCPortlet{
public void
addBook(ActionRequest req, ActionResponse res) {
String bName = req.getParameter("bookName");
/* logic for adding a book*/
//will forward to the viewbook page
//res.setRenderParameter("jspPage","relative path to viewbook.jsp");
//do redirect instead
String portletName = (String)actionRequest.getAttribute(WebKeys.PORTLET_ID);
String bName = req.getParameter("bookName");
/* logic for adding a book*/
//will forward to the viewbook page
//res.setRenderParameter("jspPage","relative path to viewbook.jsp");
//do redirect instead
String portletName = (String)actionRequest.getAttribute(WebKeys.PORTLET_ID);
PortletURL redirectURL =
PortletURLFactoryUtil.create(PortalUtil.getHttpServletRequest(actionRequest),
porltetName,
themeDisplay.getLayout().getPlid(), PortletRequest.RENDER_PHASE);
redirectURL.setParameter("jspPage", "relative path to viewbook.jsp");
redirectURL.setParameter("bookId", bookId);
actionResponse.sendRedirect(redirectURL.toString());
}
}
Liferay's MVC framework speeds up the development of portlets. Portlet classes are reduced to only action methods, because the framework handles page management. Hope this will get you started fast.
porltetName,
themeDisplay.getLayout().getPlid(), PortletRequest.RENDER_PHASE);
redirectURL.setParameter("jspPage", "relative path to viewbook.jsp");
redirectURL.setParameter("bookId", bookId);
actionResponse.sendRedirect(redirectURL.toString());
}
}
Liferay's MVC framework speeds up the development of portlets. Portlet classes are reduced to only action methods, because the framework handles page management. Hope this will get you started fast.
Hi Can you please help me
ReplyDeletehttp://www.liferay.com/community/forums/-/message_boards/message/22999878
Hi how do we set class object in setparameter for redirectURL
ReplyDelete