Sunday, September 6, 2015

Working with Dynamic Data Lists in Liferay Part-I

Liferay have provided the way to create new data definition so that we can easily create new data list and we can use it store data. Dynamic data list way of design our data model and store that data as for our desired models.

We will define our data definition and we can create different data list based on the definition then we can store the data as for defined model. Data List are associated with sites.

Liferay have given very good user Interface to create new definitions and we can display these definition list to capture data from end users.

These we can use in real time requirement like To Do List, Contact US, Feedback and Meeting Minutes.

Data Definition:

Data Definition are data model like data structure

Data List:

Data List is use the data definition and it will be separate unit the data stored is associate with data list.

These are steps to use Liferay Dynamic Data List.

Define Data List Definition
Create Data List based on Definition
Display List to capture data from End User.

Liferay have provided few data definitions.

Using Existed Dynamic Data Definitions.

Liferay have provide following definition.


Using Existed Definition to create Data List

Login as Portal Administrator


Now go to Site Administration and then select content in the site administration.




Once click on Content then it will launch Administration Dash board there you can find Dynamic Data List. Click on that so that it will launch dynamic data list user interface screens.




Now we will create new Data List so click on Add button then it will launch Create new data List screen.


Once click on Add it will launch screen will ask details to create new data list. Assume we are going to create Contact Us Data list. Give following input data.

Name: Product Contact Us
Description:  Product Contact Us




To create new data list we need to select relevant Data Definition so click on Data Definition select button it will show available definitions. In the list select Contact Us data definition in the list.



Now you can see selected Contact us Definition 



Finally click on save then then new data list will be created and it will use the contact us definition.



We ready with new data list and now we can use this list to capture the data.

Create one new page. Go to home page. Left site you can see the Admin controls there click on Add



Click on page tab then give page name and select layout for page then click on Add page then page will be created.



Go to newly created page now we have to add the Dynamic Data List Display Portlet to page.
Go to Add Application and select Dynamic Data List Display Portlet then click on add portlet then it will be added to the page.



You can see Select List and Add List controls to portlet boron now click on Select List link

Once click on Select List it will display list of dynamic list and select desired list then save it finally close the popup and list will be associated with the portlet.




Select Product Contact Us list click on save then Dynamic Data List will be associated to the portlet.



Once click on Add button then Data List will be displayed in the page.


Fill the form then click on publish data will be stored and you can see the data in the portlet.



This how we can use existed data definitions from that we can create new data list. These list we can display through Dynamic Data List Display portlet and there we can fill the list and save the data.

Author

Saturday, September 5, 2015

Java Reflection in Liferay

Reflection is the way of examining/modifying runtime the behaviour of the class at run time.
Reflection make the possibility of inspect the classes, methods, fields, interfaces without knowing the class names at compile time. We can also instantiate the class and invoke methods at run time.

Generally application development we can create object for class that is available in current class path or server class path means class should be available in the classes directory of your web application or it should be in web application lib directory or it should be in sever lib directory then only we can create object and then invoke methods.

Generally In the server we may have deployed different application and each application is different context and the classes or jar available in each context not shareable to each other until we place these jar files in the server lib directory.

Each web application related jar file we cannot place in server lib directory because until jar file common to all application then it’s good to place in server lib.

Some time we may have minimal need to invoke the methods of the class and the class not available in the current application class loader and it might be available in the other application context.

We have two ways

We need make the jar file available to the required application class path or class loader.
We can use Reflection API to achieve the requirement.

We need make the jar file available to the required application class path or class loader

We just take other application jar file and place into current application lib directory so that we can instantiate object and invoke methods but this not recommended for minimal usage and when we change some implementation in the class again we need update the jar file and place into the current application lib directory.

Reflection API

JAVA Reflection API is good way to instantiate and invoke the methods even though class not available in the current class loader or current class path.

Liferay Class Loaders

Liferay we have different class loader.

Liferay Global Class Loader
Portal Class Loader.
Portlet Class Loader

Liferay Global Class Loader

Liferay Global Class Loader will load the all jar files and make the classes available to entire Liferay portal and we can use these classes anywhere like portal development and plugins development. Generally these jars available in tomacat/lib/ext path and the important jar is portal-service.jar. All these classes will be loaded by Liferay Global Class Loader.

Portal Class Loader

Portal Class loader load all Liferay implementation classes and these classes available in the portal development and all jars available in the ROOT/WEB-INF/lib will be loaded by Portal Class Loader.

Portlet Class Loader

In Liferay development each plugin portlet have its own class loader that is portlet class loader and these class loader make the available to within the portlet and these jars available in PortletName/WEB-INF/lib

In Liferay Portlet development we may have following scenarios when we develop Liferay Plugins Portlet Development.

Using the classes in the Liferay Global Lib
Using Classes in the Portal Class loader
Using classes which are in other plugin Class Loader.

Using the classes in the Liferay Global Lib

In the Liferay development we cannot get any issues to use classes in global class loader and we can instantiate the object and invoke the methods.

Using Classes in the Portal Class loader

Portal class loader classes not available to plugin portlet so in this case we have use reflection API

Using classes which are in other plugin Class Loader.

One plugin portlet classes are not available to other plugin portlet so we need reflection API.

Note:

When we develop hook plugin, EXT plugins then all class loaders are available so we don’t get any issues.

Sharing Service Layer between to Plugin Portlets

Liferay have given way to share service layer between to plugin portlet so we don’t have any issues in the calling services between two plugin contexts.


In the dynamic query API we have provision to load portal class loader classes which are related to service layer using Porta Class loader and also we have portlet class loader.

If the scenario which not belongs to above then we will use Reflection API in Liferay call other class methods which are in different class loaders.

Reflection API using Portal Level classes

Liferay have implemented the Reflection API and we use the following util classes to invoke methods which are in different class loaders


ClassResolverUtil
PortalClassInvoker
PortletClassInvoker


Step: 1

We need to create method and here we will specify the required class, required method to invoke and it parameters types.

If objects then we will use as follows to parameters types in the reflection

Object
Declared in Reflection Method Key
String
String.class
Long
Long.class
Student
Student.class
User
User.class

Primitive Types
Declared in Reflection Method Key
int
Integer.TYPE
long
Long.TYPE


Primitive array Types
Declared in Reflection Method Key
new long[]{  }
long[].class
new int[]{  }
int[].class


Example to create method key for portal level class


MethodKey liveUsersDeleteGroup = 
newMethodKey(ClassResolverUtil.resolveByPortalClassLoader(
"com.liferay.portal.liveusers.LiveUsers"),
"deleteGroup", new Class[] { Long.TYPE, Long.TYPE });



MethodKey leaveGroup = new MethodKey(
ClassResolverUtil
.resolveByPortalClassLoader("com.liferay.portal.liveusers.LiveUsers"),
"leaveGroup", new Class[] { Long.TYPE, Long.TYPE, long[].class });


Method Key need three Parameters i.e. Class Name with class loader type, Method Name and Type of the parameters as Object Array

Step: 2

Now we need to invoke the method with passing required parameter values. We will use invoke method on PortalClassInvoker and it will take method key object and parameter values as object array. Make sure the order of parameters that we declared in the MethodKey object creation.

Syntax:


Class:

PortalClassInvoker

Method:

public static Object invoke(boolean newInstance, MethodKey methodKey, Object... arguments)


Example Usage


PortalClassInvoker.invoke(true, liveUsersDeleteGroup, new Object[] {
themeDisplay.getCompanyId(), deleteGroupId });



PortalClassInvoker.invoke(true, leaveGroup, new Object[] {
themeDisplay.getCompanyId(), groupId, removeUserIdsLong });


If the Original method return some values then we will get it as Object when we invoke through the Reflection call.

Note:

 Parameter types and order we need to make sure.

Complete Example:


<%
long companyId=themeDisplay.getCompanyId();
String portalLevelClassName="com.liferay.portal.liveusers.LiveUsers";
String requiredPortalLevelMthodName="getSessionUsers";
Class[] parameterTypePortalArray={Long.TYPE};
Object[] valuesPortalArray={companyId};
MethodKey getSessionUsers = new MethodKey(ClassResolverUtil.resolveByPortalClassLoader(portalLevelClassName),
requiredPortalLevelMthodName,parameterTypePortalArray);
Object sessionUsersObject=PortalClassInvoker.invoke(true,getSessionUsers,valuesPortalArray);
out.println("sessionUsersObject:<br/>"+userObject);

%>



Reflection API using Portlet Level classes

Assume we have Plugin PortletA and Plugin PortletB we want invoke some methods which are in PortletA from PortletB

Portlet Context:  PortletA-portlet

Finding Portlet Context.



Portlet Id: PortletA_WAR_PortletAportlet

Finding Porttet Id

Go portlet Maximized window state from portlet configuration


Find Portlet id from requested URL


We have implemented some Util class and methods in Plugin PortletA as follows


package com.meera.portleta.util;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;
public class PortletAUtil {
public static User getUser(long userId) throws PortalException, SystemException {
return UserLocalServiceUtil.getUser(userId);
}
public static String  getMessage(String message){
return "Hi Meera syas" +message;
}
}


Now we will invoke PortletA method from PortletB

Step: 1

Create MethodKey Object


MethodKey getUser = new MethodKey(ClassResolverUtil.resolveByPortletClassLoader(className,portletContext),
requiredMthodName,parameterTypeArray);



Step: 2

Invoke method using PortletClassInvoker

Syntax


Class:

PortletClassInvoker

Method:

public static Object invoke(boolean newInstance, String portletId, MethodKey methodKey,Object... arguments)


Example Code in PortletB JSP  page.


<h4>1:PortletB invoking method which is in Portlet A class Loader Using Reflection</h4>
<%
long userId=themeDisplay.getUserId();
String className="com.meera.portleta.util.PortletAUtil";
String portletContext="PortletA-portlet";
String requiredMthodName="getUser";
Class[] parameterTypeArray={Long.TYPE};
Object[] valuesArray={userId};
String portletId="PortletA_WAR_PortletAportlet";
MethodKey getUser = new MethodKey(ClassResolverUtil.resolveByPortletClassLoader(className,portletContext),
requiredMthodName,parameterTypeArray);
Object userObject=PortletClassInvoker.invoke(true,portletId,getUser,valuesArray);
out.println("userObject:<br/>"+userObject);
%>


Note:

In the above example we implemented method in the PortletA plugin context and we are invoking in PortletB JSP page.


Complete Code Example Calling Methods from Portal and Portlet Level class loader classes.

View.jsp in PortletB


<%@page import="com.liferay.portal.kernel.util.PortalClassInvoker"%>
<%@page import="com.liferay.portal.kernel.util.PortletClassInvoker"%>
<%@page import="com.liferay.portal.kernel.util.ClassResolverUtil"%>
<%@page import="com.liferay.portal.kernel.util.MethodKey"%>
<%@page import="java.util.Map"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %>
<%@taglib uri="http://liferay.com/tld/portlet" prefix="liferay-portlet" %>
<%@taglib uri="http://liferay.com/tld/security" prefix="liferay-security" %>
<%@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" %>
<portlet:defineObjects />
<liferay-theme:defineObjects />

<h4>1:PortletB invoking method which is in Portlet A class Loader Using Reflection</h4>
<%
long userId=themeDisplay.getUserId();
String className="com.meera.portleta.util.PortletAUtil";
String portletContext="PortletA-portlet";
String requiredMthodName="getUser";
Class[] parameterTypeArray={Long.TYPE};
Object[] valuesArray={userId};
String portletId="PortletA_WAR_PortletAportlet";
MethodKey getUser = 
new MethodKey(ClassResolverUtil.resolveByPortletClassLoader(className,portletContext),
requiredMthodName,parameterTypeArray);
Object userObject=PortletClassInvoker.invoke(true,portletId,getUser,valuesArray);
out.println("userObject:<br/>"+userObject);
%>
<h4>2:PortletB invoking method which is in Portal class Loader Using Reflection</h4>
<%
long companyId=themeDisplay.getCompanyId();
String portalLevelClassName="com.liferay.portal.liveusers.LiveUsers";
String requiredPortalLevelMthodName="getSessionUsers";
Class[] parameterTypePortalArray={Long.TYPE};
Object[] valuesPortalArray={companyId};
MethodKey getSessionUsers = 
new MethodKey(ClassResolverUtil.resolveByPortalClassLoader(portalLevelClassName),
requiredPortalLevelMthodName,parameterTypePortalArray);
Object sessionUsersObject=PortalClassInvoker.invoke(true,getSessionUsers,valuesPortalArray);
out.println("sessionUsersObject:<br/>"+userObject);
%>


Download Liferay Reflection Example


Usage of Portlets

Download Liferay Reflection Example from above link you can find war files and source code you can directly place war files in portlet deploy directory then it will be deployed.
Now drag and drop PortletB in the page then you can see sample output.

Note:


Portlet have developed in Liferay 6.2 CE GA4 so based on your version you can build it from source that I have given.

PortletB View shows Example out put

Author

Recent Posts

Recent Posts Widget

Popular Posts