Wednesday, September 26, 2012

Hi Friends,
 I could not write any new post due to my ill health and some personal as well as professional commitment. But I have decided now to write actively my experience while working with Liferay latest version i.e 6.x.   In the meantime I am posting a link which have many solution. RayAuge personal snippets

Wednesday, April 13, 2011

Struts Tips

Hi Friends ,
I was working on one of my j2ee project . From there I want to share few small but usefull tips for struts.In struts many time we caught in wrong side for duplicate page submission. I am going to share how to tackle that
and how to pass parameter once redirect is done, one way is there to put parameters in session but it is messy.
Manage Redirect:
It is quite simple we need to add one attribute redirect="true" in struts-config.xml
e.g.
<action path="{Action-Path}" type="{Action}" name="{Form-Bean}">

<forward name="{Forward-Name}" path="{Forward-Path}" redirect="true"/>
</action>
Pass Parameter After Redirect:
In action file in place of using mapping.findForward("{Action-Path}") use ActionRedirect (subclass of ActionForward).This class includes an addParameter() method.
e.g.
ActionRedirect ar = new ActionRedirect(mapping.findForward("{Action-Path}"));
ar.addParameter("{Parameter-Name}", {Parameter-Value});
return ar;
Or
return (new ActionRedirect(mapping.findForward("{Action-Path}"))).addParameter("{Parameter-Name}", "{Parameter-Value}");
Here all words with in {} are place holders.

Thursday, March 17, 2011

I18N Liferay 6.x

Hi today I will share how to use in built Liferay I18N functionality to your custom portlet in Liferay 6.x

It is very simple to add it , for that we need to modify just 2 files.

1.portlet.xml --- In this file add resource bundle entry.

e.g <resource-bundle>content.Language</resource-bundle>

2.build.xml --- In this file we need to call below target.

<target name="build-lang">

<antcall target="build-lang-cmd">

<param name="lang.dir" value="docroot/WEB-INF/src/content" />

<param name="lang.file" value="Language" />

</antcall>

</target>

Now we need to just add one file with name Language.properties under docroot/WEB-INF/src/content
from build.xml using ant call buil-lang. That it !!!

Wednesday, March 16, 2011

CK editor in Liferay 6.0

Hi Friends,
In this article I just want to share how to use CK editor in liferay 6.0 .

Follow these 4 simple steps.

Step 1.Add below line on your page
<liferay-ui:input-editor width="80%" />.


Step 2.Create hidden variable to set the value of CK editor like below
<aui:input name="content" type="hidden" />


Step 3.Add javascript init method like this

<aui:script>

function <portlet:namespace />initEditor() {

return "<%= UnicodeFormatter.toString(content) %>";

}

</aui:script>


Step 4:On submiting form we can assign CK editor value like this

function <portlet:namespace />saveEntry() {

var message = window.<portlet:namespace />editor.getHTML();

document.<portlet:namespace />fm.<portlet:namespace />content.value = message;

submitForm(document.<portlet:namespace />fm);

}


Currently we are having problem in liferay 6.0 is that when we refresh CK editor page , it gives JS error.

For that fix is like this get html/js/editor/ckeditor.jsp in function initCkArea() comment line 52 and 53 which starts with CKEDITOR.config.toolbar and CKEDITOR.config.customConfig respectively and add below line

ckEditor.setData(parent.<%= HtmlUtil.escape(initMethod) %>());
In the same file comment line number 131 i.e

initCkArea(); and add
if (parent.AUI) {

parent.AUI().on('domready', initCkArea);

}
In side CKEDITOR.replace method at line number 123 in same file comment line starts with filebrowserBrowseUrl , filebrowserUploadUrl and
add below code

customConfig: '<%= PortalUtil.getPathContext() %>/html/js/editor/ckeditor/ckconfig.jsp?p_l_id=<%= plid %>&p_p_id=<%= HttpUtil.encodeURL(portletId) %>&p_main_path=<%= HttpUtil.encodeURL(mainPath) %>&doAsUserId=<%= HttpUtil.encodeURL(doAsUserId) %>&cssPath=<%= HttpUtil.encodeURL(cssPath) %>&cssClasses=<%= HttpUtil.encodeURL(cssClasses) %>',
filebrowserBrowseUrl: '<%= PortalUtil.getPathContext() %>/html/js/editor/ckeditor/editor/filemanager/browser/liferay/browser.html?Connector=<%= connectorURL %>',
filebrowserUploadUrl: null,
toolbar: '<%= TextFormatter.format(HtmlUtil.escape(toolbarSet), TextFormatter.M) %>'


Finally add required import i.e
<%@ page import="com.liferay.portal.util.PortalUtil" %> and one extra variable


String portletId = ParamUtil.getString(request, "p_p_id");

