Sunteți pe pagina 1din 89

Liferay Installation

How to install Liferay ? First download the community version with tomcat server from the liferay website or Click Here Unzip the contents to a suitable location. Open the bin directory

And click on the startup.bat file to start and shutdown.bat file to shutdown.

To change the server standard time. Open the setenv.bat in an editor and change the Duser.timezone -Duser.timezone=Asia/Calcutta Restart the Server .

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

For Database Settings log into the MySql command line editor. mysql> create database `lportal` CHARACTER SET utf8 COLLATE utf8_general_ci; create a portal-ext.properties file in \liferay-portal-6.0.6 Add the following Lines to connect to MySql Database. # # MySQL # jdbc.default.driverClassName=com.mysql.jdbc.Driver jdbc.default.url=jdbc:mysql://localhost/lportal? useUnicode=true&characterEn coding=UTF-8&useFastDateParsing=false jdbc.default.username=root jdbc.default.password=root save and restart. Check installation success in MySql mysql>use lportal ; mysql>show tables ; A total of 185 rows indicating 185 tables must be shown. There is another way to connect Tomcat to the database. Here is how it is done. Assuming that lportal schema is available in MySQL. goto this path ${TOMCAT_HOME}\conf\Catalina\localhost Open the root.xml and add the following lines in it. <Context path="" crossContext="true"> <Resource name="jdbc/LiferayPool" auth="Container"
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/lportal? useUnicode=true&amp;amp;characterEncoding=UTF-8" username="root" password="root" maxActive="20" /> </Context> while configuring your database do make sure the corresponding jar file of the database is present in the lib directory of tomcat. Liferay Bundled wit tomcat has mysql.jar in it by default in the lib/ext folder. More Liferay 6.0.5 Properties. Now ,some fine tuning must be done if you are going to start development in liferay , so that everything runs faster and smoother , without much of ui customization. Here is what you've got to do. Open setenv.bat again , and add the following lines to it -Dexternal-properties=portal-developer.properties Thats it, You are done and now you can start development on Liferay !!!

MVC Portlet Development : Eclipse Installation


Liferay Installation Before jumping on the Liferay Bandwagon , lets talk in brief about the Portal Technology. A Portal is simply an aggregation of portlets and takes up the job of placement of portlets and handling the requests and rendering them back. Like Yahoo , Its a portal , or iGoogle its a portal . and on the Home page of yahoo you can see different sections Like entertainment ,games etc these are nothing but portlets. A Portlet is more or less like a servlet with the few main differences 1) A servlet URL can be chosen by the Developer , in Portlets the URLs are dynamically generated by the Portal Container 2) Every Portlet may or may not share the same real-estate on the screen.
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

3) In Servlets request and response handling happens in the same lifecycle. Portlets have a different mechanism for handling requests and generating responses. For rendering even a Portlet uses a jsp page. Liferay is using the latest Java Portlet Specification JSR-286. I would advise you to read the following links, before you jump on to Liferay. Read the Introductory Chapter 1 of Portlet Faces Portlet Faces http://editorial.mcpressonline.com/web/mcpdf.nsf/wdocs/5232/$FILE/5232 _EXP.pdf http://java.sys-con.com/node/46966 Difference between Servlets and Portlets : http://www.coderanch.com/t/203209/Portals-Portlets/java/portlet-servlet http://fanatech.wordpress.com/servlets-vs-portlets/ MVC Portlet is a design pattern built by liferay to make portlets faster,easier and scalable. It is advised to use MVCPortlet for a 2-20 action requests.If more than that , then its best to create an action class I.e. making a normal class with Action extended. In order to learn how to create MVC Portlets we shall take an example of User Registration , where we shall learn how to create a database table using the liferay services ,how to make use of built in liferay apis , the MVC portlet structure , the flow of request and response,the jsp coding , the permissioning system and practically all you need to start making your own portlets. Project Creation Well be using eclipse as our development platform. Help => Eclipse Market Place=> type liferay in the search box Screen Shot :
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Click on install and follow the general procedure of installing a plug-in . In the Meanwhile download the liferay-sdk from here Linking SDK to eclipse. Window => Preferences

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Click on Add => Browse to the sdk location and then restart your eclipse. Creating a new Liferay Project.

1) Enter the Name of the Project.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

=> Connect the project with the liferay tomcat folder on your computer.The SDK directory should show u by default. If it doesnt then browse and plug it in. => Click on Next

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Select MVCPortlet and check create custom portlet

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

=> Enter the Desired name and package of the Portlet.

Select an appropriate Display Name and Name of the Portlet. These entries shall go directly in the liferay-portlet.xml , and portlet.xml Also check the => create jsp Files => create resource bundles. If you want to store the jsps in a custom folder then just enter /customfoldername Ex : /jsps Click Finish to complete the Process.

MVC Portlet Development : Directory Structure


Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

MVC Portlet Development Eclipse Installation

While deploying the application, everything is folded up into the docroot folder. All the source class files and jsp files are folded up or wrapped up in the docroot folder. There are 3 Most Important xml files viz. : 1) liferay-display.xml : specifies where your portlet should displayed , under which category. Also specifies the portlet id. NOTE : Every Portlet is assigned a unique name using the following template portletname_WAR_applicationname. In our Case : it will be booksportlet_WAR_books-portlet

Eclipse by default adds -portletafter the application name , but this can be refactored ? 1 <?xml version="1.0"?> 2 <!DOCTYPE display PUBLIC "-//Liferay//DTD Display 6.0.0//
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

3 4 5 6 7 8 9 1 0 1 1 1 2 1 3

EN" "http://www.liferay.com/dtd/liferay-display_6_0_0.dtd"> <display> <category name="category.sample"> </category> <category name="Books"> <portlet id="booksportlet"></portlet> </category> </display>

2) liferay-portlet.xml : Defines liferay specific features of the portlet.

? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6

<?xml version="1.0"?> <!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 6.0.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_6_0_0.dtd"> <liferay-portlet-app> <portlet> <portlet-name>booksportlet</portlet-name> <icon>/icon.png</icon> <instanceable>false</instanceable> <header-portlet-css>/css/portlet.css</header-portlet-css> <footer-portlet-javascript> /js/javascript.js </footer-portlet-javascript> <css-class-wrapper>booksportlet-portlet</css-class-wrapper> </portlet> <role-mapper> <role-name>administrator</role-name> <role-link>Administrator</role-link> </role-mapper> <role-mapper> <role-name>guest</role-name> <role-link>Guest</role-link> </role-mapper> <role-mapper> <role-name>power-user</role-name> <role-link>Power User</role-link> </role-mapper>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 <role-mapper> <role-name>user</role-name> 5 <role-link>User</role-link> 2 </role-mapper> 6 </liferay-portlet-app> 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 The instanceable tag allows to configure the number of instances of that portlet on a particular page. If set to false means you cannot have the same portlet on the same page. If you want a custom icon for your portlet then , you can specify its location within the tag. 3) portlet.xml : Follows the jsr-286 specifications of defining portlets and their activities.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7

<?xml version="1.0"?> <portlet-app version="2.0" 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" > <portlet> <portlet-name>booksportlet</portlet-name> <display-name>Books Catalog</display-name> <portlet-class>com.books.portlet.BooksPortlet</portlet-class> <init-param> <name>view-jsp</name> <value>/jsps/view.jsp</value> </init-param> <expiration-cache>0</expiration-cache> <supports> <mime-type>text/html</mime-type> <portlet-mode>VIEW</portlet-mode> </supports> <resource-bundle>content/Language</resource-bundle> <portlet-info> <title>Books Portlet</title> <short-title>BooksPortlet</short-title> <keywords></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> </portlet> </portlet-app>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3

Most of the tags are self-explanatory , Attention needs to be paid at initparameter tag. The init-parameter tag holds the initial parameters needed to launch an MVCPortlet application. In this case we are having the initparameter as view-jsp which has been defined in the MVCPortlet specification as the home page or the page that shall be loaded first or by default for this particular portlet. If you define a different folder for your jsps then you need to specify it here. security-role-ref : The security-role-ref element contains the declaration of a security role reference in the code of the web application. Specifically in Liferay, the role-name references which roles can access the portlet. (A
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Power User can personalize the portal, whereas a User cannot . In the resource-bundle tag we have ? 1<resource-bundle>content/Language</resource-bundle> 2

This tag is used for having language resources. We can have different Language.properties file of different languages by including them under content/ All the above coding has been generated by eclipse by default. ? 1 <security-role-ref> 2 <role-name>administrator</role-name> 3 </security-role-ref> 4 The security-role tag creates the default roles of this portlet. Default Roles means , these roles will be present in this portlet , and will the permissions of these roles shall be mapped to the respective portal default roles.

Liferay Groups Mystery Untangled


Liferay , has 4 types of aggregation 1) Company : Company basically means a standalone portal. Like if we have one single portal then there will be only one single companyId. But if we have more than one portals then there will be different companyIds. For Ex Google will have one headquarter and different branches , so every branch including the headquarter will be different company id and the users will be grouped into those portals . So , if you want to retrieve the users from a particular branch , you just need to fire a query by giving the companyid. This companyID can easily be obtained from the ActionRequest object and the themeDisplay object as we shall see later.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2) Communities : Now , CMS or content management systems , on which liferay is based is all about sharing data or knowledge. How easy it would be if we were to segregate the interests of different users so that data sharing can be streamlined. This has been taken care of by introducing the concept of Communities. Each liferay portal instance can have different communities, and users can join these communities if their interested align with the objectives of the communities. For Example , there may be a Student community or a professors community and so on. Each community has a unique communityID within that portal instance. There are 3 types of communities : a) Restricted : Membership and visibility of the content on this community is controlled only by the admin. b) Public : Membership is free and all the contents are visible to everyone in the organization c) Private : Same as restricted but its existence is kept confidential. 3) UserGroups : This aggregation is done by admin to give cross functionality to specific members like we create a global resource Like a Technical Architect who can contribute by writing in both Java and .NET communities. So instead of having a separate community for Technical Architects we can have a Team or a UserGroup of TAs. 4) Roles : Users are aggregated on the basis of the functions assigned to them by the admin. Like we can have a Role of Reviewer , who has the permission of reviewing the blogs content. There are 3 types of roles or scope of Roles more precisely a) Portal Roles : here we define access permissions to different portlets throughout the portal instances . There are a few pre-defined default Portal Level Roles which cannot be deleted. i) Admin : is Omnipotent. ii) User : Is a member of an organization iii) Power User : inherits all the powers of the user , but also gets his/her custom public/private page.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

