Tuesday, August 31, 2010

Liferay: Exposing Webservice & access using Axis Client...

Basically in liferay, we create services using service builder, which is like child's play. In service.xml, we need to put local and remote both attributes, and it will generate class for web service also. 

The link shows steps,
- To generate web services using service builder.
- To generate WSDD changes.
- To access web service from Axis client

Friday, August 20, 2010

Liferay Wrapper Plugins ...

Very nice article about liferay core functionality extension. You can create wrappers around core services and it will be in service when you compile-deploy it! Isn't that's great? Check the link.

Tuesday, August 17, 2010

Liferay: Make Custom "Add Application" portlet ...

Sometimes client will amaze us by giving very very complex requirements which not seem to be a value adding thing. But still we need to complete it as it's our work :). Same happened here, when i need to make a portlet replicating the "Add Application" liferay portlet.

Though its not new, it has given me chance to see how "Add Application" menu works.

Basically liferay uses a Javascript file named layout_configuration.js to call the layout_configuration portlet.

Liferay has in-built portlet named layout_configuration for this functionality. It renders the same using LayoutConfiguration.toggle('87'); where 87 is the portlet ID.

Find the following portlet in file portal\portal-web\docroot\WEB-INF\liferay-portlet.xml,

 <portlet>  
         <portlet-name>87</portlet-name>  
         <icon>/html/icons/default.png</icon>  
         <struts-path>layout_configuration</struts-path>  
         <use-default-template>false</use-default-template>  
         <show-portlet-access-denied>false</show-portlet-access-denied>  
         <show-portlet-inactive>false</show-portlet-inactive>  
         <restore-current-view>false</restore-current-view>  
         <private-request-attributes>false</private-request-attributes>  
         <private-session-attributes>false</private-session-attributes>  
         <render-weight>50</render-weight>  
         <system>true</system>  
     </portlet>  

Also find the portlet in file \portal\portal-web\docroot\WEB-INF\portlet-custom.xml as below,

 <portlet>  
         <portlet-name>87</portlet-name>  
         <display-name>Layout Configuration</display-name>  
         <portlet-class>com.liferay.portlet.StrutsPortlet</portlet-class>  
         <init-param>  
             <name>view-action</name>  
             <value>/layout_configuration/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>  
     </portlet>  

You will find the path layout_configuration in files struts-config.xml and tiles-defs.xml in the same folder.

In struts-config,

     <!-- Layout Configuration -->  
     <action path="/layout_configuration/templates" forward="portlet.layout_configuration.templates" />  
     <action path="/layout_configuration/view" forward="portlet.layout_configuration.view" />  

In tiles-defs,

 <!-- Layout Configuration -->  
 <definition name="portlet.layout_configuration" extends="portlet">  
     <put name="portlet_decorate" value="false" />  
 </definition>  
 <definition name="portlet.layout_configuration.templates" path="/portlet/layout_configuration/templates.jsp" />  
 <definition name="portlet.layout_configuration.view" extends="portlet.layout_configuration">  
     <put name="portlet_content" value="/portlet/layout_configuration/view.jsp" />  
 </definition>  

At first I started learning what liferay is doing. Basically in this portlet, liferay generates the HTML layout of all portlets in liferay-display.xml as per the category. It makes the whole tree structure of categories and subcategories. This portlet is not described in liferay-disaply.xml, so it will not be disaplayed in the tree.

Then it loads this portlet on onclick event of "Add Application" menu click. It calls the portal servlet at url /portal/render_portlet, which will render the portlet and shows the result HTML in popup dialog.