Wednesday, February 23, 2011

Simple java program to read json from text file

Hi All,
was busy some what from last couple of months. Finally started on liferay 6.0 from last couple of week.Today want to share simple program which can be used to read a text file and read json from it using apache commons library. Using apache commons library we can reduce our code to large extent. Here is the program.

import java.io.IOException;
import java.io.InputStream;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JSONSerializer;

import org.apache.commons.io.IOUtils;


public class ClassloaderTest {

public static void main(String [] args) {
ClassLoader cl = ClassloaderTest.class.getClassLoader();
InputStream is = cl.getResourceAsStream("json.txt");
try {

String s = IOUtils.toString( is );
JSONObject json = (JSONObject) JSONSerializer.toJSON(s);

JSONObject searchresults = json.getJSONObject("searchresults");
System.out.println("ssssssss" + searchresults.optString("count", ""));
JSONArray jarray = searchresults.getJSONArray("URI");
for(int i=0 ; i < jarray.size(); i++) {
System.out.println("jarray [" + i + "] --------" + jarray.getString(i));
}
} catch(IOException e) {
e.printStackTrace();
}
}



}

and content of json.txt is below
{
"searchresults": {
"URI": ["qa1", "qa2", "qa3", "qa4", "qa5"],
"count": "5"
}
}

jason.txt you can keep in the same package where your class is.
Hope this post helps others.
Kamal

Thursday, November 11, 2010

creating layout in ext environment in liferay

Hi today I want to share how to create layout in ext environment in liferay. Though it should not be used as ext environment is hard to manage but some times we don't want to maintain seperate development environment (plugin) in that case it can be used.
Here are the steps:
Step 1:
In ext-web\docroot\WEB-INF create a file name liferay-layout-templates-ext.xml

Step 2:
Open file liferay-layout-templates-ext.xml and put code

<?xml version="1.0"?>
<!DOCTYPE layout-templates PUBLIC "-//Liferay//DTD Layout Templates 5.2.0//EN" "http://www.liferay.com/dtd/liferay-layout-templates_5_2_0.dtd">

<layout-templates>
<custom>
<layout-template id="4_2_columns" name="custom(4-2)">
<template-path>
/layouttpl/customlayout/4_2_columns.tpl
</template-path>
<wap-template-path>
/layouttpl/customlayout/4_2_columns.wap.tpl
</wap-template-path>
<thumbnail-path>
/layouttpl/customlayout/4_2_columns.png
</thumbnail-path>
</layout-template>
</custom>
</layout-templates>

This is file where your mapping goes regarding .tpl files used to create your layout.

Step 3:Make a layouttpl folder at same level as html folder in ext-web. Inside this folder make customlayout folder.

Step 4:Now in customlayout folder you need to keep your .png and .tpl files related to layout as per the mapping .Now create a files with name 4_2_columns.tpl and 4_2_columns.wap.tpl in customlayout folder and put below code.


<div class="columns-2" id="content-wrapper">
<table class="lfr-grid" id="layout-grid">
<tr>
<td class="lfr-column thirty" id="column-1" width="25%" valign="top">
$processor.processColumn("column-1")
</td>
<td class="lfr-column thirty" id="column-2" width="25%" valign="top">
$processor.processColumn("column-2")
</td>
<td class="lfr-column thirty" id="column-3" width="25%" valign="top">
$processor.processColumn("column-3")
</td>
<td class="lfr-column thirty" id="column-4" width="25%" valign="top">
$processor.processColumn("column-4")
</td>
</tr>
<tr>
<td colspan="4"><div style="border-bottom: 3px dotted #405DD5;"></div></td>
</tr>
<tr>
<td colspan="4">
<table class="lfr-grid" id="layout-grid">
<tr>
<td class="lfr-column thirty" id="column-5" valign="top">
$processor.processColumn("column-5")
</td>
<td class="lfr-column seventy" id="column-6" valign="top">
$processor.processColumn("column-6")
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>


and in 4_2_columns.wap.tpl put below code

<table>
<tr>
<td>
$processor.processColumn("column-1")
</td>
<td>
$processor.processColumn("column-2")
</td>
<td>
$processor.processColumn("column-3")
</td>
<td>
$processor.processColumn("column-4")
</td>
<td>
$processor.processColumn("column-5")
</td>
<td>
$processor.processColumn("column-6")
</td>
</tr>
</table>

Now do ant deploy from ext-web and start the server after successful deployment. In dock in Layout Template you will get new layout. add it and see.
That's all.

Thursday, October 7, 2010

getting url parameter value in liferay