By default a registered member is granted a power user and user roles. b) Community Roles : A Community role would grant that access only within a single community. For Example we can have an Invigilator Role assigned to the Education Community , and a Student Role assigned to the same community. The invigilator would have the permissions to create tests , but the student cannot create tests c) Organization Roles : Similarly , we have Organization Role which defines access to different portlets in a particular portal instance. Like a Role of reviewer assigned to Mumbai Portal , will not necessarily have the same role assigned to him for the Delhi Branch Portal. New roles can be created and assigned permissions by the Admin. Now the Obvious question , what is the difference between a community and an organization ? In an Organization or Company , the users are aggregated in a hierarchical manner by assigning them different organization level roles. In a community , all users are at the same level , but certain permissions related to deleting or creating a blog etc are restricted to certain users. Pages can be assigned to a Community,Organization or a UserGroup , but not to roles. A Power User Role is assigned to all registered members by default , and by assigning them to a particular UserGroup can enable us to have a custom public/private page for that User. For Example , a group of Student we can have a certain set of Pub/Pri pages where as a group of Teachers we can have a different set of Pub/Pri pages.Just create a particular UserGroup and define its public/private pages and assign the users to those respective usergroups. By Default there is a Guest UserGroup , who is just a guest or a visitor the website, with the guest role.So if a guest logins in or is registered , he is by default assigned a Guest UserGroup and Guest Role . For more information on the Portal Structure in Liferay , read The Liferay Administrators Guide page 67.

MVC Portlet Development : Service Builder-I


Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Liferay Eclipse Installation MVC Portlet Development : Directory Structure In the previous post , we saw the directory structure inherently created by eclipse and the liferay-sdk. Here we shall be introduced to a new concept of service builder. Liferay sdk has service builder which abstracts all the database building,connecting code from the developer. We just need to create a small xml file and well be done with it. Service builder abstracts all the information by making certain classes on the spring-hibernate framework.It does a lot of things most which might go tangential for us. So while learning service builder its best to focus on whatever is in our hands to code and try not to delve deeper into the service builder codes. There is only one class where we have to do the coding and another which we shall use for communication with the database. So , opening eclipse again . Create a new liferay-service.

After clicking on that add the name,package and the namespace as shown.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Click on finish and then check your directory structure. You can see that a service.xml file has opened up in the eclipse editor.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

We shall follow a Bottom-Up Approach to make our portlets. So lets make our Table Design first. Now each entity specifies the structure of a database table.Entity name will be the name of the table and also of the class which is mapped to that table. So lets populate the service.xml file. Before that we need to know what all do we require for having a Books Catalog. 1) 2) 3) 4) Title Pages Date Of Purchase Author

Along with these we shall require 3 more fields , userid,groupid and companyid. What is this ? Please Read the following blog before you go ahead. Liferay Groups Mystery Untangled Coming back to our earlier discussion of the userId,groupId and companyId, we can now map their relevance with the portal architecture in the background. UserID: Unique ID assigned to every Registered User. GroupID : ID of a particular Community on a particular portal instance CompanyID : ID of a particular portal instance. UserGroupID : ID of a particular UserGroup. So Our service.xml would look something like this ? 1 2 3 4 5 6 7 8 9
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 6.0.0//EN" "http://www.liferay.com/dtd/liferay-service-builder_6_0_0.dtd"> <service-builder package-path="com.books.database"> <author>Rohit</author> <namespace>B</namespace> <entity name="Books" local-service="true" remote-service="false"> <column name="bookId" type="long" primary="true"></column> <column name="title" type="String"></column> <column name="author" type="String"></column>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

<column name="dateOfPurchase" type="Date"></column> 1 <column name="pages" type="int"></column> 0 <column name="userId" type="long"></column> 1 <column name="companyId" type="long"></column> 1 <column name="groupId" type="long"></column> <order by="asc"> 1 <order-column name="bookId"></order-column> 2 </order> 1 <finder return-type="Collection" name="GroupId"> 3 <finder-column name="groupId"></finder-column> 1 </finder> <finder return-type="Collection" name="CompanyId"> 4 <finder-column name="companyId"></finder-column> 1 </finder> 5 <finder return-type="Collection" name="UserId"> 1 <finder-column name="userId"></finder-column> </finder> 6 <finder return-type="Collection" name="Group_Title"> 1 <finder-column name="groupId"></finder-column> 7 <finder-column name="title"></finder-column> 1 </finder> 8 <finder return-type="Collection" name="Group_Author"> <finder-column name="groupId"></finder-column> 1 <finder-column name="author"></finder-column> 9 </finder> 2 </entity> 0 </service-builder> 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

3 3 3 4 3 5 3 6 3 7 3 8 3 9 Ill try to analyze the entire document line by line. ? 1<entity

name="Books" local-service="true" remote-service="false">

Defines the Entity name which also assigns the name for the Model Class , which we shall see later. The table name however shall be assigned as NamespaceEntityname in this case itll be BBooks local-service=true shall create a utility class that can be used on the same jvm , by putting remote-service=true we can create a utility class which can be used inter-jvms.It creates stubs skeletons and handles all the network related connections. ? 1<column
name="bookId" type="long" primary="true"></column>

Defines the name and type of the column. Primary shud be set only one per entity. Type can be any primitive datatype or a java Object.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

? 1<order by="asc"> <order-column name="bookId"></order-column> 2 </order> 3 Assigning ascending order on firstname column ? 1<finder return-type="Collection" name="GroupId"> <finder-column name="groupId"></finder-column> 2 </finder> 3 This finder column is another beauty of the Liferay Service Builder. It generates a function , which shall accept groupId as the parameter/argument and return a Collection or a List of Books Objects matching that particular groupId. We can also assign multiple arguments like we have in the above finder groups Group_LastName. Its advisable to have the companyId ,groupId and userId in all entities for implementing the permissioning system in liferay.I shall explain that later. There is no need to write a finder method for primary key column , as liferay sdk ceates one by default.Inface you do attempt to write a finder element on stand-alone primary key column , it would throw an error. I told you I am here to share my experience :P The finder methods named as findByFinderName Ex : we have above GroupId so the method signature would be like this List findByGroupId(long arg0) ; More on Finder Tags NOTE : Before you go to the next step of building services and generating the code , make sure you are confident about your table structure and that you have entered in all the data well.It Is advisable to have the table design in place, before you go for the service.xml. Once you build the service , you cannot add rename any of the components. Also you cannot add more finder methods.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Click on Build Services button on top-right corner of the screen. Then open the console and see the services being build. If you get a Build Succesful as shown in the image above , means you are ready to move on. If your Build Fails then check for the jre installation. The Build Services shall work only if you have a jdk 1.6 and above. Another source of error would be from spelling mistakes in the finder and order tags. Its also case-sensitive. If you get runtime exception then , check for spellings or naming and run the build service again. Also after every build make sure you clean and build your project workspace. Now , when you see the directory structure youll say a lot of addditonal files eill be generated. Here is how it should like.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

The service Builder is working on a spring-hibernate framework.So it generates all these files from somewhere. Dont bother to understand from where.Its a waste of time unless you are more interested in learning Spring and Hibernate. The only Class that we shall open here is RegistrationLocalServiceImpl.class and BookLocalServiceImpl.class or in general EntityLocalServiceImpl. For more info on Service Builder and The class relationships check out this link. Here we got only LocalServiceImpl classes, but if you were to keep remoteservice=true in service.xml entity name="Book" local-service="true" remote-service="true" then we would have got EntityServiceImpl , separately . Because you might want to restrict external applications from using some of the functionality . I shall continue , in my next blog MVC Portlet Development - Service Builder II

MVC Portlet Development : Service Builder -II


Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

