Alimozzaman

Author Archive

I am assuming that you have your Liferay maven based development environment is ready. If not, I would recommend to read out this simple-way-to-setup-liferay-environment-through-maven. This is pretty straight forward and lovely pitch of guideline.

So now you have your environment ready and the directory structure looks like the following image. Yes, we can now start developing a sample hook to achieve some functionalities.

Figure: Liferay Maven based development directory structure.

Project Environment:

  • Linux
  • Liferay 6.x+
  • Maven 2

Create Hook

  • Lets goto your hook directory from command prompt (i.e. cd /home/workspace/example/liferay/src/hook )
  • Type command mvn archetype:generate
  • A list of archetype will come up. Find liferay-hook-archetype from the list and check the number for the same archetype. You will get something like below but number could be changed based on the version.

21: remote -> com.liferay.maven.archetypes:liferay-ext-archetype (Provides an archetype to create Liferay extensions.)

22: remote -> com.liferay.maven.archetypes:liferay-hook-archetype (Provides an archetype to create Liferay hooks.)

23: remote -> com.liferay.maven.archetypes:liferay-layouttpl-archetype (Provides an archetype to create Liferay layout templates.)

24: remote -> com.liferay.maven.archetypes:liferay-portlet-archetype (Provides an archetype to create Liferay portlets.)

In next step, you need to select Liferay Version. So select version accordingly (i.e. 6.1.0)

  • Next, define proper groupId (i.e. com.example.liferay)
  • Define proper artifactId (i.e. samplehook)
  • Specify version (i.e. 1.0-SNAPSHOT)
  • Package(i.e. com.example.liferay)
  • Confirm all the values and hit ‘Y’ for confirmation

Yahooooooooo , Your are done !!! Your Hook is created. Now you know how to create a hook in a minute, great (y)

Before deploying your package, just confirm your Portal deploy path into your auto generated pom.xml inside your sample hook ( /home/workspace/example/liferay/src/hook/sample-hook/pom.xml )

Open the pom.xml in a text editor and find the

…………..

<properties>

<liferay.auto.deploy.dir>/home/workspace/example/liferay/bundle/deploy</liferay.auto.deploy.dir>

<liferay.version>6.1.0</liferay.version>

</properties>

</project

…………….

Package and Deploy

Go to sample-hook directory and run

mvn clean package

To deploy the hook into your Liferay bundle you can run

mvn clean install liferay:deploy

Well done, you have created your sample hook with maven and deployed it to your Liferay bundle.

Are you thinking, What is Liferay hook system?

I am not gonna explain using lot of words because some guys already explained it very nicely. You can read this article to get the idea of Liferay Hook Plugin, here you go http://www.liferay.com/community/wiki/-/wiki/Main/Portal+Hook+Plugins

But then again, let me give a brief in one or two lines.

In brief, using hook plugin, we can change liferay JSP, Portal Properties, Event, Services, defining your own Model listener, overriding/adding struts actions etc.

Now I am going to show you how and where we can change those functionalities.

Overridding a JSP

Now you want to change any look and feel of an existing portlet of Liferay. For example – I want to change a jsp file of the Blog Portlet.

Okay, lets point to <sample-hook>/src/main/webapp/WEB-INF/liferay-hook.xml and open that file in an editor and the add <custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

So it will look like the following.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

</hook>

Now copy any blog portlet jsp file, for example – I want to override edit_entry.jsp, and put that into

<sample-hook>/src/main/webapp/META-INF/custom_jsps/html/portlet/blogs

Change anything your want into that file and deploy the hook. You would see that the default look and feel got changed if u change anything there. You are done with JSP overriding.

Note : If you want to know what Liferay did with the original file, then goto your <liferay-bundle>/webapp/ROOT/WEB-INF/html/portlet/blogs/ and u can find that the original file renamed edit_entry.portal.jsp

Portal Properties

Well, if you want to override any portal property value, you need to add

<portal-properties>portal.properties</portal-properties> into your liferay-hook.xml like the following.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

</hook>

Now create a portal.properties into your <sample-hook>src/main/resources and change the value. For example – by default terms.of.use.required=true into liferay. You can put that into your hook portal.properties and change it to false.

#

# Set this to true if all users are required to agree to the terms of use.

#

terms.of.use.required=false

Deploy the hook and check the term’s page. You might need to restart the tomcat if u dont see its not effecting.

Event

Liferay has a few event handler connection points throughout its lifecycle.

The available events are:

  • Application Startup Events (application.startup.events)
  • Login Events (login.events.pre, login.events.post)
  • Service Events (servlet.service.events.pre, servlet.service.events.post)