Hi All,
If we set url parameter value in normal jsp page like $some_url$?abc=ok. Then normally we can get value using request.getParameter("abc"); very simple.But in liferay I tried it was not working, then how to do in liferay?? not as simple as
request.getParameter("abc"); but little more code. Taking above example
HttpServletRequest httpReq = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(renderRequest));
String abc = httpReq.getParameter("abc");

So we will get desired result.
Hope this helps others.

Thursday, September 23, 2010

popup on popup in liferay

To implement popup on popup in liferay is quite simple. We need to have 2 pages one parent page on which 1st popup is already opened and 2nd page which will be opened in 2nd popup.

For 1st page call:
function parentPage(url) {
var popup = Liferay.Popup(
{
stack: true,
draggable:false,
title: 'Parent Page',
position:[110,50],
modal:true,
width:450,
height:365,
url:url
}
);
}
here stack:true property is important which is responsible for pop on popup.url is which page we want to load . It can be portlet url. Other parameters are self explanatory.

In child page you can simply write another popup.

function childPage(url) {
var popup = Liferay.Popup(
{

title: 'Child Page',
position:[110,50],
modal:true,
width:450,
height:365,
url:url
}
);
}

Thanks and Hope this help few people.

Wednesday, August 4, 2010

orderable search container in liferay by example

Liferay provide us with many good taglib out of them search container is one of them.It is widely used taglib. For simple understanding of search container please check Wiki here is the link Wiki Search Container. One thing that article is missing how to implement ordering using. For that we will follow few step and will do a simple example.
Step 1: Read the wiki article Search Container.
Step 2:Now write the below code in your jsp.

<%
PortalPreferences portalPrefs = PortletPreferencesFactoryUtil.getPortalPreferences(request);
String orderByCol = ParamUtil.getString(request, "orderByCol");

String orderByType = ParamUtil.getString(request, "orderByType");

if (Validator.isNotNull(orderByCol) && Validator.isNotNull(orderByType)) {
portalPrefs.setValue("KK_3", "kk-order-by-col", orderByCol);
portalPrefs.setValue("KK_3", "kk-order-by-type", orderByType);

} else {

orderByCol = portalPrefs.getValue("KK_3", "kk-order-by-col", "name");
orderByType = portalPrefs.getValue("KK_3", "kk-order-by-type", "asc");

}

OrderByComparator orderByComparator = AddressBookUtil.getAddressBookOrderByComparator(orderByCol, orderByType);
%>


Now I will explain what is happening we are getting the column on which we have to do ordering in orderByCol and order asc or desc in orderByType.
In line portalPrefs.setValue("KK_3", "kk-order-by-col", orderByCol);
here "KK_3" is namespace , "kk-order-by-col" is key and orderByCol is value.
In last line OrderByComparator orderByComparator = AddressBookUtil.getAddressBookOrderByComparator(orderByCol, orderByType);
For this you need to write a comparator , I have written it in com.ext.portlet.addressBook.util.AddressBookUtil and write this code


public class AddressBookUtil {

/**
*
* @param orderByCol
* @param orderByType
* @return
*/

public static OrderByComparator getAddressBookOrderByComparator(
String orderByCol, String orderByType) {

boolean orderByAsc = false;

if (orderByType.equals("asc")) {
orderByAsc = true;
}

OrderByComparator orderByComparator = null;

if (orderByCol.equals("name")) {
orderByComparator = new AddressBookNameComparator(orderByAsc);
} else if (orderByCol.equals("status")) {
orderByComparator = new AddressBookStatusComparator(orderByAsc);
}

return orderByComparator;
}

}

Now in same package write AddressBookNameComparator and AddressBookStatusComparator if you want you can write any where else and do the required imports. Below is the code for AddressBookNameComparator

public class AddressBookNameComparator extends OrderByComparator {

public static String ORDER_BY_ASC = "name ASC";

public static String ORDER_BY_DESC = "name DESC";

public AddressBookNameComparator() {
this(false);
}

public AddressBookNameComparator(boolean asc) {
_asc = asc;
}

public int compare(Object obj1, Object obj2) {
AddressBook project1 = (AddressBook) obj1;
AddressBook project2 = (AddressBook) obj2;

int value = project1.getName().toLowerCase().compareTo(
project2.getName().toLowerCase());

if (_asc) {
return value;
} else {
return -value;
}
}

public String getOrderBy() {
if (_asc) {
return ORDER_BY_ASC;
} else {
return ORDER_BY_DESC;
}
}

private boolean _asc;

}

Do the required imports .Same way you can do for other columns.
Step 3: Use the SearchContainer taglib.