MVC Portlet Development : Service Builder -I Also you can see , that the service builder created a small books-portlet-service.jar file in the WEB-INF/lib directory. This jar file is packaged with all the files in the WEBINF/service folder. You can access the Books Database in 2 ways 1) First , by leaving this jar file as it is in the lib folder 2) Secondly , you can just copy this file and paste it in the lib/ext folder of your tomcat . Basically you are adding the jar file to the global path of tomcat , and you can give access to BBooks table in your database to any portlet. But if you are following the 2nd step , then make sure that you delete this jar file from the lib folder before you deploy the portlet. This is a very common mistake. Now , in the BooksLocalServiceImpl .class we need to include all the code required to access data.In Books LocalServiceImpl , similar functions will be included. Note all the finder methods can be called only by a entityPersistence in this case productPersistence Object inside the BookLocalServiceImpl.class its not availible otherwise.Hence we first need to make wrapper functions for the same. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
package com.books.database.service.impl; import import import import import import import import import import com.books.database.NoSuchooksException; com.books.database.model.Books; com.books.database.service.base.BooksLocalServiceBaseImpl; java.util.Collections; java.util.List; org.apache.commons.logging.Log; org.apache.commons.logging.LogFactory; com.liferay.portal.kernel.exception.PortalException; com.liferay.portal.kernel.exception.SystemException; com.liferay.portal.model.ResourceConstants;

/** * The implementation of the books local service. * * <p> * All custom service methods should be put in this class. Whenever methods are * added, rerun ServiceBuilder to copy their definitions into the * {@link com.books.database.service.BooksLocalService} interface. * </p>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

* * <p> * Never reference this interface directly. Always use * {@link com.books.database.service.BooksLocalServiceUtil} to access the books * local service. * </p> * * <p> * This is a local service. Methods of this service will not have security * checks based on the propagated JAAS credentials because this service can only * be accessed from within the same VM. * </p> * * @author Rohit * @see com.books.database.service.base.BooksLocalServiceBaseImpl * @see com.books.database.service.BooksLocalServiceUtil */ public class BooksLocalServiceImpl extends BooksLocalServiceBaseImpl { public Books addBooks(Books booksParam) { Books booksVar; try { booksVar = booksPersistence.create(counterLocalService .increment(Books.class.toString())); } catch (SystemException e) { e.printStackTrace(); return booksVar = null; } try { resourceLocalService.addResources(booksParam.getCompanyId(), booksParam.getGroupId(), booksParam.getUserId(), Books.class.getName(), booksParam.getPrimaryKey(),false, true, true); } catch (PortalException e) { e.printStackTrace(); return booksVar = null; } catch (SystemException e) { e.printStackTrace(); return booksVar = null; } booksVar.setAuthor(booksParam.getAuthor()); booksVar.setCompanyId(booksParam.getCompanyId()); booksVar.setPages(booksParam.getPages()); booksVar.setDateOfPurchase(booksParam.getDateOfPurchase()); booksVar.setGroupId(booksParam.getGroupId()); booksVar.setTitle(booksParam.getTitle()); booksVar.setUserId(booksParam.getUserId()); try { return booksPersistence.update(booksVar, false); } catch (SystemException e) {

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 10 0 10 1 10 2 10 3 10 4 10 5

e.printStackTrace(); return booksVar = null; } }

public Books getBooksInstance() { try { return booksPersistence.create(counterLocalService .increment(Books.class.getName())); } catch (SystemException e) { e.printStackTrace(); return null; } } public List<books> getAllBooks(long companyId) { try { return booksPersistence.findByCompanyId(companyId); } catch (SystemException e) { e.printStackTrace(); return Collections.emptyList(); } } public List<books> getAllBooks() { try { return booksPersistence.findAll(); } catch (SystemException e) { e.printStackTrace(); return Collections.emptyList(); } } public List<books> getAllBooks(long groupId, String title) { try { return booksPersistence.findByGroup_Title(groupId, title); } catch (SystemException e) { e.printStackTrace(); return Collections.emptyList(); } } public List<books> getBooksByUserId(long userId) { try { return booksPersistence.findByUserId(userId); } catch (SystemException e) { e.printStackTrace(); return null; } } public void deleteBooks(long booksId, long companyId) { Books books; try {

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

10 6 10 7 10 8 10 9 11 0 11 1 11 2 11 3 11 4 11 5 11 6 11 7 11 8 11 9 12 0 12 1 12 2 12 3 12 4 12 5 12 6 12 7 12 8

books = booksPersistence.findByPrimaryKey(booksId); } catch (SystemException e) { e.printStackTrace(); return; } catch (NoSuchooksException e) { e.printStackTrace(); return; } deleteBooks(books, companyId);

public void deleteBooks(Books books, long companyId) { try { resourceLocalService.deleteResource(companyId, Books.class.getName(), ResourceConstants.SCOPE_INDIVIDUAL, books.getPrimaryKey()); } catch (PortalException e) { e.printStackTrace(); return; } catch (SystemException e) { e.printStackTrace(); return; } try { booksPersistence.remove(books); } catch (SystemException e) { e.printStackTrace(); return; } } }</books></books></books></books>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

12 9 13 0 13 1 13 2 13 3 13 4 13 5 13 6 13 7 13 8 13 9 14 0 14 1 14 2 14 3 14 4 14 5 14 6 14 7 14 8 14 9 15 0 15 1
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

15 2 15 3 15 4 15 5 15 6 15 7 15 8 15 9 16 0 16 1 16 2 16 3 16 4

Thats a lot a of coding. But we should include only that code which we require to communicate with the database. Note : After writing the code , we must run the Service Builder again and clean the project. Service Builder runs in a reverse way with respect to java specifications i.e. As per the Java Specs , we should first create the interfaces and then implement the functions.But Service Builder does a full u-turn . It asks us to implement the functions here in the LocalServiceImpl classes and then generates an Interface or an Abstract class with LocalServiceUtil as the postfix. If you read the comment above the class code , it clearly states * Never reference this interface directly. Always use * {@link com.books.database.service.BooksLocalServiceUtil} to access the
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

books * local service. i.e. we should use BookLocalServiceUtil always in all the coding. Example if you need to addBook then the call would be BookLocalServiceUtil.addBook() ; If we had remote-service=true then it would be BookServiceUtil. In the background , service builder does all the hardwork of creating all Model and Bean classes . We need only to classes . viz .. 1) LocalServiceImpl : for writing implementing all the code 2) LocalServiceUtil : for UTILising the code. ? 1 2 3 4 5 6 7 8 9 1 0

try { bookVar = bookPersistence.create(counterLocalService .increment(Book.class.toString())); } catch (SystemException e) { log.error(e); return bookVar = null; }

bookPersistence is the Object of BookPersistenceIImpl Class in service.impl package. It has implementation of all the basic methods of adding , updating , deleting and finding an entity. Basically implementing all the CRUD operations on databases. Just use shift+space to see all the functions in eclipse. counterLocalService is an object provided for incrementing primary keys of an entity.To avoid overflowing of the inbuilt 32 bit counter , we need to specify the class so that it increments only for the particular object. The above code, just creates an entity or a row in the table , by autoincrementing its primary key. Its a best practice followed by liferay and must be followed.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

? 1 2resourceLocalService.addResources(bookParam.getCompanyId(), bookParam.getGroupId(), bookParam.getUserId(), 3 Book.class.getName(), bookParam.getPrimaryKey(), false, 4 true, true); 5 6 Liferay is a CMS , and it is resource driven.Every object,blog,wiki,image etc is defined as a resource. But why ? Why everything needs to be defined as a resource ? to implement Permissioning systems. Using the above code , we are actually informing the permissioning systems of liferay that we are going to implement certain permissions on the above entity. resourceLocalService is an object of ResourceLocalServiceUtil in liferay. To define the permission , we require the groupId,companyId and the userId. Hence I had commented while beginning with the liferay service builder that we need to include all 3 of these ids. Liferay also uses the same approach for making its own entities and tables.They also use Service Builder. Along with this , we also need to include an xml file , informing liferay what kind of permissions do we need to implement and on whom should we implement.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

As you can see we have added 2 files and a folder. In the portlet.properties file we have included the path for the permissioning file default.xml , to inform liferay that permissioning system has been implemented in this application. The contents of portlet.properties is as follows resource.actions.configs=resource-actions/default.xml default.xml ? 1 2 3 4 5 6 7 8 9 1 0 1
<?xml version="1.0" encoding="UTF-8"?> <resource-action-mapping> <portlet-resource> <portlet-name>booksportlet</portlet-name> <permissions> <supports> <action-key>ADD_BOOKS</action-key> <action-key>VIEW</action-key> </supports> <community-defaults> <action-key>VIEW</action-key> </community-defaults>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3

<guest-defaults> <action-key>VIEW</action-key> </guest-defaults> <guest-unsupported> <action-key>ADD_BOOKS</action-key> </guest-unsupported> </permissions> </portlet-resource> <model-resource> <model-name>com.books.database.model.Books </model-name> <portlet-ref> <portlet-name>booksportlet</portlet-name> </portlet-ref> <permissions> <supports> <action-key>DELETE</action-key> <action-key>UPDATE</action-key> <action-key>VIEW</action-key> </supports> <community-defaults> <action-key>VIEW</action-key> </community-defaults> <guest-defaults> <action-key>VIEW</action-key> </guest-defaults> <guest-unsupported> <action-key>UPDATE</action-key> <action-key>DELETE</action-key> </guest-unsupported> </permissions> </model-resource> </resource-action-mapping>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 So , now here we are actually having two types of permissions.One on the Portlet another on the Model or the entity. These permissions can either be defined by the admin by assigning roles and defining permissions for that role , or Can be used programmatically , as we shall see later.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

? 1 2<supports> <action-key>DELETE</action-key> 3 <action-key>UPDATE</action-key> 4 <action-key>VIEW</action-key> 5</supports> 6 In the Supports tag , we need to define all the sort of permissions that need to be implemented on the model or the portlet. Delete,Add,Update,View are all the Possible Permissions defined for this particular Portlet.We can have more such permissions like Scroll , Move etc.. ? 1 <community-defaults> 2 <action-key>VIEW</action-key> 3</community-defaults> 4