Now I want to override any event with my custom implementation, for example – application.startup.events, where I want to change some default behavior. So I can put that property into <sample-hook>src/main/resources/portal.properties and override the default value.

Example : In liferay source, the default value of application.startup.events property is

application.startup.events=com.liferay.portal.events.AppStartupAction

I can change that to custom one like the following into portal.properties

application.startup.events=com.liferay.samplehook.events.StartupAction

package com.liferay.samplehook.actions;

import com.liferay.portal.kernel.dao.orm.QueryUtil;

import com.liferay.portal.kernel.events.ActionException;

import java.io.InputStream;

import java.util.*;

/**

* Action called on startup, used to create initial data.

*

* @author Rony

*

*/

public class StartupAction extends SimpleAction {

public void run(String[] ids) throws ActionException {

try {

doRun(GetterUtil.getLong(ids[0]));

} catch (Exception e) {

throw new ActionException(e);

}

}

// Do your custom coding here.

}

Do your customization in AppStartupAction, deploy it and restart the tomcat.

Or you can also define override event using liferay-hook.xml like the following

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<event>

     <event-class>com.liferay.samplehook.ServicePreAction</event-class>
     <event-type>servlet.service.events.pre</event-type>
  </event>

</hook>

Now you know two ways/process to override liferay events.

Done!

Overriding a Portal Service

Liferay provide dummy wrapper classes for all of its services, for example BlogsEntryLocalServiceWrapper is created as a wrapper of the BlogsEntryLocalService that is used to add, remove and retrieve blog entry. To modify the functionality of BlogsEntryLocalService from our hook, all we have to do is create a class that extends from BlogsEntryLocalServiceWrapper, override some of its methods or what ever you want, then we have to configure so that Liferay pick this extension instead of default wrapper class.

Sample code//

package com.liferay.samplehook.service;

import com.liferay.portal.kernel.exception.PortalException;

import com.liferay.portal.kernel.exception.SystemException;

public class CustomBlogsEntryLocalServiceImpl extends CustomBlogsEntryLocalServiceWrapper{

//Add custom coding

}

Next, lets ask Liferay to pick this class instead of the default one. Edit your liferay-hook.xml and add the <service> tags like the follow. Deploy the hook and restart the tomcat and check the effect.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<event>

<event-class>com.liferay.samplehook.ServicePreAction</event-class>
<event-type>servlet.service.events.pre</event-type>

  </event>

  <service>

<service-type>com.liferay.portal.service.BlogsEntryLocalService </service-type>

<service-impl>com.liferay.samplehook.service. CustomBlogsEntryLocalServiceImpl </service-impl>

  </service>

</hook>

We are done and we can follow this technique to override other Liferay services.

Model Listeners

  1. Overriding default Model Listener: In Liferay, we have some model listeners and we need to override them for sometimes. In hook portal.properties, we can define our own class to override them.

Lets take LayoutSetListener as an example and we want to set our own theme for all community layouts.

In Liferay portal.properties, we have a Listener class like this: value.object.listener.com.liferay.portal.model.LayoutSet=com.liferay.portal.model.LayoutSetListener

Now lets define our own class into Hook portal.properties to customize the layout like this:

value.object.listener.com.liferay.portal.model.LayoutSet= com.liferay.samplehook .modellisteners.LayoutSetListener

Example code to add custom theme for all group layouts by default instead of default Classic theme.

public class LayoutSetListener extends BaseModelListener<LayoutSet> {

public void onAfterCreate(LayoutSet layoutSet) throws ModelListenerException {

try {

Group group = GroupLocalServiceUtil.getGroup(layoutSet.getGroupId());

if (group.isCommunity()) {

addCommunityLayouts(group);

}

} catch (Exception e) {

throw new ModelListenerException(e);

}

}

protected void addCommunityLayouts(Group group) throws Exception {

// Look and Feel

updateLookAndFeel(group);

}

private void updateLookAndFeel(Group group) throws Exception {

LayoutSetLocalServiceUtil.updateLookAndFeel(group.getGroupId(), “sample_WAR_sampletheme”, “”, “”, false);

}

}

We are done adding our own theme overriding LayoutSet model.

  1. Add custom Model Listener: If we want to add our own Model Listener, we can also easily achieve that using hook system.

Lets say we want to add a blog post Listener, we can inform liferay to pickup our custom model by adding a <model-listener> tag into the hook liferay-hook.xml file. So your liferay-hook.xml will look like this.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<event>

 <event-class>com.liferay.samplehook.ServicePreAction</event-class>
 <event-type>servlet.service.events.pre</event-type>
</event>

    <service>

<service-type>com.liferay.portal.service.BlogsEntryLocalService </service-type>