Check the javascript function from layout_configuration.js file,

 toggle: function(ppid) {  
         var instance = this;  
         var plid = themeDisplay.getPlid();  
         var doAsUserId = themeDisplay.getDoAsUserIdEncoded();  
         if (!instance.menu) {  
             var url = themeDisplay.getPathMain() + '/portal/render_portlet';  
             var popupWidth = 250;  
             var body = jQuery('body');  
             body.addClass('lfr-has-sidebar');  
             instance._dialog = Liferay.Popup(  
                 {  
                     width: popupWidth,  
                     message: '<div class="loading-animation" />',  
                     position: [5,5],  
                     resizable: false,  
                     title: Liferay.Language.get("add-application"),  
                     onClose: function() {  
                         instance.menu = null;  
                         body.removeClass('lfr-has-sidebar');  
                     }  
                 }  
             );  
             jQuery.ajax(  
                 {  
                     url: url,  
                     data: {  
                         p_l_id: plid,  
                         p_p_id: ppid,  
                         p_p_state: 'exclusive',  
                         doAsUserId: doAsUserId  
                     },  
                     success: function(message) {  
                         instance._dialog.html(message);  
                         instance._loadContent();  
                     }  
                 }  
             );  
         }  
     }  

After that, the javascript adds click and drag-drop even for all portlet divs of that popup dialog. So that user will be able to add the portlet into page by click OR drag-drop.

I need to show list of portlets of specified categories only without the categories.So i need to copy this portlet as it is and filter as per the category.

First of all i choosen the plugins environment for my new portlet, but it failed because i need to use the static resource named WebAppPool as per the code below,

PortletCategory portletCategory = (PortletCategory)WebAppPool.get(String.valueOf(company.getCompanyId()), WebKeys.PORTLET_CATEGORY);

This pool is maintained by liferay, it has all the categories on server startup. Now liferay loads the war file of plugin portlet when we add the portlet in page. So new classloader will be used here. And in java, child classloader can't access parent classloader's resources.

So i decided to move to ext environment. I made the new "Custom Add Application" portlet in ext with some code changes.

1. Need to filter the categories, for that i used portlet's init-param to define my including categories as below,

 <init-param>  
         <name>includeCategories</name>  
         <value>myCategory,yours</value> <!-- Comma seperated category names, sub-categories will not be filtered...-->  
     </init-param>  

2. Changed the code in view.jsp, included the categories only given in the init-param of above step and will show in HTML un-ordered list. Sent all categories to view_category.jsp.

3. Changed the code in view_category.jsp, displayed the portlets from all categories of above step as HTML list-items. It only shows portlets, ignoring the categories from view.

4. Same JS file has been used with different name to keep the drag-drop support for portlet list-items. Changed the JS file accordingly. Like ID for the result element is passed because now we don't want it to be in popup dialog etc...

5. Made new theme from classic, and changed the navigation.vm to show the above portlet as navigation menu item.

Though this was not extra-ordinary development, i got the chance to look into some internals of Liferay's odd style of developing a complex product, which may give us harsh times if touched :) (Isn't its too complex for a portal?).

Tuesday, August 3, 2010

Some Useful Linux commands while deploying...


While deploying any WAR in tomcat on Linux platform, most problem we have faced is Linux terminal commands. In all industries you will mostly have a Linux server for test server,staging server etc...So most of the times developers need to test the code locally and then deploy it in centralized test OR development server where other can access and test it.

The steps will be same for all programmers. We get an email from so called IT people with deployment instruction having IP, username ,password (Which is always weird and we always copy paste it :)) etc... We Linux into the server using Putty or some other terminal client. But most of windows developers will face problem here. So some commands which are very easy to remember are,

- cd (Same as windows)
- pwd (Shows current working dir)
- ./ (this folowing with script filename, will execute the script. You can also use 'su')
- ps ax (Shows running process details, with process ID. like windows task manager shows.)
- grep hi (Finds the string 'hi')
- kill -9 567 (Kills process with ID 567)

Now in Linux if you have many servers running and you want to stop only specific one then you can use following combination,
- ps ax|grep projDir (This will show the process having projDir in sys variable.)

After that we can kill that process easily.

Before running startup.sh you must have set variable for JAVA_HOME, so that tomcat can find the java env.

There are other commands which are for changing file permissions (Read only, executable etc...) but will post it later.

-- Update By Kunal --
- scp sourcepath user@destserverhost:destpath (Secure copy of file from one linux server to another)

Example

scp /root/example.html root@66.235.111.88:/home/example