Specifies that , these particular permissions will be available to all members of a particular community by default. For Ex : above community-default VIEW permission has been given , hence the portlet and the data displayed by the portlet can be viewed by all the members of the community. Update,Delete permissions can only be assigned by the Admin. Similarly we have guest-defaults. ? 1 2<guest-unsupported> <action-key>UPDATE</action-key> 3 <action-key>DELETE</action-key> 4</guest-unsupported> 5

All the permissions declared under this tag , will be unavailable for the guest.Even the admin cannot change this.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

A guest would be a non-member of a community or an unregistered member. You would get an error , in LocalServiceImpl class if you try to use addBook without including the default.xml file. If you donot want to assign any permissions , then donot use ? 1resourceLocalService.addResources(bookParam.getCompanyId(), bookParam.getGroupId(), bookParam.getUserId(), 2 Book.class.getName(), bookParam.getPrimaryKey(), false, 3 true, true); 4 5ResourceLocalServiceUtil.addResources( 6entry.getCompanyId(), entry.getGroupId(), 7entry.getUserId(),BlogsEntry.class.getName(), 8entry.getPrimaryKey().toString(),false, 9addCommunityPermissions, addGuestPermissions); The last three are Boolean variables , specifying whether we are supposed to add the permissions or not. False means that portlet level permissions should be omitted. For More on Security framework , read Page 56 of Liferay Developers Guide

MVC Portlet Development : MVC Framework and AlloyUI


What we have done so far , Eclipse Installation Directory Structure Service Builder - I Service Builder - II and continuing to the last part . The MVC Framework and Alloy UI Every Portlet on a portal page , will have a different render and request cycle. In servlet we either implement a doGet or a doPost method which handle the response and the request in the same cycle. But here in the Portlet
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

specification jsr-286 , the request and rendering or response is handled separately. In the Portlet cycle , we have two main methods processAction and render. processAction handles all the requests and render handles the response. When the portlet is loaded for the first time , render is called to load the default view lets say a form.When you fill the form and send it across processAction will be called to get all the form data.Once the processAction is executed you can specify a jsp page where the next event has to be handlded. By default it will go to the home page. But in the MVCPorrlet interface , all these things have been abstracted for us. We donot need to implement any of these render or processAction methods. In portlet.xml we specified view-jsp as n initial parameter.This is nothing but the location of the default page that loads when the portlet is loaded for the first time or whenever no action is called. In MVC Portlet , there is a simple way of sending a request and rendering the response. Below is the code of a JSP file and its corresponding MVC portlet. ? 1 <%@ include file="/init.jsp"%> 2 <% Books book = (Books) request.getAttribute("book"); 3 if (book == null) { 4 book = new BooksImpl(); 5 Calendar now = CalendarFactoryUtil.getCalendar(); 6 now.set(1970, 1, 1); book.setDateOfPurchase(now.getTime()); 7 } 8 9 %> 1 <liferay-portlet:actionURL name="addBook" var="addBookURL"></liferay0 portlet:actionURL> 1 <liferay-ui:success key="book-added" message="book-added" /> <liferay-ui:success key="book-deleted" message="book-deleted" /> 1 <liferay-ui:error key="error-deleting" message="error-deleting" /> 1 <liferay-ui:error key="error-while-adding" message="error-while-adding" /> 2 <aui:form action="<%=addBookURL.toString() %>" method="post" name="fm"> 1 3 <aui:fieldset> 1 <liferay-ui:error key="title-required" message="title-required" /> <p> 4 <aui:input name="title" label="Title" type="text" 1 value="<%=book.getTitle() %>"></aui:input> 5 </p> 1 <liferay-ui:error key="author-required" message="author-required" />
<p>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3

<aui:input name="author" label="Author" type="text" value="<%=book.getAuthor() %>"></aui:input> </p> <liferay-ui:error key="pages-required" message="pages-required" /> <liferay-ui:error key="pages-cannot-be-zero" message="pages-cannot-be-zero" /> <p> <aui:input name="pages" label="Pages" type="text" value="<%=String.valueOf(book.getPages()) %>"></aui:input> </p> <liferay-ui:error key="dop-required" message="dop-required" /> <p> <% Calendar dop = CalendarFactoryUtil.getCalendar(); dop.setTime(book.getDateOfPurchase()); %> <aui:input model="<%=Books.class %>" bean="<%=book%>" label="Date of Purchase" name="dateOfPurchase" value="<%= dop %>" /> </p> <aui:button-row> <p> <aui:button class="aui-button-input" type="submit" value="Submit" /> <aui:button class="aui-button-input" type="reset" value="Reset" /> </p> </aui:button-row> </aui:fieldset> </aui:form> <liferay-ui:search-container emptyResultsMessage="no-books" delta="5"> <liferay-ui:search-container-results> <% List<Books> tempResults = (List<Books>) BooksActionUtil .getAllBooks(themeDisplay.getCompanyId()); results = ListUtil.subList(tempResults, searchContainer.getStart(), searchContainer.getEnd()); total = tempResults.size(); pageContext.setAttribute("results", results); pageContext.setAttribute("total", total); %> </liferay-ui:search-container-results> <liferay-ui:search-container-row className="com.books.database.model.Books" keyProperty="bookId" modelVar="book1"> <liferay-ui:search-container-column-text <liferay-ui:search-container-column-text property="author" /> <liferay-ui:search-container-column-text <liferay-ui:search-container-column-text property="dateOfPurchase" /> name="Title" property="title" /> name="Author" name="Pages" property="pages" /> name="Date of Purchase"

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6 0 6 1 6

<% long groupId = themeDisplay.getLayout().getGroupId(); String name = Books.class.getName(); String bookId = String.valueOf(book.getPrimaryKey()); %> <c:if test="<%= permissionChecker.hasPermission(groupId, name,bookId,"DELETE") %>"> <liferay-ui:search-container-column-jsp name="Delete" path="/jsps/display_actions.jsp" align="right" /> </c:if> </liferay-ui:search-container-row> <liferay-ui:search-iterator /> </liferay-ui:search-container>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 6 3 6 4 6 5 6 6 6 7 6 8 6 9 7 0 7 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 8 0 8 1 8 2 8 3 8 4 8
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

5 8 6 8 7 8 8 8 9 9 0 9 1 9 2 9 3 9 4 9 5 9 6 9 7 9 8 9 9 ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2

import java.util.ArrayList; import java.util.List; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import import import import import import import import com.books.database.model.Books; com.books.database.service.BooksLocalServiceUtil; com.books.util.BooksActionUtil; com.books.util.BooksValidator; com.liferay.portal.kernel.exception.SystemException; com.liferay.portal.kernel.servlet.SessionErrors; com.liferay.portal.kernel.servlet.SessionMessages; com.liferay.portal.kernel.util.ParamUtil;

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5

import import import import

com.liferay.portal.kernel.util.Validator; com.liferay.portal.kernel.util.WebKeys; com.liferay.portal.theme.ThemeDisplay; com.liferay.util.bridges.mvc.MVCPortlet;

/** * Portlet implementation class BooksPortlet */ public class BooksPortlet extends MVCPortlet { private static Log log = LogFactory.getLog(BooksPortlet.class); private static String errorJSP="/jsps/error.jsp" ; public void addBook(ActionRequest request, ActionResponse response) { log.info("Inside addBooks"); List<String> errors=new ArrayList<String>(); Books book=BooksActionUtil.getBookFromRequest(request); boolean bookValid=BooksValidator.validateBook(book,errors); if(bookValid) { try { log.info(book); Books test=BooksLocalServiceUtil.addBooks(book); if(test==null) { log.error("Book was Found Null"); response.setRenderParameter("jspPage", errorJSP); return ; } } catch (SystemException e) { log.error(e); /*If there is an error then divert the control to the error page.*/ response.setRenderParameter("jspPage", errorJSP); return ; } SessionMessages.add(request,"book-added"); return ; } else { for (String error : errors) { SessionErrors.add(request, error); } SessionErrors.add(request, "error-while-adding"); request.setAttribute("book",book); return ; } }

public void deleteBooks(ActionRequest request, ActionResponse response) { long bookId = ParamUtil.getLong(request, "bookId"); ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute( WebKeys.THEME_DISPLAY);

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8

if (Validator.isNotNull(bookId)) { BooksLocalServiceUtil.deleteBooks(bookId, themeDisplay.getCompanyId()); SessionMessages.add(request, "book-deleted"); } else { SessionErrors.add(request, "error-deleting"); } } }

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

5 9 6 0 6 1 6 2 6 3 6 4 6 5 6 6 6 7 6 8 6 9 7 0 7 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 8 0 8 1
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