<service-impl>com.liferay.samplehook.service. CustomBlogsEntryLocalServiceImpl </service-impl>

  </service>

   <model-listener>
    <model-listener-class>com.liferay.samplehook .modellisteners.MyBlogEntryListener
    </model-listener-class>
     <model-name>com.liferay.portlet.blogs.model.BlogsEntry</model- name>
  </model-listener>
</hook>

public class MyBlogEntryListener implements ModelListener {
  //Custom code here.
}
You can also Look into the post for detail at
 http://www.liferay.com/community/wiki/-/wiki/Main/Portal+Hook+Plugins

We are done!

Overriding/Adding struts actions

We can also override and add new Struts-actions from Hook System. Edit your liferay-hook.xml and add the following lines.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<event>

  <event-class>com.liferay.samplehook.ServicePreAction</event-class>
  <event-type>servlet.service.events.pre</event-type>
 </event>

    <service>

<service-type>com.liferay.portal.service.BlogsEntryLocalService </service-type>

<service-impl>com.liferay.samplehook.service. CustomBlogsEntryLocalServiceImpl </service-impl>

  </service>

  <model-listener>
    <model-listener-class>com.liferay.samplehook .modellisteners.MyBlogEntryListener
    </model-listener-class>
     <model-name>com.liferay.portlet.blogs.model.BlogsEntry</model- name>
  </model-listener>

   <struts-action>
    <struts-action-path>/portal/sample</struts-action-path>
    <struts-action-impl>com.liferay.samplehook.action.SampleStrutsAction</struts-action-impl> 
</struts-action>
</hook>
This has been explained in detail at http://www.liferay.com/web/mika.koivisto/blog/-/blogs/7132115

Language Bundles

We can also add new language package or override existing translation from the hook like the following way.

<?xml version=”1.0″?>

<!DOCTYPE hook PUBLIC “-//Liferay//DTD Hook 6.1.0//EN” “http://www.liferay.com/dtd/liferay-hook_6_1_0.dtd”&gt;

<hook>

<custom-jsp-dir>/META-INF/custom_jsps</custom-jsp-dir>

<portal-properties>portal.properties</portal-properties>

<language-properties>content/Language_en.properties</language-properties>

<language-properties>content/Language_nl.properties</language-properties>

<language-properties>content/Language_fi.properties</language-properties>

<event>

  <event-class>com.liferay.samplehook.ServicePreAction</event-class>
  <event-type>servlet.service.events.pre</event-type>
 </event>

    <service>

<service-type>com.liferay.portal.service.BlogsEntryLocalService </service-type>

<service-impl>com.liferay.samplehook.service. CustomBlogsEntryLocalServiceImpl </service-impl>

  </service>

   <model-listener>
    <model-listener-class>com.liferay.samplehook .modellisteners.MyBlogEntryListener
    </model-listener-class>
    <model-name>com.liferay.portlet.blogs.model.BlogsEntry</model- name>
  </model-listener>

   <struts-action>
    <struts-action-path>/portal/sample</struts-action-path>
    <struts-action-impl>com.liferay.samplehook.action.SampleStrutsAction</struts-action-impl> 
</struts-action>
</hook>

Great,now we know how to develop a hook using Maven what we can achieve
from Liferay Hook system at a glance.


Please make your comments or add suggestion to make this much better understanding for the community.
Tags: ,

By default JIRA planning board of GreenHopper  drag-drop not wokring. I spent some time and found the process that I might need to share to help if u face similar problem.

 

1) Login as Admin into JIRA and goto Admin mode.
2) Select project from Project navigation.
3) Select Classic mode from Agile dropdown list.
4) Select classic planning board
5) Select Configuration from Tools.
6) From general tab, select project templatescrum” from project template list.
7) Done, you can enjoy drag drop in JIRA planning mode.

Struts2 liferay 6.0.5+ all  User list and & Users detail portlet. This is very useful for any site where people can see all users and there detail. Its also good for the developers to have maven based struts2 development sample.Please give your feedback.

Please have a look at the userList portlet

I have contributed a nice looking Liferay 6.0.5+ theme, Lotus theme. I wish it will little help to the community. Also planning to contribute more.

 

Thanks

 

Here is the codes to migrate user & password from drupal 6 to drupal 7.  It works fine for me.

// connect with mysql server

$mysql_server = $server; // Server name
$mysql_userName = DATABASE_USER_NAME;
$mysql_password = DATABASE_PASSWORD;
$connection = mysql_connect($mysql_server,$mysql_userName,$mysql_password);

// query