<liferay-ui:search-container
emptyResultsMessage="No Result Found"
orderByCol="<%= orderByCol %>"
orderByType="<%= orderByType %>"
>
<liferay-ui:search-container-results results="<%= AddressBookLocalServiceUtil.getAddressBookList(searchContainer.getStart(), searchContainer.getEnd(),orderByComparator)%>">
total="<%= AddressBookLocalServiceUtil.getAddressBookCount() %>"
/>
<liferay-ui:search-container-row classname="com.ext.portlet.addressBook.model.AddressBook" escapedmodel="<%= true %>">
keyProperty="bookId"
modelVar="addressBook"
>


<liferay-ui:search-container-column-text name="name" orderable="<%= true %>" orderableproperty="name">
>

<%= addressBook.getName() %>

</liferay-ui:search-container-column-text>

<liferay-ui:search-container-column-text name="status" orderable="<%= true %>" orderableproperty="status" property="status">
/>

</liferay-ui:search-container-column-text>


<liferay-ui:search-iterator />
</liferay-ui:search-container-row></liferay-ui:search-container-results>
That is all about orderable search container.If you have read the wiki article then you will easily understand this.

HTH

Monday, March 8, 2010

Hiding portlet in liferay

Requirement: Hide the portlet for which user is not having permission to view.

Simple Approach:
It is very difficult to hide or show portlet at user level. To get rid of these type of problem liferay provide us Roles. So we can create roles and on those roles we can easily assign permission on each portlet.
Creating role in liferay is very simple.
Just login as Admin and using dock navigate to control panel , click on Role from left panel and then click Add...for more details refer portal administration guide from liferay.
Once this is done click on define permission and select portlet permission.
e.g. Suppose you want to remove view permission from portlet A then uncheck view.

When you will login as user with that role then you will get message something like this.
"you don't have required permission to access this portlet"
Finally to make this portlet invisible for that role user who is not having required permission to view the portlet.In portal-ext.properties add this line
layout.show.portlet.access.denied=false

IPC-using public render parameter

In last post we have learned how to do coordination between 2 portlet commonly known as Inter Portlet Communication. In post I am going to describe IPC using public render parameter.

This is the simplest method for IPC given by JSR-286.

Description:

In JSR 168 (Portlet 1.0), the render parameters set in the processAction() method are available only in the render phase of the same portlet.

By using the public render parameters feature, the render parameters set in the processAction() method of one portlet are available in render parameters of the other portlets. Using public render parameters instead of events avoids the additional process event call. The public render parameters can also be set on the render URL.

To enable coordination of render parameters with other portlets within the same portlet application or across portlet applications, the portlet can declare public render parameters in its deployment descriptor using the public-render-parameter element in the portlet application section. Public render parameters can be viewed and changed by other portlets or components.

In the portlet section, each portlet can specify the public render parameters to be shared through the supported-public-render-parameter element. The supported-public-render-parameter element must reference the identifier of a public render parameter defined in the portlet application section in a public-render-parameter element.

Example: If we carry same old portlets which we have build in last example i.e for Event model IPC namely test1-portlet and test2-portlet.

Step 1:

Declare the render parameters to be shared in the portlet.xml file by setting the public render parameters at the portlet application level.

e.g:

<portlet-app ...>

<portlet> ... </portlet>

<public-render-parameter>

<identifier>user-id</identifier> <qname xmlns:x="http://abc.com/userId">x:userId</qname>

</public-render-parameter>

</portlet-app>

Note:

1.A developer can declare a list of public paramters for a portlet application in portlet.xml.

2.Parameter names are namespaced to avoid naming conflict.

Step 2:

Portlet must declare which public param they want to use.

e.g.

After adding declaration portlet.xml will look something like this.

<portlet-app ......>

<portlet>

<portlet-name>test1</portlet-name> <display-name>test1</display-name>

........ ........

<supported-public-render-parameter>

user-id

</supported-public-render-parameter>

</portlet>

<public-render-parameter>

<identifier>user-id</identifier> <qname xmlns:x="http://abc.com/userId">x:userId</qname>

</public-render-parameter>

</portlet-app>

Note: Public params are available in all lifecycle method like processAction , processEvent, render and serveResource.

Step 3: We can set render parameter in the processAction() method by using the defined public render parameter identifier as the key.

e.g.

public void processAction(ActionRequest request, ActionResponse response)

throws IOException, PortletException { ........ response.setRenderParameter("user-id", userId); ........

}

Step 4: A portlet can read public render parameter using follwing method

request.getPublicParameterMap()

Note: Public render parameters are merged with regular parameters so can also be read using

request.getParameter(name) or request.getParameterMap()

Step 5: A portlet can remove a public render parameter by invoking following methods.

response.removePublicRenderParameter(name)

or

portletURL.removePublicRenderParameter(name)

Thursday, February 25, 2010

Coordination between portlets in JSR-286

To provide coordination JSR-286 provides 2 mechanism
1.Event: Portlet event that portlet can recieve and send.
2.Public Render Parameter : Render states that can be shared between portlets.

Event :

In JSR-168 :
The only way to achive eventing was through portlet session.
Limitation : Portlet has to be in the same web application.

In JSR-286 :
JSR 286 (Portlet 2.0) defines a lifecycle for events, so that eventing is possible between portlets that are in different web applications.

Definition Of Event in JSR -286 :
An event is lifecycle operation occuring before rendering phase. It is a loosely coupled , acting as a agent for communication between portlets.
Events allow portlets to respond on actions or state changes not directly related to an interaction of the user with the portlet.

A portlet can declare events in its deployment descriptor by using the event-definition element in the portlet application section.
In the portlet section, each portlet specifies the events it would like to publish through the supported-publishing-event element and
the events it would like to process through the supported-processing-event element.

The supported-publishing-event and supported-processing-event elements must reference the event name defined in the portlet application section in an event-definition element.

The portlet creates events using the setEvent() method during action processing. The events are processed by the portlet container after the action processing has finished.
Portlets can also create events during the event phase by calling the setEvent() method on EventResponse.

To receive events, the portlet must implement the javax.Portlet.EventPortlet interface. The portlet container calls the processEvent() method
for each event targeted to the portlet with an EventRequest and EventResponse object. The portlet can access the event that triggered the current
process event call by using the EventRequest.getEvent() method. This method returns an object of type Event encapsulating the current event name and value.

Event names are represented as QNames to identify them uniquely. The event name can be retrieved by using the getQName() method that returns the complete
QName of the event, or by using the getName() method that returns only the local part of the event name. The value of the event must be based on the type
defined in the deployment descriptor.

So this all about theory time for some practical.

For this simple example I am going to use plugin sdk liferay version 5.2.3

Step 1:
create 2 portlets in plugins environment.Creating portlet in plugin is very simple just execute below command
Go to {your_work_space}\plugins\portlets> and execute command
create hello "Hello World" this will create portlet with portlet display name = "Hello World" and portlet name = hello

I am creating here 2 portlets with name test1 and test2

Step 2: Go to your 1st portlet below location in our present case it is test1 i.e

{your_work_space}\plugins\portlets\test1-portlet\docroot\WEB-INF

open porlet.xml file. In that add first Event definition as below

e.g.
<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0" 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">
<portlet>

<..>
</portlet>
<!-- Event Definition-starts -->
<event-definition>
<qname xmlns:x="http:kamal.com/events">x:Name
<value-type>java.lang.String
<!-- Event Definition-ends -->
</event-definition>
</portlet-app>

Step 3: Now we need to publish event
We will make test1-portlet as Event Publishing portlet as well. So open again portlet.xml file same as step 2
Add supported-publishing-event tag like below.

<supported-publishing-event>
x:Name
</supported-publishing-event>

Now your portlet.xml file structure will be like this.

<?xml version="1.0"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0" 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">
<portlet>

<..>
<!-- supported-publishing-event- starts -->
<supported-publishing-event>
x:Name
</supported-publishing-event>
<!-- supported-publishing-event- ends -->
</portlet>
<event-definition>
<qname xmlns:x="http:kamal.com/events">x:Name
<value-type>java.lang.String
</event-definition>
</portlet-app>


Step 4: Now our Event publishing portlet is ready with required configuration , now we need to do same configuration for
Event Processing portlet. Now open portlet.xml for test2-portlet and modify it as above with minor change in place of
<supported-publishing-event> use <supported-processing-event> thats it. Now structure will look like this.

<?xml version="1.0"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0" 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">
<portlet>
<!-- here other portlet related content will come like portlet-name , diaply-name etc-->
<..>
<supported-processing-event>
x:Name
</supported-processing-event>
</portlet>
<event-definition>
<qname xmlns:x="http:kamal.com/events">x:Name
<value-type>java.lang.String
</event-definition>
</portlet-app>


Step 5: Now all configuration part is over , now we will modify java files
Go to test1-portlet's JSPPortlet.java at location {your_work_space}\plugins\portlets\test1-portlet\docroot\WEB-INF\src\com\sample\jsp\portlet
In processAction method add below code
QName qname = new QName("http:kamal.com/events" , "Name");
String value = "Hurray we have done it";
actionResponse.setEvent(qname, value);

and add needful imports
import javax.xml.namespace.QName;

Step 6: Now Go to test2-portlet's JSPPortlet.java at location {your_work_space}\plugins\portlets\test2-portlet\docroot\WEB-INF\src\com\sample\jsp\portlet
Add new method to process event

public void processEvent(EventRequest request, EventResponse response) {
_log.info("I m in process event");
Event event = request.getEvent();
if(event.getName().equals("Name")) {
String displayText = (String)event.getValue();
response.setRenderParameter(
"displayText", displayText);
}
}

and do needful imports
import javax.portlet.Event;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;

Step 7: Now we are done java part as well need to do minor coding in jsp to see our hard work live.
Open view.jsp of test1-portlet to provide a link to invoke event
e.g.
<%
PortletURL actionURL = renderResponse.createActionURL();
%>
<a href="<%= actionURL.toString() %>">click here to invoke event</a>
do needful imports if required
<%@ page import="javax.portlet.PortletURL" %>

Step 8: Open view.jsp of test2-portlet to show output
just add following line
<%= renderRequest.getParameter("displayText") %>
I have not done any thing extra , I tried to focus on concept and its implementation.

Start the server and if everything is working fine add both portlet test1 and test2 on a page and click the link
provided on test1 portlet you will see the output on portlet test2.

Pls do post your feedbacks.

Thursday, October 29, 2009

Implementing Print functionality for a web content

This is almost straight forward implementation just follow few steps.

Step 1. Get the page url u want to print I am thinking I am on the same page

of which I wanted to print the content . Then I can get the url like this

PortletURL url = PortletURLUtil.getCurrent(renderRequest, mimeResponse or renderResponse);

else you can create the url of the page like this

PortletURL printPageURL = renderResponse.createRenderURL();

and set the required parameter related to youur page plus these extra parameters

printPageURL.setWindowState(LiferayWindowState.POP_UP);
printPageURL.setParameter("viewMode", Constants.PRINT);


sample url will look like this :
PortletURL printPageURL = renderResponse.createRenderURL();
printPageURL.setWindowState(LiferayWindowState.POP_UP);
printPageURL.setParameter("struts_action", "ur_stuts_action_path");
printPageURL.setParameter("ur_param_1", "ur_param_value_1");
printPageURL.setParameter("viewMode", Constants.PRINT);
printPageURL.setParameter("print", String.valueOf(true));

Step 2:
create a boolean variable print with default value false.
eg:
boolean print = ParamUtil.getBoolean(request,"print");

Step 3: Add this code on your page.

<c:choose>
<c:when test="<%= print %>">
<script type="text/javascript">
function printArticle() {
print();
}
</script>
</c:when>
<c:otherwise>

<script type="text/javascript">
function <portlet:namespace />printPage() {
window.open('<%= printPageURL.toString()%>', '', "directories=0,height=480,left=80,location=1,menubar=1,resizable=1,scrollbars=yes,status=0,toolbar=0,top=180,width=640");
}
</script>
</c:otherwise>
</c:choose>

Step 4: Add this code

<c:choose>
<c:when test="<%= print %>">
<span style="float:right">
<liferay-ui:icon image="Print" url="javascript:onclick=printArticle();" label="<%= false %>" />
</span>
</c:when>
<c:otherwise>
<span style="float:right">
<liferay-ui:icon image="Print" url='<%= "javascript:" + renderResponse.getNamespace() + "printPage();" %>' label="<%= false %>" />
</span>
</c:otherwise>
</c:choose>

Thats it
Enjoy !!!

For preview without saving the article in Journal

Hi today I want to share how to implement preview without saving web-content in liferay.
Step 1:
Add following line
<input type="button" value="<liferay-ui:message key="preview" />" onClick="<portlet:namespace />previewArticleNoStructure();" />

Step 2:
write the following function

function <portlet:namespace />previewArticleNoStructure() {
document.<portlet:namespace />fm2.action = "<%= themeDisplay.getPathMain() %>/journal/view_article_content?<%= Constants.CMD %>=<%= Constants.PREVIEW %>&groupId=<%= String.valueOf(groupId) %>&articleId=<%= HttpUtil.encodeURL(articleId) %>&version=<%= version %>&languageId=" + document.<portlet:namespace />fm1.<portlet:namespace />languageId.value + "&type=" + document.<portlet:namespace />fm1.<portlet:namespace />type.value;
document.<portlet:namespace />fm2.target = "_blank";
document.<portlet:namespace />fm2.title.value = document.<portlet:namespace />fm1.<portlet:namespace />title.value;
document.<portlet:namespace />fm2.xml.value = <portlet:namespace />getArticleContentNoStructure();
document.<portlet:namespace />fm2.submit();

}

Step 3:

Write this function

function <portlet:namespace />getArticleContentNoStructure(){

var xsd = "<root available-locales=\"en_US\" default-locale=\"en_US\">";
xsd += "<static-content language-id=\"en_US\">";
xsd += "<![CDATA[";
xsd += window. xsd += "]]>";
xsd += "</static-content>";
xsd += "</root>";
return xsd;
}

that's it .
Enjoy!!!

Thursday, September 10, 2009

Reading tempelates in liferay

Hi Friends,
I have seen many new comers to liferay seems to be struggling regarding the email tempelates.
So I thought why not put the whole procedure in a document which can help. For this reason I am
writing this post may be it is quite simple for many but will be quite helpful for the new comers.


Brief Overview:
If we see in existing liferay source code then we can find the email tempelates regarding

create account and forgot password in com/liferay/portlet/admin/dependencies/ and they are read from there.

In 1 case I can tell you from UserLocalServiceImpl and corresponding entry for each tempelate is there in

portal.properties


Enough theory time to do your self:

1.Just create a folder in ext-impl may be u can choose this path
ext-impl\src\com\mytempelate

2.Write a simple tempelate
eg:
Dear [$TO_NAME$],<br /><br />

Hi this is my first tempelate.<br /><br />


Sincerely,<br />
[$FROM_NAME$]

save this as my_first_tmpl.tmpl


3.make an entry in portal-ext.properties

for our example like this :

ext.myfirst.tempelate=ext-impl\src\com\mytempelate\my_first_tmpl.tmpl
This is just a normal key value pair.

4.Now time to read your tempelate

String firstTemeplate = PrefsPropsUtil.getContent(user.getCompanyId(),"ext.myfirst.tempelate");

or

String firstTemeplate = ContentUtil.get("ext-impl\src\com\mytempelate\my_first_tmpl.tmpl");



5. We can easily replace the content :
String firstTemeplate= StringUtil.replace(firstTemeplate, new String[] {"[$TO_NAME$]","[$FROM_NAME$]"

}, new String[] {

"any_name","any_name"
});

Thats it !!!

Thursday, August 13, 2009

Customizing url and changing default landing after login

Introduction:
Currently when ever we are login in we are getting path like

http://localhost:8080/web/guest/home

First we will try to simplify this url

eg:
Suppose I made a community with name Fquad then I want to access
it as http://fquad.com rather than http://fquad.com:8080/web/guest/home

How to achieve it??

we need to follow few simple steps for it

Step 1: Go to c:\WINDoWS\System32\drivers\etc or search for host file

in host file add a line like this

127.0.0.1 www.fquad.com

Step 2: Stop the sever and start it and try to access the application with

url http://fquad:8080/web/guest/home , if working fine go to step 3

Step 3: Now create a community with name Fquad.

Step 4: Create 2 pages in Fquad community 1 public page and other private page.

Step 5: Go to manage pages of Fquad community click the setting tab and then click

the Virtual Host tab then you can see Public Virtual Host text field fill it with

www.fquad.com

Step 6: Now try to access application using url http://fquad:8080/

Step 7: To remove :8080 is simple just change connector port in tomcat/conf/server.xml

search for line Connector port="8080" protocol="HTTP/1.1 and change 8080 to 80 thats it.

Sometimes it is required to land directly to private page of a community then in portal-ext.properties

add 1 line , portal-ext.properties exist under tomcat\webapps\ROOT\WEB-INF\classes if not there create it

default.landing.page.path=/group/fquad

Wednesday, August 12, 2009

Give a try to ContactListener in ext environment

step 1. create a class that extends ModelListener .

eg. If want to extend ContactListener and want to do some action onAfterCreate then

public class CustomContactListener extends ContactListener {
public void onAfterCreate(BaseModel model) throws ModelListenerException {
try {
super.onAfterCreate(model)

//your code
System.out.println("Conatct info after update: " + contact.getContactId() + ":" + contact.getFirstName());
}
catch (Exception e) {
throw new ModelListenerException(e);
}
}
}

step 2. Make an entry in portal-ext.properties

value.object.listener.com.liferay.portal.model.Contact=\
com.liferay.portal.model.ContactListener,\
com.liferay.portal.model.CustomContactListener

do ant deploy and update contact table entry and check in console whether updated data is coming or not.

Tuesday, August 11, 2009

Using Json in Liferay

Introduction:
We have 2 Service tiers..

The Local tier - this tier has no permission checks and is simply a clean cut implementation of the business logic of the service.

i.e. you set local-service="true" when you created the entity.

e.g.
UserLocalServiceUtil.updateActive(long userId, boolean active) (re, no permission check is made, use with caution).

The Remote Tier - this tier is designed to include your permission checks and finally calls the underlying Local service to actually perform the service operation. This tier is also the one on which ALL web-service methods are generated. All the HTTP, JSON, and SOAP are backed by the methods found in this tier.

i.e. you set remote-service="true" when you created the entity AND you implemented methods in [Entity]ServiceImpl.java rather than leaving it blank.