8 2 8 3 8 4 8 5 <liferay-portlet:actionURL name="addBook" var="addBookURL"></liferayportlet:actionURL> In Portlet , we cannot create our own links, the way we do it in servlets . We need to create URLs to submit a form or to perform some action. The above code , maps the to the function public void addBook(ActionRequest request, ActionResponse response) { in the BooksPortlet class. The name in actionURL tag is the name of the function that is implemented in the portlet class. The var is just a variable holding the link. So while creating a form , we specify it in the following manner . ? 1<aui:form action="<%=addBookURL.toString() %>" method="post" name="fm"> 2 Just like actionURL , we also have renderURL . ? 1 2<liferay-portlet:renderURL var=successURL> <portlet:param name=jspPage value=success.jsp /> 3<liferay-portlet:renderURL> 4<a href=<%=successURL.toString()%>>Success</a> 5 It basically renders a jsp or an HTML page. ? 1portlet:param name=jspPage value=success.jsp /> 2 For rendering any JSP , MVCPortlet framework , has the above syntax.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

For rendering after completing an action , we have ? 1response.setRenderParameter(jspPage,jspLocation) ; 2 Calls to these functions , are followed by execution of the Public void render(RenderRequest request,RenderResponse response) function internally. BooksActionUtil.class As you have seen in the BooksPortlet , we have called two functions , ? 1 Books book=BooksActionUtil.getBookFromRequest(request); 2boolean bookValid=BooksValidator.validateBook(book,errors); 3 This is a standard procedure followed by Liferay , to reduce concentrating all the code in one class itself. Like common , it follows more out of practise and common sense. So here , are the two classes , BooksActionUtil.class and BooksValidator.class ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1
package com.books.util; import java.util.*; import javax.portlet.ActionRequest; import import import import import import import import import com.books.database.model.Books; com.books.database.model.impl.BooksImpl; com.books.database.service.BooksLocalServiceUtil; com.liferay.portal.kernel.exception.PortalException; com.liferay.portal.kernel.util.ParamUtil; com.liferay.portal.kernel.util.Validator; com.liferay.portal.kernel.util.WebKeys; com.liferay.portal.theme.ThemeDisplay; com.liferay.portal.util.PortalUtil;

public class BooksActionUtil { public static Books getBookFromRequest(ActionRequest request) { ThemeDisplay themeDisplay = (ThemeDisplay) request .getAttribute(WebKeys.THEME_DISPLAY);

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3

String title = ParamUtil.getString(request, "title", "Title Not Availible"); String author = ParamUtil.getString(request, "author", "Author Not Availible"); String pageStr = ParamUtil.getString(request, "pages", "0"); int pages = 0; if (Validator.isDigit(pageStr)) { pages = Integer.parseInt(pageStr); } // Month ,Day and Year are a prefix which must be given int dopMonth = ParamUtil.getInteger(request, "dateOfPurchaseMonth"); int dopDay = ParamUtil.getInteger(request, "dateOfPurchaseDay"); int dopYear = ParamUtil.getInteger(request, "dateOfPurchaseYear"); Books book = new BooksImpl(); book.setAuthor(author); book.setPages(pages); book.setTitle(title); book.setCompanyId(themeDisplay.getCompanyId()); book.setGroupId(themeDisplay.getLayout().getGroupId()); book.setUserId(themeDisplay.getUserId()); if (Validator.isDate(dopMonth, dopDay, dopYear)) { try { book.setDateOfPurchase(PortalUtil.getDate(dopMonth, dopDay, dopYear, new PortalException())); } catch (PortalException ex) { //Setting to Null Will enable us to catch it in the Validator book.setDateOfPurchase(null); } } else { book.setDateOfPurchase(null); } return book; } public static List<books> getAllBooks(long companyId) { return BooksLocalServiceUtil.getAllBooks(companyId); } } </books>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4 7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

0 6 1 6 2 6 3 6 4 6 5 BooksVaildator.class ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0
package com.books.util; import java.util.* ; import com.books.database.model.Books; import com.liferay.portal.kernel.util.Validator; public class BooksValidator { public static boolean validateBook(Books book, List<string> errors) { boolean valid=true ; if (Validator.isNull(book.getTitle())) { errors.add("title-required"); valid = false; } if (Validator.isNull(book.getAuthor())) { errors.add("author-required"); valid = false; } if (Validator.isNull(book.getDateOfPurchase())) { errors.add("dop-required"); valid = false; } if (Validator.isNull(book.getPages())) { errors.add("pages-required"); valid = false; } if(book.getPages()==0) { errors.add("pages-cannot-be-zero"); valid = false; } return valid ; }

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 } 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9

ThemeDisplay
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

? 1 ThemeDisplay themeDisplay = (ThemeDisplay) request 2.getAttribute(WebKeys.THEME_DISPLAY); 3 themeDisplay is an object containing all the information about the page, its layout, about the user whether he is logged in or not , certain fixed urls like create account , sign in etc. from themeDisplay we can get information about the company,group,user the particular page is associated with. Its a very important object. Here is the documentation of the ThemeDisplay Object and its functions. Here is the Screen Shot of the portlet that we have created.

DatePicker The date picker object Is very simple to implement. Here is the implementation code. ? 1 2 3 4 5 6 7 8 9 1 0 1
<p> <% Calendar dop = CalendarFactoryUtil.getCalendar(); dop.setTime(book.getDateOfPurchase()); %> <aui:input model="<%=Books.class %>" bean="<%=book%>" label="Date of Purchase" name="dateOfPurchase" value="<%= dop %>" /> </p> //And here is how you would retrieve the Date object, nt dopMonth = ParamUtil.getInteger(request, "dateOfPurchaseMonth"); int dopDay = ParamUtil.getInteger(request, "dateOfPurchaseDay");

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0

int dopYear = ParamUtil.getInteger(request, "dateOfPurchaseYear"); if (Validator.isDate(dopMonth, dopDay, dopYear)) { try { book.setDateOfPurchase(PortalUtil.getDate(dopMonth, dopDay, dopYear, new PortalException())); } catch (PortalException ex) { /* Setting to Null Will enable us to catch it in the Validator */ book.setDateOfPurchase(null); } } else { book.setDateOfPurchase(null); }

For the date picker , it is necessary to provide the Model and the bean attributes to the input tag. In the src/META-INF folder , we have a n xml file where we can set restrictions on the datatypes portlet-model-hints.xml
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0

<?xml version="1.0" encoding="UTF-8"?> <model-hints> <model name="com.books.database.model.Books"> <field name="bookId" type="long" /> <field name="title" type="String" /> <field name="author" type="String" /> <field name="dateOfPurchase" type="Date"> <hint name="year-range-delta">90</hint> <hint name="year-range-future">true</hint> <hint name="show-time">false</hint> </field> <field name="pages" type="int" /> <field name="userId" type="long" /> <field name="companyId" type="long" /> <field name="groupId" type="long" /> </model> </model-hints>

We can also restrict the lenth of certain fields using ? 1<hint name=max-length>4000</hint> 2 For more info on model-hints , take a look at the liferay source code , portal-impl/src/META-INF/portal-modelt-hints.xml file. Model-Hints

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

NOTE : While using the date field , the name attribute of the input tage should match with the name attribute of the field tag in portlet-model-hint. ParamUtil and PortalUtil. ParamUtil is a utility class provided by liferay to extract the parameters from the query strings with a lot of added functionality. For Example : ? 1String title = ParamUtil.getString(request, "title","Title Not Availible"); 2 Here the getString method is having 3 parameters, request object ,the parameter name , and the default parameter if in case there is an error in the connection or the session is timed out. ParamUtil Documentation . PortalUtil is also a utility class having some portal related functions Liferay Also provides a Validator class , which we can use to validate all predefined java primitives and objects. Life email address,phonenumber , street address , null check etc. Validator Documentation Liferay-Search Container Liferay provides yet another awesome feature of generating a tabular container , with navigation capabilities. Its also pretty simple to implement. You just needs the list of Object that needs to be displayed.That object can either be Model class or our Own bean class.

? 1 <liferay-ui:search-container emptyResultsMessage="no-books" delta="5">


Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8

<liferay-ui:search-container-results> <% List<Books> tempResults = (List<Books>) BooksActionUtil .getAllBooks(themeDisplay.getCompanyId()); results = ListUtil.subList(tempResults, searchContainer.getStart(), searchContainer.getEnd()); total = tempResults.size(); %> </liferay-ui:search-container-results> <liferay-ui:search-container-row className="com.books.database.model.Books" keyProperty="bookId" modelVar="book1"> <liferay-ui:search-container-column-text name="Title" property="title" /> <liferay-ui:search-container-column-text name="Author" property="author" /> <liferay-ui:search-container-column-text name="Pages" property="pages" /> <liferay-ui:search-container-column-text name="Date of Purchase" property="dateOfPurchase" /> <% long groupId = themeDisplay.getLayout().getGroupId(); String name = Books.class.getName(); String bookId = String.valueOf(book.getPrimaryKey()); %> <c:if test="<%= permissionChecker.hasPermission(groupId, name,bookId,"DELETE") %>"> <liferay-ui:search-container-column-jsp name="Delete" path="/jsps/display_actions.jsp" align="right" /> </c:if> </liferay-ui:search-container-row> <liferay-ui:search-iterator /> </liferay-ui:search-container>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 In the <liferay-ui:search-container-results> tag , we first populate the list . It counts the number of elements. <liferay-ui:search-container-row> this tag , is used to display the all the information , But we must make sure to give the correct class name and the primary key Note : Make sure you specify your "className", "keyProperty" name exactly the way you have written in service.xml, It is case-sensitive , and the "modelVar" is just a variable name, You can name it whatever you want just make sure that name doesnt repeat throughout the entire jsp document. ? 1<liferay-ui:search-container-column-text name="Title" property="title" /> 2Note : Make sure that the property matches the exact property name given in 3service.xml You might come across a situation where the data in your column is not matching the UI requirement , Like for Example , you store the date in 1970,11,11 and now you want to format this date before you put it up on search-container , how to go about that ?
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Simple , Just create a new Class , and just to follow proper naming convention , post-fix the class name with "Bean" Then create instance variables , of the class same as that in service.xml , you can also give them different names For Example , for the books portlet , ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2
package com.books.util; import java.util.* ; public class BooksBean { private long bookId ; private String title ; private String author ; private Date dop ; private int pages ; private long userId ; private long companyId ; private long groupId ; public long getBookId() { return bookId; } public void setBookId(long bookId) { this.bookId = bookId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Date getDop() { //Write your Own Simple Date Formatter Code Here return dop; } public void setDop(Date dop) { this.dop = dop; } public int getPages() { return pages; } public void setPages(int pages) { this.pages = pages; } public long getUserId() { return userId;

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1 4 2 4 3 4 4 4 5 4 6 4

} public void setUserId(long userId) { this.userId = userId; } public long getCompanyId() { return companyId; } public void setCompanyId(long companyId) { this.companyId = companyId; } public long getGroupId() { return groupId; } public void setGroupId(long groupId) { this.groupId = groupId; } }

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

7 4 8 4 9 5 0 5 1 5 2 5 3 5 4 5 5 5 6 5 7 5 8 5 9 6 0 6 1 6 2 6 3 6 4 6 5 6 6 then refer modelClass=com.package.name.BooksBean and the keyProperty=bookId or whatever you have chosen in your beanClass. Also while populating the List donot forget to map each property of Bean to the Actual Class
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2

List<booksbean> list= new ArrayList<booksbean>(); List<books> originalList=getAllBooks(companyId) ; for(Books b:originalList){ BooksBean bean= new BooksBean(); bean.setCompanyId(b.getCompanyID); and so ... } </books></booksbean></booksbean>

More on Search Container Liferay-Permission Checker Checking permission in liferay is just a matter of calling a function . ? 1permissionChecker.hasPermission(groupId, name,bookId,"DELETE") ; 2 This function , is given the groupId , the name of the class , the primary key of the class and the type of Action supported. We have defined all this in the default.xml file under the resource-actions folder. The above permissionChecker , simply passes on these parameters and checks it against the permissions given to the particular user . If the user has permission it will return true , else false. We have used the permission checker to toggle the Delete functionality for different users . Any user having role for which delete functionality has been granted permission . will see the delete icon , else wont. Here is a screen shot displaying the permissionChecker in action , with 2 images of the portlet on before log-in and one after log-in.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Pre-Login .

Post-Login

PermissionChecker API Liferay Messages ? 1 2SessionMessages.add(request,"book-added"); 3<liferay-ui:success key="book-added" message="book-added" /> 4 5SessionErrors.add(request, "error-while-adding"); 6<liferay-ui:error key="error-while-adding" message="error-while-adding" /> 7 SessionMessages and SessionErrors , are two classes which ease out sending out messages to the users or while debugging. Few Uses of the liferay-error :
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

? 1<liferay-ui:error message="this-is-an-error" key="key" /> 2 3SessionErrors.add(actionRequest, e.getClass().getName(), e); 4 5<liferay-ui:error exception="<%=SomeException.class%>" message="your-message" 6/>

The message attribute contains the key to the key-value pair store in the Language.properties file. Language.properties : book-added=Books have been Added Successfully ! error-while-adding=Some Error has Occured While Adding, Please Try Again If you click on Submit with all the fields empty , it will show you the above messages.

Some More Useful Links : Liferay-UI TagLib : Liferay Freak : Minesweeper Portlet Game Main Page of Development Articles in Liferay From DB to simple UI
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Liferay MVC Framework : Liferays Permissioning System : Portal Properties Liferay 6.0.5 Alloy UI Forms : Alloy-UI Scripting basics : Alloy-ui Working with widgets : Alloy-ui Working with Ajax : and plug-ins :

Liferay : Default Landing Page


import java.util.HashMap; We have seen in liferay that , when we login , we get directed to the Welcome Page of Liferay. An interesting questions would be how to change that default functionality ? Its simple. Liferay provides certain events 1) Start-up Events 2) Shut-Down Events 3) Portal Events Now we are interested in Portal Event which have 4 Types 1) Pre Login 2) Post Login 3) Pre Logout 4) Post Logout 1) Open your portlet-ext.properties file and insert the following lines login.events.post=com.liferay.portal.events.LoginPostAction, com..defaultlandingpage.CustomLandingPageAction auth.forward.by.last.path=true default.landing.page.path= So Basically , the format is login.events.post=com.liferay.portal.events.LoginPostAction,your.package.cl
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