$query = “SELECT * FROM users”;
$count = 0;
$result = mysql_db_query(DATABASE_NAME, $query) or die(mysql_error() . “<br />” . $query);
while($row = mysql_fetch_array($result))
{
//if($count++ > 10) break;

if($row[uid] == 0 || $row[uid] == 1) continue;

//require_once DRUPAL_ROOT . ‘/’ . variable_get(‘password_inc’, ‘includes/password.inc’);
$new_password_hash = user_hash_password($row[pass], 11);
if($new_password_hash){
$new_password_hash = ‘U’.$new_password_hash;
}
$data = array(
‘uid’ => $row[uid],//db_next_id(db_query(‘SELECT MAX(uid) FROM {users}’)->fetchField()),
‘name’ => $row[name],
‘pass’ => $new_password_hash,
‘mail’ => $row[mail],
‘theme’ => $row[theme],
‘signature’ => $row[signature],
‘signature_format’ => $row[signature_format],
‘created’ => $row[created],
‘access’ => $row[access],
‘login’ => $row[login],
‘status’ => $row[status],
‘timezone’ => $row[timezone],
‘language’ => $row[language],
‘picture’ => !empty($row[picture])?1:0,
‘init’ => $row[init],
‘data’ => $row[data],
);

drupal_write_record(‘users’, $data);
}

Connection pooling is a technique of creating and managing a pool of connections that are ready for use by any thread that needs them.

This technique of “pooling” connections is based on the fact that most applications only need a thread to have access to a JDBC connection when they are actively processing a transaction, which usually take only milliseconds to complete. When not processing a transaction, the connection would otherwise sit idle. Instead, connection pooling allows the idle connection to be used by some other thread to do useful work

more on ….. http://dev.mysql.com/tech-resources/articles/connection_pooling_with_connectorj.html

Tags:

1. To save a single image with node.

global $user;

// Build the node.

$node = new stdClass();

$node->type = $node_type;

$node->uid = $user->uid;

$node->name = $user->name;

$node->title = isset($title) ? $title : $name_place;

$node->body = isset($body) ? $body : $body_content;

// Image file path.

$image = file_directory_path().’/ example.jpg’’;

// Load up the CCK field. First parameter image field name and second parameter node type. It can be chnaged to any field name and also and node type.

$field = content_fields(‘field_image’,“page”);

// Load up the appropriate validators

$validators = array_merge(filefield_widget_upload_validators($field), imagefield_widget_upload_validators($field));

// Store file path.

$files_path = filefield_widget_file_path($field);

// Create the file object, replace existing file with new file as source and dest are the same

$file = field_file_save_file($image, $validators, $files_path, FILE_EXISTS_REPLACE);

// put the file into node image field.

$node->field_image = array( 0 => $file);

// Set the node’s defaults… (copied this from node and comment.module)

$node_options = variable_get(‘node_options_’. $node->type, array(‘status’, ‘promote’));

$node->status = in_array(‘status’, $node_options);

$node->promote = in_array(‘promote’, $node_options);

if (module_exists(‘comment’)) {

$node->comment = variable_get(“comment_$node->type”,   COMMENT_NODE_READ_WRITE);

}

$node = node_submit($node);

node_save($node);

2. To save multiple images with node

3.  global $user;

4.  // Build the node.

5.  $node = new stdClass();

6.  $node->type = $node_type;

7.  $node->uid = $user->uid;

8.  $node->name = $user->name;

9.  $node->title = isset($title) ? $title : $name_place;

10.$node->body = isset($body) ? $body : $body_content;

11.$files = array();

12.

13.for($i =0;$i<10;$i++){

14.

15.// Image file path.

16.$image = file_directory_path().’/example.jpg’;

17.

18.// Load up the CCK field. First parameter image field name and second parameter node type. It can be chnaged to any field name and also and node type.

19.

20.$field = content_fields(‘field_image’,“page”);

21.

22.// Load up the appropriate validators

23.$validators = array_merge(filefield_widget_upload_validators($field), imagefield_widget_upload_validators($field));

24.

25.// Store file path.

26.$files_path = filefield_widget_file_path($field);

27.// Create the file object, replace existing file with new file as source and dest are the same

28.$file = field_file_save_file($image, $validators, $files_path, FILE_EXISTS_REPLACE);

29.

30.$files[$i] = $file;

31.

32.}

33.

34.// put the files into node image field.

35.$node->field_image = $files;

36.

37. // Set the node’s defaults… (copied this from node and comment.module)

38.$node_options = variable_get(‘node_options_’. $node->type, array(‘status’, ‘promote’));

39.$node->status = in_array(‘status’, $node_options);

40.$node->promote = in_array(‘promote’, $node_options);

41.if (module_exists(‘comment’)) {

42. $node->comment = variable_get(“comment_$node->type”,   COMMENT_NODE_READ_WRITE);

43.    }

44.

45.$node = node_submit($node);

46.node_save($node);

Tags: