tag:blogger.com,1999:blog-2424119574913004622024-03-13T17:05:51.725+05:30Apoorva's EmpiricismSeeking niche...Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.comBlogger67125tag:blogger.com,1999:blog-242411957491300462.post-91077329747285478332016-09-04T20:22:00.000+05:302016-09-04T20:22:00.153+05:30Liferay: A note on Portlet Namespace<div dir="ltr" style="text-align: left;" trbidi="on">
<b>Portlet namespace is a unique ID associated to each instance of the portlet provided by the portlet container.</b><br />
<b><br /></b>
When a team is working on a Liferay project, there are several portlets are created. From my experience, I have seen projects having 150+ portlets. So it’s very difficult to track the client side elements, such as JavaScript function, HTML elements IDs etc., which are being written by several developers. Portlet Namespace is a solution of the same. This tag returns the ID of the portlets which can prefixed with client side elements. This tag returns the ID of the portlet, with instance ID in case of instantiable portlet. Portlet Namespace can be used by several ways, to day we’ll see getting it by tag and PortletResponse object.<br />
<br />
Non Instantiable portlet’s ID:<br />
<i>_empiricismportlet_WAR_namespaceportlet_</i><br />
<i>_{Portlet WAR ID}_WAR_{Portlet ID}_</i><br />
<br />
Instantiable portlet<br />
<i>_empiricismportlet_WAR_namespaceportlet_INSTANCE_rwgp46_</i><br />
<i>_{Portlet WAR ID}_WAR_{Portlet ID}_INSTANCE_{random ID generated by Liferay}_</i><br />
<br />
<b>Usage of <span style="font-family: Courier New, Courier, monospace;"><portlet:namespace /></span></b><br />
<span style="font-family: Courier New, Courier, monospace;"><portlet:namespace /></span> gets converted to ID at the time of JSP’s conversion to class.<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<portlet:defineObjects />
<input type="text" id=”<portlet:namespace/>sampleParam” name="<portlet:namespace/>sampleParam">
<input type=”button” onClick=”<portlet:namespace/>getParamVal()” />
]]></script>
In JavaScript<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
function <portlet:namespace/>getParamVal(){
var sampleParam = $(‘#<portlet:namespace/>sampleParam’).val();
}
]]></script><br />
<br />
So internally the mark-up generated will be as follows:<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<input type="text" id=”_empiricismportlet_WAR_namespaceportlet_sampleParam” name="_empiricismportlet_WAR_namespaceportlet_sampleParam">
<input type=”button” onClick=”_empiricismportlet_WAR_namespaceportlet_getParamVal()” />
function _empiricismportlet_WAR_namespaceportlet_getParamVal(){
var sampleParam = $(‘#_empiricismportlet_WAR_namespaceportlet_sampleParam’).val();
}
]]></script><b>
Usage by PortletResponse</b><br />
<br />
Namespace can be obtained by any of the PortletResponse objects:<br />
<br />
<ol style="text-align: left;">
<li>renderResponse.getNamespace()</li>
<li>actionResponse.getNamespace()</li>
<li>resourceResponse.getNamespace()</li>
</ol>
<br />
<br />
for example, I’ll consider renderResponse object is available on the JSP<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<input type="text" id=”<%=renderResponse.getNamespace() %>sampleParam” name=”=”<%=renderResponse.getNamespace()%>sampleParam">
]]></script><br />
<br />
To conclude, both the approached are same however <span style="font-family: Courier New, Courier, monospace;"><portlet:namespace /></span> most preferred way. However second one is needed when you are in controller class, utility methods or TLDs.<br />
<br />
That’s all for today. Thanks for reading and have a nice day.</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.comBengaluru, Karnataka 560001, India12.9715987 77.59456269999998312.4764182 76.949115699999979 13.4667792 78.240009699999987tag:blogger.com,1999:blog-242411957491300462.post-39138990570968971572016-08-29T00:50:00.000+05:302016-08-29T00:50:01.454+05:30Liferay: Understanding theme:defineObjects<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
In the <a href="http://www.apoorvaprakash.in/2016/08/liferay-understanding-portlet-defineobjects.html" target="_blank">previous post</a>, we have gone through the implicit objects provided by <span style="font-family: "courier new" , "courier" , monospace;"><portlet:defineObjects/></span>. In the continuation, today we will go through the implicit objects provided by <span style="font-family: "courier new" , "courier" , monospace;"><theme:defineObjects /></span>.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<%@ taglib uri="http://liferay.com/tld/theme" prefix="theme" %>
<theme:defineObjects/>
]]></script>
Similar to <span style="font-family: "courier new" , "courier" , monospace;"><portlet:defineObjects/></span>, <span style="font-family: "courier new" , "courier" , monospace;"><theme:defineObjects /></span> is also an empty tag without any attribute, and must be included after the mentioned directive. Lets see the objects:</div>
<ol style="text-align: left;">
<li style="text-align: justify;"><b>ThemeDisplay themeDisplay</b> - contains attributes such as groupId, company id, user id, if the user is logged in, etc..</li>
<li style="text-align: justify;"><b>Company company</b> – Portal instance specific information</li>
<li style="text-align: justify;"><b>Account account</b> – current user’s account object</li>
<li style="text-align: justify;"><b>User user</b> – logged in user’s attributes</li>
<li style="text-align: justify;"><b>User realUser</b> – in case of impersonation, gets the logged in user’s id</li>
<li style="text-align: justify;"><b>Contact contact</b> – current user’s contact object</li>
<li style="text-align: justify;"><b>Layout layout</b> – current page attributes</li>
<li style="text-align: justify;"><b>List<Layout> layouts</b></li>
<li style="text-align: justify;"><b>long plid</b> - current portlet layout id</li>
<li style="text-align: justify;"><b>LayoutTypePortlet layoutTypePortlet</b> – object having information about portlets on the current layout</li>
<li style="text-align: justify;"><b>long scopeGroupId</b> – groupid of the current scope</li>
<li style="text-align: justify;"><b>PermissionChecker permissionChecker</b> – attributes regarding surrent user’s permission</li>
<li style="text-align: justify;"><b>Locale locale</b> – current user’s locale, determined by JVM</li>
<li style="text-align: justify;"><b>TimeZone timeZone</b> – current user’s timezone, determined by JVM</li>
<li style="text-align: justify;"><b>Theme theme</b> – attributes of current theme being rendered on the page</li>
<li style="text-align: justify;"><b>ColorScheme colorScheme</b> – attributes of the current colour scheme of the current theme</li>
<li style="text-align: justify;"><b>PortletDisplay portletDisplay</b> – attributes regarding name, ID, portlet mode etc.</li>
</ol>
<div style="text-align: justify;">
That’s all for today. Thanks for reading and have a nice day. </div>
<div style="text-align: justify;">
<br /></div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.comBengaluru, Karnataka 560001, India12.9715987 77.59456269999998312.4764182 76.949115699999979 13.4667792 78.240009699999987tag:blogger.com,1999:blog-242411957491300462.post-6663863312905459042016-08-28T00:01:00.000+05:302016-08-28T00:01:00.949+05:30Liferay: Understanding portlet:defineObjects<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
There is so much confusion about the implicit objects provided by <portlet:defineObjects/> tag on JSP as developers cannot see them easily. Experienced developers know what is available and they can use them freely. Here is a cheat sheet for the same.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<%@ taglib uri=”http://java.sun.com/portlet_2_0” prefix=”portlet”%>
<portlet:defineObjects/>
]]></script>
<span style="font-family: "courier new";"><portlet:defineObjects/></span> is an empty tag without any attribute, and must be included after the mentioned directive.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
JSR -286 (Portlet 2.0) have objects available from the following 13 objects, depending upon the origin of render, which lies in 3 categories:</div>
<div style="text-align: justify;">
<br /></div>
<ol style="text-align: left;">
<li style="text-align: justify;"><b>Request Objects</b></li>
<ol type="i">
<li style="text-align: justify;">RenderRequest – if the origin of request is from render phase</li>
<li style="text-align: justify;">ActionRequest - if the origin of request is from action phase</li>
<li style="text-align: justify;">ResourceRequest - if the origin of request is from ajax (serveResource)</li>
<li style="text-align: justify;">EventRequest - if the origin of request is from event (processEvent)</li>
</ol>
<li style="text-align: justify;"><b>Response Objects</b></li>
<ol type="i">
<li style="text-align: justify;">RenderResponse - if the origin of request is from render phase</li>
<li style="text-align: justify;">ActionResponse - if the origin of request is from action phase</li>
<li style="text-align: justify;">ResourceResponse - if the origin of request is from ajax (serveResource)</li>
<li style="text-align: justify;">EventResponse - if the origin of request is from event (processEvent)</li>
</ol>
<li style="text-align: justify;"><b>Portlet Objects</b></li>
<ol type="i">
<li style="text-align: justify;">PortletConfig</li>
<li style="text-align: justify;">PortletSession</li>
<li style="text-align: justify;">Map<String, Object> - contains list of all portletSessionAttributes</li>
<li style="text-align: justify;">PortletPreferences</li>
<li style="text-align: justify;">Map<String, String[]> - contains list of all portletPreferences</li>
</ol>
</ol>
<div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
That’s all for today. Thanks for reading and have a nice day.</div>
</div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.comBengaluru, Karnataka 560001, India12.9715987 77.59456269999998312.4764182 76.949115699999979 13.4667792 78.240009699999987tag:blogger.com,1999:blog-242411957491300462.post-15924704307382942892016-08-21T22:36:00.000+05:302016-08-21T22:36:00.173+05:30Liferay: A note of Liferay IPCs<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
Now as we have discussed about all 5 kinds of IPCs in Liferay, We should have some preference which one to use first.</div>
<div style="text-align: justify;">
Obviously Server Side IPC should be considered first, and then the client side implementations.</div>
<div style="text-align: justify;">
As per my understanding, following is the order of IPC mechanisms one should consider while implementing IPC.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
1. IPC via Server Side Events (Read <a href="https://www.blogger.com/Now%20as%20we%20have%20discussed%20about%20all%205%20kinds%20of%20IPCs%20in%20Liferay,%20we%20should%20have%20some%20preference%20which%20one%20to%20use%20first.%20%20Obviously%20Server%20Side%20IPC%20should%20be%20considered%20first,%20and%20then%20the%20client%20side%20implementations.%20As%20per%20my%20understanding,%20following%20is%20the%20order%20on%20IPC%20mechanism%20one%20should%20consider%20while%20implementing%20IPC.%20%20%20%20%20%201.IPC%20via%20Server%20Side%20Events%20(http://www.apoorvaprakash.in/2015/05/liferay-ipc-via-events.html)%202.IPC%20via%20Private%20Session%20Attributes%203.IPC%20via%20Public%20Render%20Parameters%20(http://www.apoorvaprakash.in/2015/05/liferay-public-render-parameters.html)%204.Client%20Side%20IPC%20via%20Events/Ajax%20%205.Client%20Side%20IPC%20via%20Cookies%20(http://www.apoorvaprakash.in/2016/08/im-starting-to-write-here-again-after.html)%20%20That%E2%80%99s%20all%20for%20today.%20Thanks%20for%20reading%20and%20have%20a%20nice%20day." target="_blank">here</a>)</div>
<div style="text-align: justify;">
2. IPC via Private Session Attributes (Read <a href="http://www.apoorvaprakash.in/2016/08/liferay-ipc-via-private-session.html" target="_blank">here</a>)</div>
<div style="text-align: justify;">
3. IPC via Public Render Parameters (Read <a href="http://www.apoorvaprakash.in/2015/05/liferay-public-render-parameters.html" target="_blank">here</a>)</div>
<div style="text-align: justify;">
4. Client Side IPC via Events/Ajax (Read <a href="http://www.apoorvaprakash.in/2016/08/liferay-client-side-ipc-via-eventsajax.html" target="_blank">here</a>)</div>
<div style="text-align: justify;">
5. Client Side IPC via Cookies (Read <a href="http://www.apoorvaprakash.in/2016/08/im-starting-to-write-here-again-after.html" target="_blank">here</a>)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
That’s all for today. Thanks for reading and have a nice day.</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.comBengaluru, Karnataka 560001, India12.9715987 77.59456269999998312.4764182 76.949115699999979 13.4667792 78.240009699999987tag:blogger.com,1999:blog-242411957491300462.post-86485424661996954742016-08-20T16:30:00.000+05:302016-08-20T23:43:12.177+05:30Liferay: IPC via Private Session Attributes<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
Every portlet WAR has a session associated with it. A portlet session is a java object. This session object can be used for sharing data between portlets and achieving IPC. So this article will explain IPC via portlet session.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
To understand Portlet sessions, we have to understand session scope of the session object. There are two scopes – PORTLET_SCOPE and APPLICATION_SCOPE. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The data stored in the PortletSession of a portlet is not shared with any other portlets on the page, or anywhere else in the portal. This default behaviour is known as PORTLET_SCOPE. With the JSR-168(Portlet 1.0) portlet specification, concept of APPLICATION_SCOPE was introduced, and is available in its successor JSR-286(Portlet 2.0) which gives data access to all the portlets of the same WAR.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Let’s see the snippets:</div>
<div style="text-align: justify;">
<b>Portlet 1: Setting Attributes:</b></div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletSession portletSession = renderRequest.getPortletSession();
// Application Scope
portletSession.setAttribute("appParam","I’m Sample App Scope Param Value", PortletSession.APPLICATION_SCOPE);
// Portlet Scope
portletSession.setAttribute("portletParam"," I’m Sample Portlet Scope Param Value ", PortletSession.PORTLET_SCOPE);
]]></script>
<br />
<b>Portlet 2: Fetching Attributes:</b></div>
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletSession portletSession = renderRequest.getPortletSession();
// Application Scope
String appParam = (String) session.getAttribute("appParam", PortletSession.APPLICATION_SCOPE);
// Portlet Scope
String portletParam = (String) session.getAttribute("portletParam", PortletSession.PORTLET_SCOPE);
]]></script>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Portlet session attributes can be removed also, using the following:</div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletSession portletSession = renderRequest.getPortletSession();
portletSession .removeAttribute("appParam")
portletSession .removeAttribute("portletParam ", PortletSession.PORTLET_SCOPE);
]]></script>
Please note that both methods are interchangeable.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Liferay further provide feature for sharing portlet session attributes with portlet from other WARs. For achieving the same, we have to set <span style="font-family: Courier New, Courier, monospace;"><private-session-attributes></span> to false in liferay-portlet.xml.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
That’s all for today. Thanks for reading and have a nice day. </div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.comBengaluru, Karnataka 560001, India12.9715987 77.59456269999998312.4764182 76.949115699999979 13.4667792 78.240009699999987tag:blogger.com,1999:blog-242411957491300462.post-59818913187852635912016-08-15T16:46:00.000+05:302016-08-20T23:43:59.469+05:30Liferay: Client Side IPC via Events/Ajax<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
Client Side IPC using Ajax is another way of achieving communicating between portlets from client size. This mechanism was introduced in JSR-286 (Portlet 2.0) specification and provides a very lightweight and decoupled mechanism to communicate portlets purely in the browser through a JavaScript events mechanism.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The API of this system is very simple and is based on two methods</div>
<div style="text-align: justify;">
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[Liferay.fire(eventName, data);]]></script>
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
Liferay.on(eventName, function, [scope]);
]]></script>
Prerequisite for this includes - setting <requires-namespaced-parameters> to false, in liferay-portlet.xml file of the both the portlets, which makes allows to share data via Ajax call and adding both the portlets in the same page after deployment.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Let’s see some snippets:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>Portlet 1: JS code for setting params</b></div>
<div style="text-align: justify;">
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<portlet:resourceURL var="setParamsViaAjax" />
$(document).on('ready',function(){
var param1 = "I'm a sample value of Param 1";
var param2 = "I'm a sample value of Param 2";
$.ajax({
url:'<portlet:resourceURL var="setParamsViaAjax" />',
dataType: "json",
data:{param1: param1, param2: param2},
type: "get",
success: function(data){
Liferay.fire('setParamsViaAjax', {eventData: data});
},
complete: function(){
alert('Success');
},
error: function(){
alert(Some 'Error');
}
});
});
]]></script><br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b>Portlet 2: JS code for fetching the Params</b></div>
<div style="text-align: justify;">
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
Liferay.on('setParamsViaAjax', function(event) {
alert("Param 1: " + event.eventData.param1);
alert("Param 2: " + event.eventData.param2);
});
]]></script><br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
That’s all for today. Thanks for reading and have a nice day.</div>
<div>
<div style="text-align: justify;">
<br /></div>
</div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.comBengaluru, Karnataka 560001, India12.9715987 77.59456269999998312.4764182 76.949115699999979 13.4667792 78.240009699999987tag:blogger.com,1999:blog-242411957491300462.post-2113886897047771522016-08-13T13:05:00.003+05:302016-08-20T23:45:10.382+05:30Liferay: Client Side IPC via Cookies<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="MsoNormal" style="background: white; margin: 9pt 0cm;">
<div style="text-align: justify;">
<span style="font-family: "arial" , sans-serif;"><span style="font-size: 13.3333px; line-height: 24px;">I’m starting to write here again after long time. I was keeping busy while working on ReactJS and it’s integration with Liferay. However, I’m here continuing from where I left and will start about ReactJs and its integration with Liferay soon. </span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "arial" , sans-serif;"><span style="font-size: 13.3333px; line-height: 24px;">In the previous two posts we’ve seen IPC via Public Render Parameter and Server Side Events. Today I’ll write about Client Side IPC at using Cookies. As IPC via Public Render Parameters and Server Side Events, this concept was also introduced in JSR 286.</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "arial" , sans-serif;"><span style="font-size: 13.3333px; line-height: 24px;">Important point to note about Client Side IPC via Cookies is that we cannot have information stored/shared more than 4096 bytes in size, as this is the maximum size of a cookie allowed by browsers and maximum number of cookies allowed, varies browser to browser; which is, for example, 20 in case of IE and 600 in case of Safari Mobile. (You can read details <a href="http://browsercookielimits.squawky.net/" target="_blank">here</a>)</span></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "arial" , sans-serif;"><span style="font-size: 13.3333px; line-height: 24px;">The scenario we’ll see here in snippet will be: creating the cookie in Portlet 1 and reading the same in portlet 2. I’m keeping name of the cookie ‘sampleIPCCookie’ for example.</span></span></div>
<div style="text-align: justify;">
<span style="font-family: "arial" , sans-serif;"><span style="font-size: 13.3333px; line-height: 24px;">Setting/Getting the cookie can be done by either of the method - server side (Java/JSP etc.) or client side (Javascript/JQuery etc.). Here I am writing example using of Javascript.</span></span></div>
<br />
<div style="text-align: justify;">
<span style="font-family: "arial" , sans-serif; font-size: 13.3333px; line-height: 24px;">Let’s go and see the snippets.</span></div>
<span style="font-family: "arial" , sans-serif; font-size: 13.3333px; line-height: 24px; text-align: justify;"><b>Portlet 1: Setting the cookie </b></span><br />
<br />
<span style="font-family: "arial" , sans-serif; font-size: 13.3333px; line-height: 24px; text-align: justify;"><b><br /></b></span>
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
function setIPCCookie() {
document.cookie = "sampleIPCCookie=I'm a sample IPC value";
}
]]></script>
<span style="font-family: "arial" , sans-serif; font-size: 13.3333px; line-height: 24px; text-align: justify;"><b>Portlet 2: Fetching the cookie value in another portlet.</b> </span><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
function getIPCCookie() {
var cookies = "; " + document.cookie;
var keyValues = cookies.split(";sampleIPCCookie=");
if (keyValues.length == 2)
return keyValues.pop().split(";").shift();
else
return '';
}
]]></script>
<span style="font-family: "arial" , sans-serif; text-align: justify;"><span style="font-size: 13.3333px; line-height: 24px;">Client Side IPC via cookies is not a best practice of IPC and should be considered as the last option for implementing IPC. If it is very necessary to implement IPC at client side, one should first consider Client Side Events (</span></span><span style="font-family: "arial" , sans-serif; font-size: 13.3333px; line-height: 24px; text-align: justify;">which we’ll see in the next post)</span><span style="font-family: "arial" , sans-serif; font-size: 13.3333px; line-height: 24px; text-align: justify;"> before considering this mechanism.</span><br />
<br />
<span style="font-family: "arial" , sans-serif; font-size: 13.3333px; line-height: 24px; text-align: justify;">That’s all for today. Thanks for reading and have a nice day.</span></div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.comBengaluru, Karnataka 560001, India12.9715987 77.59456269999998312.4764182 76.949115699999979 13.4667792 78.240009699999987tag:blogger.com,1999:blog-242411957491300462.post-57484318012724086232015-05-31T10:08:00.000+05:302016-08-13T13:13:26.232+05:30Liferay: IPC via Server Side Events<div dir="ltr" style="text-align: left;" trbidi="on">
IPC (Inter Portlet Communication) in Liferay can be implemented in different ways and I've already written an article on Public render parameter mechanism. In this article, we'll see Event based IPC. As Public Render Parameters, this concept was also introduced in JSR 286.<br />
<br />
As per IPC using Events, portlet can publish/send and process/receive the event. This mechanism works flawlessly with inter and intra WARs.<br />
<br />
1. Event deceleration in Event Publisher Portlet's portlet.xml<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<supported-public-render-parameter>
sampleParam
</supported-public-render-parameter>
]]></script>
Full portlet.xml will look like as follows:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<?xml version="1.0"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">
<portlet>
<portlet-name>event-publisher</portlet-name>
<display-name>Event Publisher</display-name>
<portlet-class>com.apoorvaprakash.eventpublisher.controller.EventPublisherController</portlet-class>
<init-param>
<name>view-template</name>
<value>/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<portlet-info>
<title>Event Publisher</title>
<short-title>Event Publisher</short-title>
<keywords>Event Publisher</keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
<supported-publishing-event>
<qname xmlns:x="http://apoorvaprakash.in/events">x:sampleParam</qname>
</supported-publishing-event>
</portlet>
</portlet-app>
]]></script>
<br />
2. Event definition in Event Receiver Portlet's portlet.xml<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<supported-processing-event>
<qname xmlns:x="http://apoorvaprakash.in/events">x:sampleParam</qname>
</supported-processing-event>
]]></script>
Full portlet.xml will look like as follows:
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<?xml version="1.0"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">
<portlet>
<portlet-name>event-processor</portlet-name>
<display-name>Event Processor</display-name>
<portlet-class>com.apoorvaprakash.eventprocessor.controller.EventProcessorPortlet</portlet-class>
<init-param>
<name>view-template</name>
<value>/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<portlet-info>
<title>IPC Event Receiver</title>
<short-title>IPC Event Receiver</short-title>
<keywords>IPC Event Receiver</keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
<supported-processing-event>
<qname xmlns:x="http://apoorvaprakash.in/events">x:sampleParam</qname>
</supported-processing-event>
</portlet>
</portlet-app>
]]></script>
<br />
3. Event Publishing Portlet's Controller Class<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.apoorvaprakash.eventpublisher.controller;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.ProcessAction;
import javax.xml.namespace.QName;
import com.liferay.util.bridges.mvc.MVCPortlet;
/**
* @author apoorva.prakash
*/
public class EventPublisherController extends MVCPortlet{
@ProcessAction(name="publishEvent")
public void process(ActionRequest request, ActionResponse response) {
QName qName = new QName("http://apoorvaPrakash.in/events", "sampleParam");
response.setEvent(qName, "Custom Param Value");
}
}
]]></script>
<br />
Invoking Publish Event method<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<portlet:actionURL var="publishEventUrl" name="publishEvent"/>
<aui:form method="post" action="<%=publishEventUrl.toString() %>">
<aui:button type="submit" value="Send"/>
</aui:form>
]]></script>
<br />
4. Event Processing Portlet's Controller Class and fethching parameter's value<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.apoorvaprakash.eventprocessor.controller;
import javax.portlet.Event;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.ProcessEvent;
import com.liferay.util.bridges.mvc.MVCPortlet;
/**
* @author apoorva.prakash
*/
public class EventProcessorPortlet extends MVCPortlet {
@ProcessEvent(qname = "{http://apoorvaprakash.in/events}sampleParam")
public void sampleEvent(EventRequest request, EventResponse response) {
Event event = request.getEvent();
//fetching the value of the param, sent via event
String paramValue = (String)event.getValue();
System.out.println("Event Param Value: " + paramValue )
}
}
]]></script>
Note: 'QName' is a nothing but a qualified name of the parameter. Usage of QName minimizes chances of having two identical events.
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com1tag:blogger.com,1999:blog-242411957491300462.post-24331963397137110562015-05-30T18:39:00.000+05:302015-07-11T00:57:40.647+05:30Liferay: IPC using Public Render Parameters<div dir="ltr" style="text-align: left;" trbidi="on">
IPC (Inter Portlet Communication) in Liferay can be implemented in different ways and we'll see one among the possibilities, i.e. Public Render Parameter. This concept was introduced in JSR 286.<br />
<br />
The central idea of this concept is to share a normal parameter across all deployed portlets despite of the fact that they lie in same WAR or in different.<br />
<br />
1. In <i>portlet.xml</i> in the end of <i></portlet></i> tag we have to define the name of parameter<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<supported-public-render-parameter>
paramName
</supported-public-render-parameter>
]]></script>
<br />
2. In <i>portlet.xml</i> in the end of <i><portlet-app></i> tag we have to define the identifier with the name of parameter<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<public-render-parameter>
<identifier>paramName</identifier>
<qname xmlns:x="http://apoorvaprakash.in/public">x:paramName</qname>
</public-render-parameter>
]]></script>
<br />
Full <i>portlet.xml</i> file will look like as follows:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<?xml version="1.0"?>
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0">
<portlet>
<portlet-name>hello-world-portlet</portlet-name>
<display-name>hello-world-portlet</display-name>
<portlet-class>com.liferay.util.bridges.mvc.MVCPortlet</portlet-class>
<init-param>
<name>view-template</name>
<value>/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<portlet-info>
<title>Hello World</title>
<short-title>Hello World</short-title>
<keywords>Hello World</keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
<supported-public-render-parameter>
myname
</supported-public-render-parameter>
</portlet>
<public-render-parameter>
<identifier>paramName</identifier>
<qname xmlns:x="http://apoorvaprakash.in/public">x:paramName</qname>
</public-render-parameter>
</portlet-app>
]]></script>
<br />
Setting Parameter:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
response.setRenderParameter("paramName", "value of the parameter");
]]></script>
<br />
Reading Parameter:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
String paramValue1 = ParamUtil.getString(request, "paramName")
String paramValue2 = renderRequest.getParameter("paramName");
]]></script>
<br />
Note: If render parameters need to be shared among two different WARs, and you have to set parameter in portlet 1 and read in portlet 2, For achieving this, we have to add definition of render parameter in the <i>portlet.xml</i> file of both the WARs. </div>Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com0tag:blogger.com,1999:blog-242411957491300462.post-7303027687940889372014-10-11T22:09:00.000+05:302014-10-11T22:10:37.353+05:30Liferay: Instance Specific 'portal.properties' File<div dir="ltr" style="text-align: left;" trbidi="on">
To start with this topic, we need to refresh the following:<br />
<br />
<b>Portal-ext.properties</b><br />
Everybody who works with Liferay, know about portal-ext.properties file. Just to refresh, this file contains key-value pairs of settings and is present in the classpath to override the properties of portal.properties file (can be seen in Liferay source code or portal-impl.jar).<br />
<br />
<b>Liferay Portal Instance</b><br />
Liferay Portal allows you to run more than one portal instance on a single server (e.g. tomcat instance). The Portal Instances page of the control panel lets you manage these instances. All portal data, however, is kept in the same database. (You can read in details here)<br />
<br />
As a standard practice, the settings we do in portal-ext.properties file are shared among all portal instances. But with the settings we are now going to discuss will allow us to create different property files for each portal instance, and this is out of box only. To do so, we have to do the following two settings:<br />
<br />
1. There are two ways of doing this, first you can set the following property in your system.properties file<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[-Dcompany-id-properties=true]]></script><br />
or you can set this in your setenv.bat or setenv.sh as per your environment. You can enter the above entry just after '-Duser.timezone=IST' in the file.<br />
<br />
2. Now we have to create properties file with the naming format 'portal-<<WebId>>.properties'. For instance, if the web id of the instance is 'finance', then the name of the property file for this instance will be portal-finance.properties.<br />
<br />
Similarly we can create different property files for other portal instances. The default web id of liferay instance is 'liferay', so the name of property file for this instance will be 'portal-liferay.properties'.<br />
<br />
Important things to note here is - not all properties can be overridden by this setting. Properties such as database configurations should be in the property file of default instance only.<br />
<br />
For testing this, you can try to modify the authentication method. Change the value to screen name in the second instance's properties file while keeping the email (as default come bundled), you will get the second instance authenticating with screen name while the first with email address. It also works well while fetching the values using PropsUtil API. </div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com2tag:blogger.com,1999:blog-242411957491300462.post-65829154654939019192014-08-02T12:39:00.001+05:302014-08-05T08:21:50.801+05:30Liferay:Quick Reference to Asynchronous Message Bus<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="MsoNormal">
There are needs in practical scenario when it’s needed to do some huge processing in the background. It’s like some command is given to do something, while the application is not waiting for the response, such as sending bulk emails, handling scheduler’s requests, processing some data etc. Asynchronous message bus is great way to achieve this kind of requirement in Liferay.<br />
<br />
The Message Bus is a mechanism for sending message payloads to different components in Liferay, providing loose coupling between message producers and consumers to prevent class loading issues. It’s located in the global class loader, making it accessible to every deployed web application. Remote messaging isn’t supported, but messages are sent across a cluster when ClusterLink is enabled.<br />
<br />
Following are the message bus components which we'll use while implementing it:<br />
<ol style="text-align: left;">
<li><b>Message Bus:</b> Manages transfer of messages from message senders to message listeners.</li>
<li><b>Destinations</b>: Addresses or endpoints to which listeners register to receive messages.</li>
<li><b>Listeners:</b> Consume messages received at destinations. They receive all messages sent to their registered destinations.</li>
<li><b>Senders:</b> Invoke the Message Bus to send messages to destinations.</li>
</ol>
We have to follow the steps given below, to create a message bus in Liferay:<br />
<br />
<b>Step 1:</b> First of all we need to create <i>messaging-spring.xml</i> in /src/META-INF of your plug-in portlet. If you don’t have a service builder in the portlet, then you won't be having this META-INF folder, in that case you have to create a dummy service for the same. Now we have to put the following contents in this file:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<?xml version="1.0"?>
<beans
default-destroy-method="destroy"
default-init-method="afterPropertiesSet"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Listeners -->
<bean id="liferay.async.bus.example" class="com.apoorva.asyncbus.SampleMsgListnerImpl" />
<!-- Destinations -->
<bean id="liferay.async.bus.destination" class="com.liferay.portal.kernel.messaging.SerialDestination">
<property name="name" value="liferay/asyncbus/example/destination" />
</bean>
<!-- Configurator -->
<bean id="messagingConfigurator" class="com.liferay.portal.kernel.messaging.config.PluginMessagingConfigurator">
<property name="messageListeners">
<map key-type="java.lang.String" value-type="java.util.List">
<entry key="liferay/asyncbus/example/destination">
<list value- type="com.liferay.portal.kernel.messaging.MessageListener">
<ref bean="liferay.async.bus.example" />
</list>
</entry>
</map>
</property>
<property name="destinations">
<list>
<ref bean="liferay.async.bus.destination"/>
</list>
</property>
</bean>
</beans>
]]></script>
<br />
<br />
<b>Step 2:</b> Now we have to make entry of this file in spring config. To do so, we have to open the service.properties file and make the entry of this file in "spring.configs" property.<br />
<br />
<b>Step 3:</b> What remains wow is to create a class which should process the messages. This class must inherit the class MessageListener and should also implement method receive. (Please help yourself with proper imports)<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.apoorva.asyncbus;
public class SampleMsgListnerImpl implements MessageListener {
public void receive(Message message) {
try {
_log.info("inside message listner...");
String sampleParam1 = (String)message.get("sampleParam1");
String sampleParam2 = (String)message.get("sampleParam2");
_log.info("sampleParam1: " + sampleParam1);
_log.info("sampleParam2: " + sampleParam1);
}
catch (Exception e) {
_log.error("Unable to process message " + message, e);
}
}
private static Log _log =
LogFactoryUtil.getLog(SampleMsgListnerImpl.class);
}
]]></script>
<br />
<br />
<b>Step 4:</b> All set, now use the following code invoke this listener from your code from action class, scheduler etc. from wherever you want.<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
try {
Message message = new Message();
message.put("sampleParam1", "Hello");
message.put("sampleParam2", "World!");
MessageBusUtil.sendMessage("liferay/asyncbus/example/destination", message);
}catch(Exception e){
_log.error("Exception in invoking message: " + e);
}
]]></script>
<br />
Thanks for reading.<br />
<br />
Ref: <a href="https://www.liferay.com/documentation/liferay-portal/6.1/development/-/ai/lp-6-1-dgen09-using-message-bus-0" target="_blank"> Liferay Message Bus</a><br />
<div>
<br /></div>
</div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com0tag:blogger.com,1999:blog-242411957491300462.post-79699083768925010752014-04-05T21:39:00.000+05:302014-04-05T23:38:17.064+05:30Liferay: Connecting Portlet to an External Database Table<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Sometimes we need to fetch data from two different databases in one project. There are several approaches, such as creating a new hibernate/spring session or fetching through web services. Both have their advantage and disadvantages. This article explains how we can create another session for fetching data from a database which is not configured as the portal's default database, but as some other (custom).<br />
The problem with this approach is with the table creation, which is Liferay's obvious behavior. Why? I'll explain this in the end of this article.<br />
<br />
1. First of all, create a new portlet with a service.xml file. Now build the service. For example, we create the following service. Here we need to know that the <i>data-source</i> value specifies the target data source which is the persistence class. The <i>session-factory</i> value specifies the session factory which is also set to the persistence class.The <i>tx-manager</i> value specifies the transaction manager which is used by Spring services. Rest of the things are pretty standard.<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<service-builder package-path="org.apoorva.prakash">
<author>apoorva.prakash</author>
<namespace>apoorva</namespace>
<entity name="Enq" local-service="true" remote-service="false" data-source="externalDataSource" session-factory="externalSessionFactory" tx-manager="externalTransactionManager">
<!-- PK field -->
<column name="enqId" type="long" primary="true" />
<!-- Other fields -->
<column name="salutation" type="String" />
<column name="fullName" type="String" />
<!-- Order -->
<order by="asc">
<order-column name="fullName"></order-column>
</order>
</entity>
</service-builder>
]]></script></div>
<br />
2. As we have built the service, Now its time to create table in the external database we're going to connect our portlet.<br />
<br />
3. Now we have to supply the database connection details to our code. We can hardcode the database connection details directly in XML file directly, but its handy if use the approach Liferay uses, i.e. through property file. So, lets just create some custom entries in portal-ext.properties file, not to mention you have to change the connection details as per your's:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
jdbc.external.driverClassName=com.mysql.jdbc.Driver
jdbc.external.url=jdbc:mysql://localhost/externalPortalDB?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
jdbc.external.username=root
jdbc.external.password=abc123]]></script>
4. As connection details now available, we have to use them to create a new session. So, for this we have to do spot the spring-ext.xml file which gets generated as soon as we build the service. The path of this file is: \docroot\WEB-INF\src\META-INF. We have to add the following entries in the end of this file:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[<bean id="externalSessionFactory" class="com.liferay.portal.spring.hibernate.PortletHibernateConfiguration" lazy-init="true">
<property name="dataSource" ref="externalDataSource" />
</bean>
<bean id="externalSessionFactory" class="com.liferay.portal.dao.orm.hibernate.SessionFactoryImpl" lazy-init="true">
<property name="sessionFactoryImplementor" ref="externalSessionFactory" />
</bean>
<bean id="externalTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" lazy-init="true">
<property name="dataSource" ref="externalDataSource" />
<property name="globalRollbackOnParticipationFailure" value="false" />
<property name="sessionFactory" ref="externalSessionFactory" />
</bean>
<bean id="externalDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource">
<bean class="com.liferay.portal.dao.jdbc.util.DataSourceFactoryBean">
<property name="propertyPrefix" value="jdbc.external." />
</bean>
</property>
</bean>
]]></script>
Now we are done. We can now simple write LocalServiceInple code to access data from external database's table.<br />
<br />
For the security reason, Liferay does not allow to create new table ontside the default DB. If you want to analyze liferay SRC, you can see the ServiceBuilder class's _createSQLTables method, where there is a condition check for default database.<br />
<br />
You can download sample portlet from <a href="https://dl.dropboxusercontent.com/u/30117816/Blog-Examples/Portlet%20for%20connecting%20two%20databases%20in%20liferay/yahoo-portlet.rar" target="_blank">here</a>. Hope this article will help you.
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com4tag:blogger.com,1999:blog-242411957491300462.post-25106921469896007232013-08-15T13:30:00.000+05:302013-08-21T15:37:11.241+05:30A Note of Liferay Portlet URLs<div dir="ltr" style="text-align: left;" trbidi="on">
In a portlet, we get our code executed by two ways - at the time of rendering of the portlet and another on some action which is generally a form submit or some event. For getting the same done, we have three different URLs in Liferay:<br />
<ol style="text-align: left;">
<li><b>Render URL</b> (which is portlet URL and responsible for rendering of the portlet and in typical MVC portlet, the code of method doView() is executed)</li>
<li><b>Action URL</b> (which is also portlet URL and responsible for performing some action with page reload and in typical MVC portlet, the code method processAction() is executed, and is followed by renderRequest)</li>
<li><b>Resource URL</b> (which is NOT a portlet URL but it extends the same base URL, is responsible for performing some action without page reload i.e. Ajax and in typical MVC portlet, the code of method serveResource() is executed and is NOT followed bt render request, Resource Serving was not available in JSR168 but its avaible in JSR286.</li>
</ol>
We can create these URL mainly by four approaches:
<br />
<ol style="text-align: left;">
<li>Using TagLib</li>
<li>Using Java</li>
<li>Using Javascript (AUI)</li>
<li>Using Velocity</li>
</ol>
<br />
Now we'll see how we can create these three type of URLs with the above four approaches considering that you have done all necessary imports:<br />
<br />
<b><u>1. Using Taglib</u></b><br />
<br />
<b>Render URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<portlet:renderURL windowState="<%=WindowState.MAXIMUM.toString()%>" name="renderURL" var="renderURL">
<portlet:param name="message" value="Hello World"/>
</portlet:renderURL>
]]></script>
here we are setting the window state of the portlet to maximum and a custom parameter(message).<br />
<b>Action URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<portlet:actionURL windowState="<%=WindowState.MAXIMUM.toString()%>" name="actionURL" var="actionURL">
<portlet:param name="message" value="Hello World"/>
</portlet:actionURL>
]]></script>
<b>Resource URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<portlet:resourceURL var="resourceUrl" id="resourceUrl"></portlet:resourceURL>
]]></script>
<b><u><br /></u></b>
<b><u>2. Using Java</u></b><br />
<br />
<b>Render URL:</b><br />
<i>Using RenderResponse:</i><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletURL renderURL = renderResponse.createRenderURL();
renderURL.setWindowState(WindowState.MAXIMIZED);
renderURL.setParameter("param", "value");
]]></script>
<i>Using PortletUrlFactory:</i><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletURL renderURL = PortletURLFactoryUtil.create(renderRquest,
themeDisplay.getPortletDisplay().getId(),themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
renderURL.setWindowState(WindowState.MAXIMIZED);
renderURL.setParameter("param", "value");
]]></script>
<b>Action URL:</b><br />
<i>Using RenderResponse:</i><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletURL actionUrl = renderResponse.createActionURL();
renderURL.setWindowState(WindowState.NORMAL);
renderURL.setParameter("param", "value");
]]></script>
<br />
<i>Using PortletUrlFactory:</i><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletURL actionUrl = PortletURLFactoryUtil.create(renderRquest,
themeDisplay.getPortletDisplay().getId(), themeDisplay.getPlid(), PortletRequest.ACTION_PHASE);
actionUrl.setWindowState(WindowState.NORMAL);
actionUrl.setParameter("param", "value");
]]></script>
<b>Resource URL:</b><br />
<i>Using RenderResponse:</i><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletURL resourceUrl = renderResponse.createResourceURL();
resourceUrl.setParameter("param", "value");
resourceUrl.setResourceID("resourceRequest");
]]></script>
<i>Using PortletUrlFactory:</i><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
PortletURL resourceUrl = PortletURLFactoryUtil.create(renderRquest,
themeDisplay.getPortletDisplay().getId(), themeDisplay.getPlid(), PortletRequest.RESOURSE_PHASE);
actionUrl.setParameter("param", "value");
]]></script>
<b><u><br /></u></b>
<b><u>3. Using Javascript (AUI)</u></b><br />
<b>Render URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
function getRenderUrl() {
AUI().ready('liferay-portlet-url', function(a) {
var renderUrl = Liferay.PortletURL.createRenderURL();
});
}
]]></script><br />
<b>Action URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
function getActionUrl() {
AUI().ready('liferay-portlet-url', function(a) {
var actionUrl = Liferay.PortletURL.createActionURL();
});
}
]]></script><br />
<b>Resource URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
function getActionUrl() {
AUI().ready('liferay-portlet-url', function(a) {
var resourceUrl = Liferay.PortletURL.createResourceURL();
});
}
]]></script><br />
The following can be set on these portlet URL methods:<br />
<ul style="text-align: left;">
<li>setCopyCurrentRenderParameters: function(copyCurrentRenderParameters);</li>
<li>setDoAsUserId: function(doAsUserId);</li>
<li>setEncrypt: function(encrypt);</li>
<li>setEscapeXML: function(escapeXML);</li>
<li>setLifecycle: function(lifecycle);</li>
<li>setName: function(name);</li>
<li>setParameter: function(key, value);</li>
<li>setPlid: function(plid);</li>
<li>setPortletConfiguration: function(portletConfiguration);</li>
<li>setPortletId: function(portletId);</li>
<li>setPortletMode: function(portletMode);</li>
<li>setResourceId: function(resourceId);</li>
<li>setSecure: function(secure);</li>
<li>setWindowState: function(windowState);</li>
<li>toString: function();</li>
</ul>
<br />
<b style="text-decoration: underline;">4. Using velocity:</b> Here we have to replace correct portletId and plid for getting the URL generated correctly.<br />
<b>Render URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
#set ($renderUrl = $portletURLFactory.create($request,"portlet ID","plid","RENDER_PHASE"))
$renderUrl.setParameter("param", "value")]]></script>
<b>Action URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
#set ($actionUrl = $portletURLFactory.create($request,"portlet ID","plid","ACTION_PHASE"))
$actionUrl.setParameter("param", "value")]]></script>
<b>Resource URL:</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
#set ($resourseUrl = $portletURLFactory.create($request,"portlet ID","plid","RESOURSE_PHASE"))
$resourseUrl.setParameter("param", "value")]]></script>
Hope you enjoyed the read.</div>Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com6tag:blogger.com,1999:blog-242411957491300462.post-14741388922156496582013-07-23T01:00:00.000+05:302013-07-23T11:01:13.308+05:30A Note of Liferay Portal Instances<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
Liferay provides us facility to run more than one portal instance on a single server. Liferay comes with one inbuilt portal instance, which is names 'Liferay' and its web id is 'liferay.com', however it can be modified with following properties in portal-ext.properties file:</div>
<div style="text-align: justify;">
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
company.default.name=Liferay
company.default.web.id=liferay.com
]]></script>
Note: There are several other properties regarding portal instances present in portal.properties as well which can be referred in Liferay Portal SRC.</div>
<br />
<div style="text-align: justify;">
If we login as administrator (generally test@liferay.com), and go to control panel we can see list of all available portal instances in 'Portal Instances' section inside 'Server' category. Here we will see a table with atlest one entry (inbuilt one) , lets know what the column of this table depicts:</div>
<br />
<ul style="text-align: left;">
<li><b>Instance ID:</b> It’s a numeric Id, generated by code automatically at the time of Instance creation. Internally this Instance ID is referred as 'companyid' in the database table. We can see all available instances in database table 'company'.</li>
<li><b>Web ID:</b> It’s a user-generated ID for the instance. It can be anything relevant but a general convention is to use the domain name.</li>
<li><b>Virtual Host:</b> Domain name which is to be configured in the network kept here. This domain name is referred when users are directed to our Liferay server, and the same enables Liferay to resolve request for proper portal instance.</li>
<li><b>Mail Domain:</b> The domain name to be used as mail host for this instance kept here. Liferay will use this to send email notifications from the portal, and the same is used for creating the default test user, as test@mail-domain.com</li>
<li><b># of Users:</b> Depicts current number of users on particular portal instance.</li>
<li><b>Max # of Users:</b> Depicts total number of users allowed on particular portal instance.</li>
<li><b>Active:</b> Depicts if the portal instance active or not (Yes / No).</li>
</ul>
<br />
Enough of theory, lets experience it. Startup the server and replicate the following steps:<br />
<ol style="text-align: left;">
<li style="text-align: justify;">Login as administrator. (test@liferay.com/test will work)</li>
<li style="text-align: justify;">Navigate to Manage → Control Panel → Portal Instances section in 'Server' category.</li>
<li style="text-align: justify;">By default only one portal instance will be listed. To add new, click on add button fill up the form fields. Say you have created 'newinstance.com'.</li>
<li style="text-align: justify;">Assuming that you are working on your local system, you have to edit the host file (%SYSTEMROOT%\ System32\ drivers\ etc\ hosts). Add the following in the file:<br /><script class="brush: java" type="syntaxhighlighter">
<![CDATA[127.0.0.1 newinstance.com]]></script>If you are in network then you can map the entry with the IP address of the server on which Liferay is running and try.</li>
<li style="text-align: justify;">Start the browser (restart in case already running) and put 'newinstance.com:<PORT>' in address bar. What you see now in the new portal instance.</li>
<li style="text-align: justify;">You can login as test@<domainname>, (test@newinstance.com in out case). This is the admin user of the instance. As an administrator you cannot see the 'Server' category in Control Panel, which means new instance can be created only from main portal instance.</li>
</ol>
If we dig in further, we will come to know that we can have different properties file for each portal instances. To enable this feature, set the "company-id-properties" system property to true. The read order will now be: portal.properties, then portal-ext.properties, and then portal-liferay.com.properties. Note that not all properties can have different values per company. This functionality is only available for legacy reasons. The preferred way to configure a portal instance is through the Control Panel.<br />
<br />
<b>Handling Portal Instances in Custom Code:</b><br />
In real life scenario, we may need to process data differently for each Portal Instance in our custom code. So have a look on small code snippet:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
if(themeDisplay.getCompany().getWebId().equalsIgnoreCase(PropsUtil.get("company.default.web.id "))){
// do something
}else if(themeDisplay.getCompany().getWebId().equalsIgnoreCase("<Your custom portal instance web id>"))){
// do something else
}]]></script>
Hope you enjoyed the reading.
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com2Mumbai, Maharashtra, India19.0759837 72.87765590000003618.595792699999997 72.232208900000032 19.5561747 73.52310290000004tag:blogger.com,1999:blog-242411957491300462.post-60382947672353661382013-06-23T21:42:00.000+05:302013-07-08T09:49:20.795+05:30Customizing Database Column Size<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
In most on the real life implementations, we need to use different datatype and and their sizes in database tables. As in Liferay, tables are created at the time of portlet deployment with the help of SQL generated by building of service.xml file, so we need to put all the table attribute information in configuration so that it can create table with the customized settings. The size of String is 75 by default. For customizing the same, we have to modify the <i>portlet-model-hints.xml </i>file. This file is available in META-INF directory inside src. To customizing the column size, we have to do the following:<br />
<br />
Lest see the sample service.xml file:<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<service-builder package-path="com.apoorva.portlet">
<author>apoorva.prakash</author>
<namespace>education</namespace>
<entity name="school" local-service="true" >
<column name="schoolId" type="long" primary="true"></column>
<column name="schoolName" type="String"></column>
<column name="schoolDescription" type="String"></column>
</entity>
</service-builder>
]]></script>
Now we are going to modify the 'schoolName' and 'schoolDescription' attributes:<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<model-hints>
<model name=" com.apoorva.portlet.school">
<field name=" schoolId" type="long" />
<field name=" schoolName" type="String">
<hint name="max-length">1000</hint>
</field>
<field name=" schoolDescription" type="String">
<hint name="max-length">5000</hint>
</field>
</model>
<model-hints>
]]></script>
Now, after the deployment and creation of the table when you'll see table description, the 'schoolName' attribute will be of String type where as the 'schoolDescription' will be of varchar. Great! Indeed, but How the miracle happened? well, its not the magic, if length given in the model hints is greater than 4000 then the column type is converted in Varchar or Text automatically by Liferay but if length less than or equal to 4000 then column type will be String.</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com0tag:blogger.com,1999:blog-242411957491300462.post-1897404923308054702013-06-08T14:42:00.000+05:302013-07-08T09:49:44.628+05:30Enabling SSL in Liferay6.1.1-Jboss7.1.1 Bundle<div dir="ltr" style="text-align: left;" trbidi="on">
My last post was about SSL in Liferay-Tomcat bundle. In the array, my this post about enabling SSL in Liferay-Jboss 7 bundle, in standalone mode. (We'll discuss about standalone and domain mode of Jboss in the next post)<br />
<br />
Similarly there are two parts, first creating of certificates and another is configuration. For SSL certificate creation you can see my previous post. Now lets talk about settings. Go to the <i>\liferay-portal-6.1.1-ce-ga2\jboss-7.1.1\standalone\configuration\</i> and open the <i>standalone.xml</i> file and follow the following steps:<br />
<br />
<ol style="text-align: left;">
<li>Search for "<i>urn:jboss:domain:web:1.1</i>" and replace the <subsystem> ... </subsystem> contents with following:
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="false">
<configuration>
<jsp-configuration development="true"/>
</configuration>
<connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http"/>
<connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true">
<ssl name="https" password="changeit" certificate-key-file="C:\Documents and Settings\Apoorva\.keystore"/>
</connector>
<virtual-server name="default-host" enable-welcome-root="false">
<alias name="localhost"/>
</virtual-server>
</subsystem>
]]></script>
<br />Again the password and certificate-key-file value will depend on your inputs at the time of certificate creation and default home directory.
</li>
<li>Scroll further down and look for <interfaces> ... </interfaces> entry and replace whole with the following:
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<interfaces>
<interface name="management">
<inet-address value="127.0.0.1"/>
</interface>
<interface name="public">
<inet-address value="127.0.0.1"/>
</interface>
<interface name="any">
<any-address/>
</interface>
</interfaces>
]]></script></li>
<li>Now you the next block you will see will be of <socket-binding-group>, again replace the <socket-binding-group> ... </socket-binding-group> with the following:
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<socket-binding-group name="standard-sockets" default-interface="any">
<socket-binding name="http" port="8080"/>
<socket-binding name="https" port="8181"/>
<socket-binding name="jmx-connector-registry" port="1090"/>
<socket-binding name="jmx-connector-server" port="1091"/>
<socket-binding name="jndi" port="1099"/>
<socket-binding name="osgi-http" port="8090"/>
<socket-binding name="remoting" port="4447"/>
<socket-binding name="txn-recovery-environment" port="4712"/>
<socket-binding name="txn-status-manager" port="4713"/>
</socket-binding-group>
]]></script></li>
</ol>
<div>
That's it. Now start the server and use <i>https://localhost:8181:/web/guest/</i> and enjoy! :)</div>
<div>
<br /></div>
<div>
You can download sample standalone.xml from <a href="https://dl.dropboxusercontent.com/u/30117816/Blog-Examples/standalone.xml" target="_blank">here</a>.</div>
<br />
<br /></div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com0tag:blogger.com,1999:blog-242411957491300462.post-37361125845248598572013-05-25T14:17:00.000+05:302013-07-08T09:49:57.954+05:30Enabling SSL in Liferay-Tomcat Bundle<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
For enabling the SSL (https) in Liferay-Tomcat bundle, we need to modify the server.xml file inside <i>\liferay-portal-6.1.1-ce-ga2\tomcat-7.0.27\conf\</i> directory. By default the following entry is used:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8444"
URIEncoding="UTF-8" />
]]></script>
There are basically two steps for enabling SSL. First - we need to create a self signed certificate (if you don't have one from publisher) and secondly setting up tomcat configurations. You can see approach for certificate creation in my previous post, only STEP 1 is sufficient for this purpose.<br />
<br />
Now for enabling SSL, just put the following in server.xml</div>
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<connector port="8181"
protocol="HTTP/1.1"
SSLEnabled="true"
maxThreads="150"
scheme="https"
secure="true"
keystorePass="changeit"
clientAuth="false"
sslProtocol="TLS" />
]]></script>where the keystore password is the password used at the time of certificate creation.<br />
<br />
Now start the server. You will be able to use <i>https://localhost:8181/web/guest/ </i>after complete startup. You can manage ports as per requirements.
<br />
<br />
You can download the sample server.xml file from <a href="https://dl.dropboxusercontent.com/u/30117816/Blog-Examples/server.xml" target="_blank">here</a>.</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com0tag:blogger.com,1999:blog-242411957491300462.post-2826820275095966872013-05-12T23:17:00.000+05:302013-05-12T23:17:00.663+05:30Creating Self Signed Certificate using Keytool<div dir="ltr" style="text-align: left;" trbidi="on">
Prerequsites: For using the keytool utility, we have to ensure that our environment is configured to use the <i>bin</i> directory of JDK, otherwise the full path to the utility must be present on the command line. Which can be ensured by typing <i>java</i> or <i>javac</i> on command prompt.<br />
<br />
There are basically three steps:<br />
1. Generate the certificate in the keystore file<br />
<br />
<script class="brush: xml" type="syntaxhighlighter">
<![CDATA[
keytool -genkey -alias tomcat -keypass changeit -keyalg RSA
]]></script>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-kGnpFXoPYtM/UXlobz8zusI/AAAAAAAAAcQ/o5nWQmpQt1A/s1600/creating+Self+signed+certificate.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="324" src="http://2.bp.blogspot.com/-kGnpFXoPYtM/UXlobz8zusI/AAAAAAAAAcQ/o5nWQmpQt1A/s640/creating+Self+signed+certificate.png" width="640" /></a></div>
Here <i>tomcat</i> is an unique alias of certificate. change is the default password, you can change it. You now have a <i>.keystore</i> in the current user's home directory<br />
<br />
2. Now export the certificate you just generated:<br />
<script class="brush: xml" type="syntaxhighlighter">
<![CDATA[
keytool -export -alias tomcat -keypass changeit -file server.crt
]]></script>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-eanyvlxC9B8/UXlqV8LiZ6I/AAAAAAAAAcc/e9lqXeV3x3E/s1600/2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="326" src="http://4.bp.blogspot.com/-eanyvlxC9B8/UXlqV8LiZ6I/AAAAAAAAAcc/e9lqXeV3x3E/s640/2.PNG" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
Now the certificate has been exported to server.crt file.</div>
<br />
3. Now, add the exported certificate (server.crt) to your JRE's cacerts file<br />
<script class="brush: xml" type="syntaxhighlighter">
<![CDATA[
keytool -import -file server.crt -keypass changeit -keystore <path TO CACERTS>
]]></script>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-o9_nCvJiHug/UXlrJJ68teI/AAAAAAAAAcs/wuiHcspk2Qw/s1600/3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="326" src="http://2.bp.blogspot.com/-o9_nCvJiHug/UXlrJJ68teI/AAAAAAAAAcs/wuiHcspk2Qw/s640/3.PNG" width="640" /></a></div>
Yes, now its done.</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com0tag:blogger.com,1999:blog-242411957491300462.post-53792789148826167562013-04-28T21:16:00.000+05:302013-05-01T13:55:36.069+05:30Creating Roles in Liferay with Portal-ext.properties<div dir="ltr" style="text-align: left;" trbidi="on">
Need of user role is a very common in live scenario. One way is quite easy, just sign in as administrator, go to control panel and add one. But there is a drawback of this approach. If you are working on staging environment, you have to create this role in production environment when the code is deployed there. It means this is database specific and it will not move to production when the build is deployed on the server.<br />
<br />
Liferay has provided us a better solution for the same. We can create role by using certain properties in portal-ext.properties file. We have to add the following properties in our portal-ext properties file.<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
system.roles=RoleA,RoleB
system.role.RoleA.description=This is Role A description.
system.role.RoleB.description=This is Role B description.
]]></script>
Just restart the box after adding them, and go to the Roles section in Control Panel, you will be able to see both the roles added there.<br />
<br />
Now if we want to access these roles in our code programmatically because this is basic need of creating role. So it can be done as following:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
Role roleA = RoleLocalServiceUtil.getRole(companyId, "RoleA");
for (long userId : UserLocalServiceUtil.getRoleUserIds(roleA.getRoleId())) {
//some custom code for role users
}]]></script>
For getting users we can use the following methods:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
List<user> UserLocalServiceUtil.getRoleUsers(long roleId);
]]></script>
Some other properties of portal-ext.properties that you can work on are:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
system.organization.roles=
system.site.roles=
]]></script>
Hope this will be helpful.
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com3tag:blogger.com,1999:blog-242411957491300462.post-4242577160635350942013-04-18T01:18:00.000+05:302013-04-18T01:18:00.145+05:30Liferay: Uploading User Portrait via Custom Portlet<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
The following code can be integreate with any MVC portlet extending MVCPortlet in controller class.<br />
<br />
<b>view.jsp</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %>
<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme" %>
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
<%@ taglib uri="http://liferay.com/tld/util" prefix="liferay-util" %>
<%@ page import="com.liferay.portal.model.User" %>
<portlet:defineObjects />
<liferay-theme:defineObjects />
This is the <b>Photo Uploder</b> portlet in View mode.
<%
User selUser = themeDisplay.getUser();
%>
<portlet:actionURL var="editUserPortraitURL">
<portlet:param name="struts_action" value="/users_admin/edit_user_portrait" />
</portlet:actionURL>
<form action="<%= editUserPortraitURL %>
" enctype="multipart/form-data" method="post" name="fm">
<input name="p_u_i_d" type="text" value="<%= selUser.getUserId() %>" />
<input name="fileName" size="50" type="file" />
<input type="submit" name="submit" value="submit"/>
</form>
]]></script>
</div>
<b>Controller class</b><br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.upload.UploadPortletRequest;
import com.liferay.portal.kernel.util.FileUtil;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserServiceUtil;
import com.liferay.portal.util.PortalUtil;
import com.liferay.util.bridges.mvc.MVCPortlet;
/**
* Portlet implementation class PhotoUploder
*/
public class PhotoUploder extends MVCPortlet {
public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws IOException, PortletException{
try {
updatePortrait(actionRequest);
sendRedirect(actionRequest, actionResponse);
}
catch (Exception e) {
e.printStackTrace();
}
}
protected void updatePortrait(ActionRequest actionRequest)
throws Exception {
UploadPortletRequest uploadPortletRequest = PortalUtil.getUploadPortletRequest(actionRequest);
User user = PortalUtil.getSelectedUser(uploadPortletRequest);
File file = uploadPortletRequest.getFile("fileName");
InputStream inputStream = new FileInputStream(file);
byte[] bytes = FileUtil.getBytes(inputStream);
UserServiceUtil.updatePortrait(user.getUserId(), bytes);
}
private static Log _log = LogFactoryUtil.getLog(PhotoUploder.class);
}
]]></script>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com0tag:blogger.com,1999:blog-242411957491300462.post-20780322445246621952013-04-02T23:12:00.000+05:302013-04-03T13:06:33.927+05:30Solution of Duplicate Submission issue of Form on Page Reload<div dir="ltr" style="text-align: left;" trbidi="on">
Re submission of form on press of refresh button is an old issue is Liferay. The reason behind this issue is the parameters and action which are available in URL after the form submission. Earlier some developers used to open some other JSP after completion of Action.<br />
<br />
But its solution is a very easy, provided by liferay itself. We have to set the following value in a tag inside liferay-portlet.xml which is set false by default.<br />
<script class="brush: xml" type="syntaxhighlighter">
<![CDATA[
<action-url-redirect>true</action-url-redirect>
]]></script>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com9tag:blogger.com,1999:blog-242411957491300462.post-46729370459756773282012-10-20T00:03:00.000+05:302012-10-21T00:18:37.487+05:30Java Threads via Extending Thread class, implementing Runnable interface and Callable interface<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">If anybody asks - What are the two methods of using Threads
in Java? The answer is on our tip of tongue- TWO, but further if it is asked
what is the difference between threads implemented via extending Thread class
and implementing runnable interface? we feel dificulty in explaining. Here some
of my thoughts are presented to draw a line among them.</span></div>
<div class="MsoNormal">
</div>
<ol style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;"> As we all know Java doesn't support multiple inheritance.
If you want to extend the Thread class then it will make your class unable to
extend other classes as java is having single inheritance feature whereas If
you implement runnable interface, you can gain better object-oriented design
and consistency and also avoid the single inheritance problems.</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">In OOP, we extend a class for adding some new behaviour.
If we are not making any modification on Thread than its a good OOP design to
use Runnable interface.</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">When we extend a thread class, all the Properties and Behaviours of Thread class and inherited by the subclass, its kind of overhead if we are not going to use it and the same can be achieved on ease with Runnable.
</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Runnable interface represent Task and the same gives
flexibility to get them executed by either Executors or Thread or any other means.
So it draws a line between Task as Runnable than Thread as good design
decision. However Executors accept Runnable as Task and they have worker thread
which executes those tasks, but that's a totally different point. </span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">While we are differentiating task as Runnable exhibits it
can be reused and we are also provided with liberty to execute it from
different means. As we know, a thread cannot be restarted once it's complete so
again Runnable seems more promising. </span></li>
</ol>
<br />
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><b>A Short Note on Callable and Runnable</b>:<o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">Both the interfaces are implemented by those classes who
want to execute a thread of execution, but few notable differences are as
follows:</span></div>
<div class="MsoNormal">
</div>
<ol style="text-align: left;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">A Thread implemented via Callable interface may return a
value, whereas its not possible if we are using a Runnable interface.</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">A Thread implemented via Callable interface may throw
checked exceptions, whereas its not possible if we are using a Runnable interface.</span></li>
</ol>
<br />
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;"><o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">What I feel, the developers of Java felt a need of enhancing
the capabilities of the Runnable interface, without changing the usage of the
Runnable interface and that is why probably they've developed Callable
interface.<o:p></o:p></span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-family: Arial, Helvetica, sans-serif;">I hope this will clear some of the doubt clouds about
threads.</span></div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com8Andheri East, Mumbai, Maharashtra, India19.1154908 72.872695219.0854778 72.833213199999989 19.1455038 72.9121772tag:blogger.com,1999:blog-242411957491300462.post-63162523759882219002012-10-18T23:48:00.000+05:302012-10-19T17:06:35.237+05:30Liferay: Reading cookies in Theme Template<div dir="ltr" style="text-align: left;" trbidi="on">
We can read the cookies in theme template using the following code:<br />
<script class="brush: html" type="syntaxhighlighter">
<![CDATA[
#foreach($cookie in $request.getCookies())
<b>$cookie.getName() - </b>$cookie.getValue()
#end
]]>
</script>
Hope this will help.</div>Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com2tag:blogger.com,1999:blog-242411957491300462.post-76835758571659742342012-10-14T12:55:00.000+05:302012-10-14T12:59:56.751+05:30Overriding Events: Working with PreActions and PostActions in Liferay using EXT<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Liferay provides us facility to
execute some code before and after of some specific events, namely Login, Logout
and Service. Login and Logout are self-explanatory, Service is the event that
takes place before or after every Action. For instance, If we have
CustomServicePreAction and CustomLOginPreAction, in that case CustomServicePreAction
will be called first then CustomLOginPreAction and then the LoginAction class
will be invoked.</span><br />
<div class="MsoNormal">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><o:p></o:p></span></div>
<div class="MsoNormal">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">To achieve this, we need to make some
entry in the portal-ext.properties, however some values are already present in
portal.properties file, we have to update those properties, as following:<o:p></o:p>
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
servlet.service.events.pre=com.liferay.portal.events.ServicePreAction,com.liferay.portal.events.CustomServicePreAction
servlet.service.events.post=com.liferay.portal.events.ServicePostAction,com.liferay.portal.events.CustomServicePostAction
login.events.pre=com.liferay.portal.events.LoginPreAction,com.liferay.portal.events.CustomLoginPreAction
login.events.post=com.liferay.portal.events.LoginPostAction,com.liferay.portal.events.DefaultLandingPageAction,com.liferay.portal.events.CustomLoginPostA
ction
logout.events.pre=com.liferay.portal.events.LogoutPreAction,com.liferay.portal.events.CustomLogoutPreAction
logout.events.post=com.liferay.portal.events.LogoutPostAction,com.liferay.portal.events.DefaultLogoutPageAction,com.liferay.portal.events.SiteMinderLogou
tAction,com.liferay.portal.events.CustomLogoutPostAction
]]>
</script>
</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">Here the our custom classes are: </span><br />
<br />
<ol style="text-align: left;">
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">com.liferay.portal.events.CustomServicePreAction, </span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">com.liferay.portal.events.CustomServicePostAction, </span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">com.liferay.portal.events.CustomLoginPreAction, </span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">com.liferay.portal.events.CustomLoginPostAction,</span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">com.liferay.portal.events.CustomLogoutPreAction, and </span></li>
<li><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">com.liferay.portal.events.CustomLogoutPostAction.</span></li>
</ol>
<br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif; line-height: 115%;">Now
we have to add the following classes in Ext:</span><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><span style="line-height: 115%;"><br /></span><span style="line-height: 115%;"><b>1. CustomServicePreAction</b></span></span>
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.liferay.portal.events;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liferay.portal.kernel.events.Action;
/**
* @author apoorva.prakash
*/
public class CustomServicePreAction extends Action {
public void run(HttpServletRequest request, HttpServletResponse response) {
System.out.println("this is custom service preaction");
}
}
]]>
</script><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif; line-height: 115%;"><b><br /></b></span>
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">2. CustomServicePostAction</span></b>
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.liferay.portal.events;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liferay.portal.kernel.events.Action;
/**
* @author apoorva.prakash
*/
public class CustomServicePostAction extends Action {
public void run(HttpServletRequest request, HttpServletResponse response) {
System.out.println("this is custom service post action");
}
}
]]>
</script><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">3. CustomLoginPreAction</span></b><script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.liferay.portal.events;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liferay.portal.kernel.events.Action;
import com.liferay.portal.kernel.events.ActionException;
/**
* @author apoorva.prakash
*
*/
public class CustomLoginPreAction extends Action {
public void run(HttpServletRequest request, HttpServletResponse response)
throws ActionException {
System.out.println("this is CustomLoginPreAction...");
}
}
]]>
</script><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">4. CustomLoginPostAction</span></b><script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.liferay.portal.events;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liferay.portal.kernel.events.Action;
import com.liferay.portal.kernel.events.ActionException;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
/**
* @author apoorva.prakash
*
*/
public class CustomLoginPostAction extends Action {
public void run(HttpServletRequest request, HttpServletResponse response)
throws ActionException {
System.out.println("this is CustomLoginPostAction...");
if (_log.isInfoEnabled()) {
_log.info("Running CustomLoginPostAction" + request.getRemoteUser());
}
}
private static Log _log = LogFactoryUtil.getLog(CustomLoginPostAction.class);
}
]]>
</script><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">5. CustomLogoutPreAction</span></b><script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.liferay.portal.events;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liferay.portal.kernel.events.Action;
import com.liferay.portal.kernel.events.ActionException;
/**
* @author apoorva.prakash
*
*/
public class CustomLogoutPreAction extends Action {
public void run(HttpServletRequest request, HttpServletResponse response)
throws ActionException {
System.out.println("this is CustomLogoutPreAction");
}
}
]]>
</script><br />
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span>
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">6. CustomLogoutPostAction</span></b><script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package com.liferay.portal.events;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.liferay.portal.kernel.events.Action;
import com.liferay.portal.kernel.events.ActionException;
/**
* @author apoorva.prakash
*
*/
public class CustomLogoutPostAction extends Action {
public void run(HttpServletRequest request, HttpServletResponse response)
throws ActionException {
System.out.println("this is CustomLogoutPostAction");
}
}
]]>
</script><br />
<b><span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;"><br /></span></b>
<br />
<div class="MsoNormal">
<span style="font-family: Helvetica Neue, Arial, Helvetica, sans-serif;">And now, run your code. It will
work.</span><o:p></o:p></div>
<br /></div>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com3tag:blogger.com,1999:blog-242411957491300462.post-56827169239273205632012-10-13T23:35:00.000+05:302013-08-07T15:12:43.138+05:30Creating Account Creation URL in Theme Velocity Template in LIferay<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
For creating URL for new account creation in theme velocity template, the following code can be used:<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
#set ($createAccountUrl = $portletURLFactory.create($request, "58", $page.getPlid(), "ACTION_PHASE"))
$createAccountUrl.setWindowState(WindowState.MAXIMIZED)
$createAccountUrl.setParameter("struts_action", "/login/create_account")
$createAccountUrl.setPortletMode(PortletMode.VIEW)
$createAccountUrl.setParameter("saveLastPath", "0")
]]>
</script>
</div>
Apoorva Prakashhttp://www.blogger.com/profile/14006187818572192191noreply@blogger.com0