ass.name By inputting this line you are informing liferay that , the default functionality of LoginPostAction class has been overriden by your custom class. Now how to achieve this overriding behavior ? Thats a multi-million dollar question !
import import import import import import import import import import import import import import import javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; javax.servlet.http.HttpSession; com.liferay.portal.kernel.events.Action; com.liferay.portal.kernel.exception.PortalException; com.liferay.portal.kernel.exception.SystemException; com.liferay.portal.kernel.log.Log; com.liferay.portal.kernel.log.LogFactoryUtil; com.liferay.portal.kernel.struts.LastPath; com.liferay.portal.kernel.util.PropsKeys; com.liferay.portal.kernel.util.StringPool; com.liferay.portal.kernel.util.Validator; com.liferay.portal.kernel.util.WebKeys; com.liferay.portal.model.User; com.liferay.portal.util.PortalUtil;

public class CustomLandingPageAction extends Action { private static Log _log = LogFactoryUtil.getLog(CustomLandingPageAction.class); public void run(HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(); String path = null; User user = null; if( session != null ){ try { user = PortalUtil.getUser(request); path = user.getScreenName(); _log.debug("path = " + path); } catch (PortalException e) { _log.error("Error: " + e.getMessage()); } catch (SystemException e) { _log.error("Error: " + e.getMessage()); } } if (Validator.isNotNull(path) && user != null){ //login user with its default page LastPath lastPath = new LastPath(StringPool.BLANK, "/user/"+path, new HashMap()); _log.info("Use Default User Path: " + lastPath.toString()); session.setAttribute(WebKeys.LAST_PATH, lastPath); } else{ //use the default landing page from config. _log.info("Using the default landing page from config");

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

} }

setDefaultLandingPagePath(session);

private void setDefaultLandingPagePath(HttpSession session) { String path=PropsKeys.DEFAULT_LANDING_PAGE_PATH; if (Validator.isNotNull(path)) { LastPath lastPath = new LastPath(StringPool.BLANK, path, new HashMap()); session.setAttribute(WebKeys.LAST_PATH, lastPath); _log.debug("Use System Config LastPath URL: "+ lastPath.toString()); System.out.println("Use System Config LastPath URL: "+ lastPath.toString()); } else { _log.error("Default Landing Page is Null"); } } }

The Run Method will be called the moment the user Logs In.
user = PortalUtil.getUser(request); path = user.getScreenName();

Using the above method we get all the details of the user , like the screen name. Now , when you start liferay , form your tomcat machine , you specify the path as http://localhost:8080 This path is basically your domain name. When the user logs in , Liferay by Default, appends "/web/group/home". This basically is the address of the Default Public Community of liferay called liferay.com. You can always go to the communities and check.There will be a liferay.com community which is public and has no private pages.It has only one public Page. layout.friendly.url.private.group.servlet.mapping=/group layout.friendly.url.private.user.servlet.mapping=/user layout.friendly.url.public.servlet.mapping=/web Now these are the layout friendly URLs , which map to specific pages of liferay. The first one "/group" maps to the private page of a community. "/user" Maps to the private page of the user.
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

"/web" Maps to the public page of a public community. Now, we know how the mapping takes place.But how to actually Map the page in the code ?
if (Validator.isNotNull(path) && user != null){ //login user with its default page LastPath lastPath = new LastPath(StringPool.BLANK, "/user/"+path, new HashMap()); _log.info("Use Default User Path: " + lastPath.toString()); session.setAttribute(WebKeys.LAST_PATH, lastPath); } else{ //use the default landing page from config. _log.info("Using the default landing page from config"); setDefaultLandingPagePath(session); }

Here , the variable "path" is actually holding the screenname of the user. So first we check , whether the user logged in is a registered user or Not. If he is not then forward him to "web/guest/home" page which is the default page set with the property company.default.home.url=/web/guest Then notice that, in the lastPath variable declaration we are setting the path as "user"+path This basically means we shall have something like this when lets say you sign in as Test Test http://localhost:8080/user/joebloggs/home "home" is the first page of the private layout of Joe Bloggs. Keeping all the code same , we can in this way modify the default Landing page of the user PostLogin. similary we can have a user directed directly to the private page of his community , by simply appending the "group"+path , path being the name of the community. Now , what if , you want to have a particular Private Page for particular group of users , like you may have a different customization for different users , For Ex : If you have a College Portal , there might be students of Arts,Commerce and Science, And for each you might want to have a different page. What to do ?
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Simple, just create differerent UserGroups and design the public/private pages according to the requirement. It Works ! and its very Simple ! Now , about deployment. This is a bit tricky.y In eclipse , you"ll need to create a new liferay project. And since with every project you always get a portlet , this time you will have to ingore that portlet. Just create a different package , a new class , and then simply paste the code above in that class. Modify it as per your requirement , but now i am sure you know what you really need to modify. just the lastPath Object.Nothing else. Keep everything the same. Once that is done , just export that package , as a jar file and put that jar file in the lib directory of tomcat. Also , donot forget to add the following lines to portal-ext.properties file login.events.post=com.liferay.portal.events.LoginPostAction, com..defaultlandingpage.CustomLandingPageAction auth.forward.by.last.path=true default.landing.page.path= Enjoy !!!

Liferay HOWTOs - I
There are a lot of places where liferay can tuned and tweaked . I shall discus some of them. Most of these tweaks can be done by looking at Portal Properties 6.0.5

1) How to change the domain name from liferay.com to example.com


Company Properties company.default.web.id=liferay.com change it to example.com

2) How to change my login ? If i want to use screen name instead of emailAddress


company.security.auth.type=emailAddress #company.security.auth.type=screenName #company.security.auth.type=userId
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

In the above case , screenName and userId are commented out using # 3) Password Related

Set this to true to allow users to ask the portal to send them their password. company.security.send.password=true

Set this to true to allow users to ask the portal to send them a password reset link. company.security.send.password.reset.link=true

Set the following encryption algorithm to encrypt passwords. The default algorithm is SHA (SHA-1). If set to NONE, passwords are stored in the database as plain text. The SHA-512 algorithm is currently unsupported. #passwords.encryption.algorithm=CRYPT #passwords.encryption.algorithm=MD2 #passwords.encryption.algorithm=MD5 #passwords.encryption.algorithm=NONE passwords.encryption.algorithm=SHA #passwords.encryption.algorithm=SHA-256 #passwords.encryption.algorithm=SHA-384 #passwords.encryption.algorithm=SSHA Uncomment whichever password encryption algo you would like http://www.blogger.com/img/blank.gifto use

Set your own regex pattern for your Password passwords.regexptoolkit.pattern=(?=.{4})(?:[a-zA-Z0-9]*)

Set this to true to allow the user to choose a password during account creation. login.create.account.allow.custom.password=false

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

More On Passwords 4) I want to have my own Login portlet , what to do ? Change the following properties with your own login Portlet id auth.login.portlet.name=58 here 58 is the portletId or the portlet name of Login Portlet used in Liferay. In your Portlet , use the following functions to add users and depending on your requirement add them to their respective groupshttp://www.blogger.com/img/blank.gif ? 1 2User user = UserLocalServiceUtil.addUser(0, companyId, 3autoPassword,password1, password2, autoScreenName, screenName, emailAddress,facebookId, openId, locale, 4, middleName, lastName,prefixId, suffixId, male, 5birthdayMonth, birthdayDay,birthdayYear, jobTitle, 6groupIds, organizationIds, roleIds,userGroupIds, sendEmail, serviceContext); 7 UserLocalServiceUtil GroupLocalServiceUtil UserGroupLocalServiceUtil RoleLocalServiceUtil

4) Get Rid of the remind queries while Registration


To enable them set both to true. users.reminder.queries.enabled=false users.reminder.queries.custom.question.enabled=false

5) Static Portlets
Set the static portlets that will appear for every layout. See /html/portal/layout/view/portlet.jsp for the logic of when these portlets will be shown. For example, these portlets will only show for layouts that can contain portlets and are not in a pop up state.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

layout.static.portlets.all=1_WAR_chatportlet 6) If you want to remove the wrench-shaped icon for Look and Feel and Configuration, you can add the following code to your portlet JSP file: ? 1 2<% ThemeDisplay themeDisplay= 3(ThemeDisplay)renderRequest.getAttribute(WebKeys.THEME_DISPLAY); 4PortletDisplay portletDisplay= themeDisplay.getPortletDisplay(); 5portletDisplay.setShowConfigurationIcon(false); %> 6

7) SignIn , CreateAccount Links in themeDisplay


? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2

//Check Whether the user is signed in or not themeDisplay.isSignedIn(); // Liferay Defined URLs in themeDusplay themeDisplay.getURLAddContent(); themeDisplay.getURLControlPanel(); themeDisplay.getURLCreateAccount(); themeDisplay.getURLHome(); themeDisplay.getURLSignIn(); themeDisplay.getURLSignOut();

8) How can I give all my users the ability to Maxmize and Minimize portlets abilities only?
For guest we can do in portal-ext.properties while for users u need to customize portlet.vm file of your theme. it can be done like this #if ($permissionChecker.isCompanyAdmin($company_id)) $theme.iconOptions() $theme.iconClose() #end so admin only can see all icon . and all other users will get only maximize and minimized icon. Don't forget to stop and start the server after modifying vm files...
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

9) What are some suggestions on improving start up time under a VM?


It may take several (five-plus) minutes to reboot Liferay. We are running 4.1 Liferay Enterprise in a virtual web server. I've removed unused portlets to try to cut down the booting speed, but that doesn't help much. What are other ways available to speed up? Of course, a physical server rather than a virtual server will help. What else? Adding more memory to the JVM via the argument of: -Xmx1024m will help. Depending on what you are using Liferay for, you can remove uneeded webapps under /webapps (for Tomcat). Another thing that will help is to set: index.on.startup=false in portal-ext.properties. This property tells Lucene not to reindex content that is part of the portal.

10) How do you completely hide portlets with borders that users dont have permission to see?
To change this feature for all the portlets in the portal, set the following parameter in portal.properties to "false": layout.show.portlet.access.denied=false To change this feature on a per portlet level, set the "show-portlet-accessdenied" parameter in liferay-portlet.xml to "false" for a particular portlet. The setting in liferay-portlet.xml will override the setting in portal.properties.

11) How do you completely hide portlets with borders that are inactive?
To change this feature for all the portlets in the portal, set the following parameter in portal.properties to "false": layout.show.portlet.inactive=false To change this feature on a per portlet level, set the "show-portlet-inactive" parameter in liferay-portlet.xml to "false" for a particular portlet. The setting in liferay-portlet.xml will override the setting in portal.properties.

12) How do you display/store images in Liferay?


There are 2 ways to display images in Liferay:
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

1) There is a portlet called "Image Gallery" that can be used to upload images to the portal. These images can then be accessed in your HTML in the following way: ? 1<img src="/image/image_gallery?img_id=1001"> 2

Obviously, this may not be the optimal way to access images because you would have to know each image's ID in order to display it. However, this is probably the quickest and least intrusive way to do it. 2) Images can be put into the theme of your page. Each theme has the same directory structure, and one of those directories is the "images" directory. Within the images directory, we've further divided the image files into more granular directories (e.g., blogs, document_library, message_boards, etc.). You can create your own directory and place any image files that you may need here. You would then access the files in the following way: ? 1<img src="<%= themeDisplay.getPathThemeImage() 2%>/your_portlet/some_image.gif"> Reference for Questions 8-12

13) How Do i Associate new Users with a Default community or a default landing page ? 14) How to add Expression Language EL in JSPs in Liferay ?
add the following lines in your init.jsp or your jsp page using the EL ? 1<%@ page contentType="text/html" isELIgnored="false" %> 2 Will Keep Adding as and when i come across new thing

Liferay UI Taglib
Here are a few UI TagLibs defined by liferay which can be used in your jsps. For a few of the tags i have also displayed the code of how to retrieve it in the your Portlet.
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

1) Displaying the Users Pictures and Name , with link into the MyAccount Page

? 1 2<c:if test="<%=themeDisplay.isSignedIn()%>" > 3 4<liferay-ui:user-display displayStyle="0" 5userId="<%= themeDisplay.getUser().getUserId() %>" 6/> 7</c:if> 8

2) Displaying Option for Selecting Languages with Flags


? 1//Shows Flags 2<liferay-ui:language displayStyle="0" languageIds='<%= new String[] {"en_US","en_GB","en_AU"} %>' /> 3// Shows as a drop down list 4<liferay-ui:language displayStyle="3" languageIds='<%= new String[] 5{"en_US","en_GB","en_AU"} %>' />

3) Liferay UI Tabs 4) Date Picker


The date picker object Is very simple to implement. Here is the implementation code.

? 1 2 3 4 5 6 7 8 9

<p> <% Calendar dop = CalendarFactoryUtil.getCalendar(); dop.setTime(book.getDateOfPurchase()); %> <aui:input model="<%=Books.class %>" bean="<%=book%>" label="Date of Purchase" name="dateOfPurchase" value="<%= dop %>" /> </p> //And here is how you would retrieve the Date object,

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9

nt dopMonth = ParamUtil.getInteger(request, "dateOfPurchaseMonth"); int dopDay = ParamUtil.getInteger(request, "dateOfPurchaseDay"); int dopYear = ParamUtil.getInteger(request, "dateOfPurchaseYear"); if (Validator.isDate(dopMonth, dopDay, dopYear)) { try { book.setDateOfPurchase(PortalUtil.getDate(dopMonth, dopDay, dopYear, new PortalException())); } catch (PortalException ex) { /* Setting to Null Will enable us to catch it in the Validator */ book.setDateOfPurchase(null); } } else { book.setDateOfPurchase(null); }

For the date picker , it is necessary to provide the Model and the bean attributes to the input tag. In the src/META-INF folder , we have a n xml file where we can set
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

restrictions on the datatypes portlet-model-hints.xml ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9