e.g.
UserServiceImpl.updateActive(long userId, boolean active) (i.e., makes a permission check internally):
public User updateActive(long userId, boolean active)
throws PortalException, SystemException {

if ((getUserId() == userId) && !active) {
throw new RequiredUserException();
}

UserPermissionUtil.check(
getPermissionChecker(), userId, ActionKeys.DELETE);

return userLocalService.updateActive(userId, active);
}


SO, all webservice methods which call their implementation of "updateActive" on the UserService are backed by this method. Also, this means that the caller must be authenticated in order to be tested for permissions... otherwise the call will fail. So, you need to be authenticated, AND you need to have permission.

How does a JSON method get authenticated when it's called through and ajax call? All our JSON services are passed through an AutoLogin Filter which handles the authentication based on authorization cookies.

Abstraction for using Json in Liferay:

Step 1. generate service layer for your entity with remote-service="true"
eg.


Step 2. In [entity]ServiceImpl write a method which you want to call using Json.
eg. updateName(userName) throws Exception{//your code goes here}.

Step 3. Do ant build-service -Dservice.file=your_service_xml_path from ext/ext-impl

Step 4. Do ant deploy from ext.

Step 5. Check file ext-web/docroot/html/js/liferay/ext_service_unpacked.js is updated with your method or not.

Note: In liferay version 5.2.x onwards this file is "ext_service.js".

Step 6. Include js like this in file in which you want to call json.

Step 7. Call method like this
eg:
function updateName(userName) {
var params = {
userName: userName
};
Liferay.Service.your_entity_namespace.entity_name.updateName(params);
}

Monday, August 10, 2009

Creating simple struts Portlet in liferay in 5 min

In struts portlet as compare to Jsp portlet we need to add 2 extra xml files

1.struts-config.xml
2.tiles-defs.xml

We have to modify follwing xml files.

These xml files are located under "ext/ext-web/docroot/WEB-INF"

2.1. portlet-ext.xml
--------------------

<portlet>
<portlet-name>Sample</portlet-name>
<display-name>Sample Struts Portlet</display-name>
<portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class>
<init-param>
<name>view-action</name>
<value>/ext/sample/view</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<resource-bundle>com.liferay.portlet.StrutsResourceBundle</resource-bundle>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>

2.2. liferay-portlet-ext.xml
----------------------------

<portlet>
<portlet-name>Sample</portlet-name>
<struts-path>ext/sample</struts-path>
<use-default-template>false</use-default-template>
</portlet>

2.3. liferay-display.xml
------------------------

add

<portlet id="Sample" />

inside

<category name="category.sample">

2.4. struts-config.xml
----------------------

<action path="/ext/sample/view" forward="portlet.ext.sample.view" />

2.5. tiles-defs.xml
-------------------

<definition name="portlet.ext.sample" extends="portlet" />
<definition name="portlet.ext.sample.view" extends="portlet.ext.sample">
<put name="portlet_content" value="/portlet/ext/sample/view.jsp" />
</definition>


(create the following two jsp files under "/ext/ext-web/docroot/html/portlet/ext/sample")

2.6. init.jsp
-------------

<%@ include file="/html/portlet/init.jsp" %>

2.7. view.jsp
-------------

<%@ include file="/html/portlet/ext/sample/init.jsp" %>
Simple Struts Portlet!

2.8 Language-ext.properties
---------------------------

Add a new entry in the above file,

javax.portlet.title.Sample=Sample Struts Portlet

creating simple jsp portlet in Liferay

For creating simple Jsp portlet in Liferay we have to modify following files.

Following xml files are located under "ext/ext-web/docroot/WEB-INF"

1.1. portlet-ext.xml
--------------------
Add entry for your portlet

<portlet>
<portlet-name>Sample</portlet-name>
<display-name>JSP Portlet Introduction</display-name>
<portlet-class>com.liferay.util.bridges.jsp.JSPPortlet</portlet-class>
<init-param>
<name>view-jsp</name>
<value>/html/portlet/ext/jsp_portlet/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
</supports>
<resource-bundle>com.liferay.portlet.StrutsResourceBundle</resource-bundle>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>

1.2. liferay-portlet-ext.xml
----------------------------
Make an entry for your portlet.

<portlet>
<portlet-name>Sample</portlet-name>
</portlet>

1.3. liferay-display.xml
------------------------
Make an entry for the category in which you want to display your portlet.

<category name="category.sample">
<portlet id="Sample" />
</category>

1.4. view.jsp
-------------

create this file under "ext/ext-web/docroot/html/portlet/ext/jsp_portlet"
and put some contents


do "ant deploy" from "ext-web"

1.5 Language-ext.properties
---------------------------

(under /ext/ext-impl/src/content)

Add two new entries in the above file, this helps us in I18N

javax.portlet.title.Sample=Sample JSP Portlet

category.sample=Example

do "ant deploy" from "ext-impl"