<?xml version="1.0" encoding="UTF-8"?> <model-hints> <model name="com.books.database.model.Books"> <field name="bookId" type="long" /> <field name="title" type="String" /> <field name="author" type="String" /> <field name="dateOfPurchase" type="Date"> <hint name="year-range-delta">90</hint> <hint name="year-range-future">true</hint> <hint name="show-time">false</hint> </field> <field name="pages" type="int" /> <field name="userId" type="long" /> <field name="companyId" type="long" /> <field name="groupId" type="long" /> </model> </model-hints>

We can also restrict the length of certain fields using ? 1<hint name=max-length>4000</hint> 2 For more info on model-hints , take a look at the liferay source code , portal-impl/src/META-INF/portal-modelt-hints.xml file. Model-Hints NOTE : While using the date field , the name attribute of the input tage should match with the name attribute of the field tag in portlet-model-hint.
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

5) Liferay-UI Panel
? 1<liferay-ui:panel-container > 2<liferay-ui:panel id="panelId" title="Any Title" collapsible="true" 3extended="true" > 4Any Content here 5<liferay-ui: </liferay-ui:panel> 6</liferay-ui:panel-container > 7

7) Liferay Text Area


? 1<liferay-ui:input-textarea param="aoi" defaultValue="Your Areas of Interest" 2/>

8) Liferay Time Select


? 1 2<liferay-ui:input-time 3amPmParam="ampm" hourParam="hour" 4minuteParam="min" 5minuteInterval="10" 6/> 7

9) Liferay Text Editor


? 1<liferay-ui:input-editor /> 2

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

More on Liferay Editor Soon...

Liferay UI Tabs
Creating Tabs is a really Cool feature and Liferay has an inbuilt functionality to do so. Here is how it can be done. 1) In your Project , first create the following files under the following path /docroot/jsps by creating a new folder called jsps view.jsp sunday.jsp monday.jsp tuesday.jsp admin.jsp code for view.jsp ? 1 2 3 4 5 6 7 8

<%@ 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://java.sun.com/jstl/core_rt" prefix="c" %> <%@page import="com.liferay.portal.kernel.util.ParamUtil" %> <%@page import="java.util.ArrayList"%> <%@page import="java.util.List"%> <liferay-theme:defineObjects />

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3

//A renderURL is created because we need to render a jsp page you need to use //renderURL we can also pass parameters if required <liferay-portlet:renderURL var="portletURL"/> <% //We must Specify a default value for tabs. In this example it is sunday. Else it //will throw an error. String tabValue = ParamUtil.getString(request, "tab", "sunday"); String tabsURL = "/jsps/" + tabValue.trim() + ".jsp"; String tabNames="Sunday,Monday,Tuesday" ; String tabVal="sunday,monday,tuesday" ; if(permissionChecker.isCompanyAdmin(themeDisplay.getCompanyId())){ tabNames+=",Admin" ; tabVal+=",admin" ; } %> <liferay-ui:tabs names="<%=tabNames%>" tabsValues="<%=tabVal%>" param="tab" url="<%= portletURL %>" /> //this wud render the tab page <c:import url="<%= tabsURL %>"></c:import>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 3 3 3 4 3 5 3 6 Here is how it would Look Like

The Admin Page Will be Visible only if an Admin Logs in.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

To Download the Project click here

Liferay HOWTOs - II
Liferay HOWTOs Part-I Continued from the first Part ,

15) How to programmatically get file content from document library?


? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4

long scopedGroupId = themeDisplay.getScopeGroupId(); DLFolder root = null; try { root = DLFolderServiceUtil.getFolder(DLFolderConstants.DEFAULT_PARENT_FOLDER_ID); List<DLFolder> sub = DLFolderServiceUtil.getFolders(scopedGroupId, root.getFolderId()); } catch (PortalException e) { e.printStackTrace(); } catch (SystemException e) { e.printStackTrace(); }

Now you can perform various operations by going through the code below on how to deal with files DLFolderServiceUtil Documentation

Adding Users to Groups,Communities,UserGroups Programmatically


This post shows how to programatically add a user to UserGroups,Communities,Groups etc. For an indepth understanding of what are the above notions click here.
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

Here is the code snippet to do the same. ? 1 2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6


long[] groupIds = new long[1]; long[] organizationIds = new long[1]; long[] roleIds = new long[1]; long[] userGroupIds = new long[1]; UserGroup userGroup = null; userGroup = UserGroupLocalServiceUtil.getUserGroup(companyId,"userGroupName"); log.info("User GRoup " + userGroup.getName()); Group group = GroupLocalServiceUtil.getGroup(companyId, "groupName"); log.info("Community " + group.getName()); Role role = RoleLocalServiceUtil.getRole(companyId, "roleName"); log.info("Role Name " + role.getName()); if (userGroup.getUserGroupId() > 0) { userGroupIds[0] = userGroup.getUserGroupId(); } else { userGroupIds = null; } if (role.getRoleId() > 0) { roleIds[0] = role.getRoleId(); log.info("Role Id" + roleIds[0]); } else { roleIds = null; } if (group.getGroupId() > 0) { groupIds[0] = group.getGroupId(); log.info("Group Id" + groupIds[0]); } else { groupIds = null; } Locale locale = Locale.ENGLISH; ServiceContext serviceContext = ServiceContextFactory.getInstance( User.class.getName(), actionRequest); User user = UserLocalServiceUtil.addUser(0, companyId, autoPassword,password1, password2, autoScreenName, screenName,emailAddress,facebookId, openId, locale, firstName, middleName, lastName,prefixId, suffixId, male, birthdayMonth, birthdayDay,birthdayYear, jobTitle, groupIds, organizationIds, roleIds, userGroupIds, sendEmail, serviceContext);

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 7 2 8 2 9 3 0 3 1 3 2 3 3 3 4 3 5 3 6 3 7 3 8 3 9 4 0 4 1

UserLocalServiceUtil GroupLocalServiceUtil UserGroupLocalServiceUtil RoleLocalServiceUtil

Liferay Refresh Bug


If you have downloaded myBooks-portlet example , and deployed it in your liferay server , you would observe that there is a small bug in the application.
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

After you add a book , and click on refresh it creates a duplicate copy of the same book Like Here in the picture below , i first add a book. (on the Side note , its a really awesome Book !)

Now , after i click on refresh , magically the same book gets added :P.

Well , there is nothing like magic (dont wana disappoint you if you are a big fan of harry porter) but the thing is that , when we click on refresh , the same portletURL gets executed once again. Means the entire lifecycle of the Portlet repeats from action-render. To avoid that , there are 2 ways 1) in the liferay-portlet.xml add the following line ? 1 2<portlet> 3 <portlet-name>booksportlet</portlet-name> 4 <icon>/icon.png</icon> 5 <action-url-redirect>true</action-url-redirect> <instanceable>false</instanceable> 6 7

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

pay close attention to the line <action-url-redirect>true</action-url-redirect> The value of this tag is by default false. 2) to transfer control to another jsp page or to the same jsp page we traditionally use sendRedirect("jspPage",jspPage) ; This method is highly inefficient as it merely renders the page. We also need to update the content in the page. so we need to have a different approach. Here is what you need to do. Just call the function below whenever you need to forward to another jsp. ? 1 public boolean forwardToJsp(String jspPage, ActionResponse response, ActionRequest request) { 2 boolean success =true ; 3 ThemeDisplay themeDisplay = (ThemeDisplay) request 4 .getAttribute(WebKeys.THEME_DISPLAY); portletName=(String) request.getAttribute(WebKeys.PORTLET_ID); 5 PortletURL portletURL = PortletURLFactoryUtil 6 .create(PortalUtil.getHttpServletRequest(request), portletName, 7 themeDisplay.getLayout().getPlid(), 8 PortletRequest.RENDER_PHASE); 9 1 try { portletURL.setWindowState(WindowState.NORMAL); 0 } catch (WindowStateException e) { 1 log.error(e); 1 return success=false ; 1 } portletURL.setParameter("jspPage",jspPage); 2 try { 1 response.sendRedirect(portletURL.toString()); 3 } catch (IOException e) { 1 log.error(e); 4 return success=false ; } 1 return success ; 5 } 1 6 1 7 1 8 1 9 2 0
Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 One interesting parameter here is "PortletRequest.RENDER_PHASE" Basically this parameter informs the Portal that the jspPage just needs to be rendered. What will happen in this case is that the portlet request and response will be of the type RenderRequest and RenderResponse If you are trying to transfer control to another portlet , then in that case you need to have "PortletRequest.EVENT_PHASE" , so the PortletRequest interface shall produce EventRequest and EventResponse type of Portlet Request. Cannot comment which one is better as i still have to look in passing parameters via request using the above methods.

Table Relationships
Lets Say there is a Parent Table and a Child Table. Now One Parent may have one ore more than one Children. So in your service.xml file should look something like this ? 1 2 3 4 5 6 7 8
<entity name="Parent" local-service="true" remote-service="false"> <column name="parentId" type="long" primary="true" /> . . .

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3

. . </entity>

<entity name="Child" local-service="true" remote-service="false"> <column name="childId" type="long" primary="true" /> <column name="parentId" type="Collections" entity="Parent" mappingkey="parentId" /> . . . </entity>

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

2 3 3 So basically , you are informing service.xml that parentId is the foreign key of the Child Table. Since, internally Liferay is using Spring and Hibernate , it injects an instance of Parent Object with all the Parent Functions into the ChildLocalServiceUtil. if you want to sepcify many to many relationship then in the above mentioned way use the relationship in the both entities.

Reference link: http://liferaydemystified.blogspot.com/2011/08/tablerelationships.html

S-ar putea să vă placă și