You are on page 1of 119

Liferay Developer's Guide

Liferay Developer's Guide Connor McKay, Editor Jorge Ferrer, Editor Copyright !"" #y Liferay, $nc% &his 'or( is offered under the Creative Co))ons *ttri#ution+,hare *li(e -nported license%

.ou are free/ to share0to copy, distri#ute, and trans)it the 'or( to re)i10to adapt the 'or( -nder the follo'ing conditions/ Attribution% .ou )ust attri#ute the 'or( in the )anner specified #y the author or licensor 2#ut not in any 'ay that suggests that they endorse you or your use of the 'or(3% Share Alike% $f you alter, transfor), or #uild upon this 'or(, you )ay distri#ute the resulting 'or( only under the sa)e, si)ilar or a co)pati#le license% &he full version of this license appears in the appendi1 of this #oo(, or you )ay vie' it online here/ http/44creativeco))ons%org4licenses4#y+sa45%! Contri#utors/ Joseph ,hu), *le1ander Cho', 6ed)ond Mar, Ed ,hin, 6ich ,e7ov, ,a)uel Kong, Connor McKay, Jorge Ferrer, Julio Ca)arero, Daniel ,an7, Juan Fern8nde7, ,ergio Gon78le7, Miguel 9astor, Ji) :in(ey

Table of Contents
C;<=E<&$;<,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%> 9-?L$,:E6 <;&E,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ -9D*&E,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ <ove)#er 5rd !"!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ Fe#ruary @th !""%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ March Ath !""%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ March 5"st%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%B 1. Introduction...................................................................................................................9 DE=EL;9$<G *99L$C*&$;<, F;6 L$FE6*.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%A 9ortlets%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"! ;pen,ocial Gadgets%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"! 6eusing e1isting 'e# applications%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"" ,upported &echnologies%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" EC&E<D$<G *<D C-,&;M$D$<G L$FE6*.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"5 Custo)i7ing the loo( and feel/ &he)es%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"5 *dding ne' predefined page layouts/ Layout &e)plates%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"5 Custo)i7ing or e1tending the out of the #o1 functionalities/ :oo( plugins%%%%%%%%%%%%%%%%%%%%"5 *dvanced custo)i7ation/ E1t plugins%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"E C:;;,$<G &:E ?E,& &;;L F;6 &:E J;?%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"E 2. The Plugins SDK...........................................................................................................17 $<$&$*L ,E&-9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"@ *nt Configuration%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"B 9lugins ,DK Configuration%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"A ,&6-C&-6E ;F &:E ,DK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"A 3. Portlet Develo !ent.....................................................................................................21 C6E*&$<G * 9;6&LE&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% " Deploying the 9ortlet%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *<*&;M. ;F * 9;6&LE&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 * Closer Loo( at the My Greeting 9ortlet%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% E F6$&$<G &:E M. G6EE&$<G 9;6&LE&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @ -<DE6,&*<D$<G &:E &F; 9:*,E, ;F 9;6&LE& ECEC-&$;<%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% A 9*,,$<G $<F;6M*&$;< F6;M &:E *C&$;< 9:*,E &; &:E 6E<DE6 9:*,E%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%55 DE=EL;9$<G * 9;6&LE& F$&: M-L&$9LE *C&$;<,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5> ;9&$;<*L/ *DD$<G F6$E<DL. -6L M*99$<G &; &:E 9;6&LE&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5@ ". #reating $i%era& The!es...............................................................................................39 $<&6;D-C&$;<%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5A C6E*&$<G * &:EME%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%E! Deploying the &he)e%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%E! *<*&;M. ;F * &:EME%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%E! &:-M?<*$L,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%E J*=*,C6$9&%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%E ,E&&$<G,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%E5 C;L;6 ,C:EME,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%EE 9;6&*L 96EDEF$<ED ,E&&$<G,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%EG &:EME $<:E6$&*<CE%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%E> '. (ooks........................................................................................................................... "9 C6E*&$<G * :;;K%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%EA Deploying the :oo(%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%EA ;=E66$D$<G * J,9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%G! Custo)i7ing J,9s 'ithout overriding the original%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%G! 9E6F;6M$<G * C-,&;M *C&$;<%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%G" E1tending and ;verriding portal%properties%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%G

iii

;=E66$D$<G * 9;6&*L ,E6=$CE%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%G ;=E66$D$<G * L*<G-*GE%96;9E6&$E, F$LE%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%GE ). *+t lugins....................................................................................................................'' C6E*&$<G *< EC& 9L-G$<%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%G> DE=EL;9$<G *< EC& 9L-G$<%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%GB ,et up%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%GB $nitial deploy)ent%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%GA 6edeploy)ent%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>" *dvanced custo)i7ation techniHues%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%> *dvanced configuration files%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%> Changing the *9$ of a core service%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>E 6eplacing core classes in portal+i)pl%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>G Licencing and Contri#uting%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>G DE9L;.$<G $< 96;D-C&$;<%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>> Method "/ 6edeploying Liferay's 'e# application%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>> Method / Generate an aggregated F*6 file%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>> M$G6*&$<G ;LD EC&E<,$;< E<=$6;<ME<&,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>B C;<CL-,$;<,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%>B 7. $i%era& ID*....................................................................................................................)9 $<,&*LL*&$;<%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@! 6eHuire)ents%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@! $nstallation steps%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@! *lternative installation%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@" ,E& -9%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ 6eHuire)ents%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ Liferay 9lugins ,DK ,etup%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@ Liferay 9ortal &o)cat 6unti)e 4 ,erver ,etup%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@5 &E,&$<G4L*-<C:$<G L$FE6*. &;MC*& ,E6=E6%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@B C6E*&$<G <EF L$FE6*. 96;JEC&,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@B DE9L;.$<G <EF L$FE6*. 96;JEC&, &; L$FE6*. ,E6=E6%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%B" $M9;6&$<G EC$,&$<G 96;JEC&, $<&; L$FE6*. $DE%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%B5 $)porting e1isting Liferay 9roIect fro) a 9lugins ,DK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%B5 Create one single proIect fro) one plugin in an e1isting sources%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%B5 Create )ultiple proIects for all plugins in a 9lugins ,DK%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%BG $)porting an e1isting Eclipse 9roIect that is not a'are of the Liferay $DE%%%%%%%%%%%%%%%%%%%%%%%B@ $)porting an e1isting Liferay $DE proIect%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%BB =erifying that the i)port has succeeded%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%BB ,. $i%era& APIs and -ra!e.orks.......................................................................................91 ,EC-6$&. *<D 9E6M$,,$;<,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%A" J,6 9ortlet ,ecurity%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%A" Liferay's 9er)ission ,yste) ;vervie'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%A5 $)ple)enting 9er)issions%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%A5 9er)ission *lgorith)s%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%A@ *dding a 6esource%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%A@ *dding 9er)ission%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%AB Chec(ing 9er)issions%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%AA *,,E& F6*MEF;6K%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"!E *dding, updating and deleting assets%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"!G Entering and displaying tags and categories%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"!> 9u#lishing assets 'ith *sset 9u#lisher%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"!@ ,E6=$CE ?-$LDE6%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%""5 Define the Model%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%""5 ;vervie' of service%1)l%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%""E Generate the ,ervice%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%""E Frite the Local ,ervice Class%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%""> ?uilt+$n Liferay ,ervices%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%""@ ;&:E6 F6*MEF;6K,%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%""@ 9. /esources %or $i%era& Develo ers................................................................................119

iv

10. #onclusions...............................................................................................................123

PREFACE

&his guide 'as 'ritten as a Huic( reference to getting started developing on the Liferay 9ortal platfor)% $t is a guide for those 'ho 'ant to get their hands dirty using Liferay's fra)e'or( and *9$s to create fantastic 'e#sites% For a )ore e1haustive vie' into Liferay develop)ent, 'e encourage you to chec( out the co)plete, official guide to Liferay develop)ent, Liferay in Action, pu#lished #y Manning 9u#lications% .ou can find this #oo( online at http/44)anning%co)4se7ov% &he infor)ation contained herein has #een organi7ed in a for)at si)ilar to a ref+ erence, so that it 'ill #e easier to find specific details later%

Conventions
,ections are #ro(en up into )ultiple levels of headings, and these are designed to )a(e it easy to find infor)ation% Tip: This is a tip. Tips are used to indicate a suggestion or a piece of information that affects whatever is being talked about in the surrounding text. They are always accompanied by this gray box and the icon to the left.

Source code and configuration file directives are presented like this. If source code goes multi-line, the lines will be \ separated by a backslash character like this.

Italics are used to represent lin(s or #uttons to #e clic(ed on in a user interface

vi

and to indicate a la#el or a na)e of a Java class% 1old is used to descri#e field la#els and portlets% 9age headers denote the chapters, and footers denote the particular section 'ith+ in the chapter%

Publisher Notes
$t is our hope that this guide 'ill #e valua#le to you, and that it 'ill #e an indis + pensa#le resource as you #egin to develop on the Liferay platfor)% $f you need any as+ sistance #eyond 'hat is covered in this guide, Liferay, $nc% offers training, consulting, and support services to fill any need that you )ight have% 9lease see http/44'''%liferay%co)4'e#4guest4services for further infor)ation a#out the ser+ vices 'e can provide% *s al'ays, 'e 'elco)e any feed#ac(% $f there is any 'ay you thin( 'e could )a(e this guide #etter, please feel free to )ention it on our foru)s% .ou can also use any of the e)ail addresses on our Contact Us page 2http/44'''%liferay%co)4'e#4guest4a#outJus4contactJus 3% Fe are here to serve you, our users and custo)ers, and to help )a(e your e1perience using Liferay 9ortal the #est it can #e%

Updates
November 3rd 2010
E1tended e1isting infor)ation a#out the e1t plugin and added infor)ation a#out alternatives for deploy)ent to production%

February 27th 2011


;verall revie' of the style #y 6ich ,e7ov% ;verall revie' of the guide and re'rite of so)e sections #y Jorge Ferrer% 6e'rite of the introduction to )a(e it )ore 'elco)ing to ne' developers% <e' section/ K-nderstanding the t'o phases of portlets/ action and renderL E1tended infor)ation of the chapter a#out KE1t 9luginsL #y &o)as 9olesovs(y% <e' section on J,6+ B> security #y &o)as 9olesovs(y% <e' chapter a#out the *sset Fra)e'or( and Huic( introduction to other Liferay fra)e'or(s% <e' chapter a#out Liferay $DE <e' chapter for Conclusions 'ith infor)ation a#out ho' to learn )ore after reading this guide% <e' chapter 'ith lin(s to reference docu)entation%

March 9th 2011


Minor i)prove)ents and fi1es #ased on the co))ents #y co))unity )e)+ vii

#ers David : <e#inger and De# &ro1el%

April 7th 2011


E1tracted out Liferay $DE into its o'n chapter and e1pand it 'ith )ore in+ for)ation% -pdate infor)ation to Liferay $DE v"% % &he ,ervice ?uilder section has #een )oved 'ithin the chapter a#out *9$'s and fra)e'or(s and the chapter on tools has #een re)oved%

April 29th 2011


-pdated the Chec(ing 9er)issions section to focus on per)ission 'ith re+ spect to )odel resources% 9rovided )inor updates to the ,ecurity and 9er+ )issions section overall% *dded section Creating :elper Classes for 9er)ission Chec(ing%

viii

1. INTRODUCTION

Felco)e to the Liferay's Developers Guide, the official guide for all developers that 'ant to develop a portal #ased on Liferay or that 'ant to develop an application that anyone can use in their Liferay installation% &his guide 'ill asu)e that you already (no' 'hat a portal is and (no' ho' to use Liferay fro) an end user per+ spective% $f you don't, it is reco))ended that you read the What is a Portal? Fhitepa+ per and chapters ", G and > of Liferay's *d)inistration Guide% &his first chapter introduces the technologies and tools that you 'ill #e a#le to use to develop applications and also to e1tend or custo)ise the functionalities that Liferay provides out of the #o1 to adapt the) to your needs% &he )ain )echanis) that you as a developer 'ill use to achieve all of the a#ove in a )odular 'ay are Liferay 9lugins% Liferay 9lugins are al'ays distri#uted as Fe# *rchives 2%'ar files3, and deployed through Liferay's deploy )echanis)s% &here are different types of plugins depending of its purpose% &he follo'ing sections descri#e ho' to develop applications for Liferay and ho' to perfor) custo)i7ations and the types of plugins that you can use in each case%

Developing applications for Liferay


*ccording to Fi(ipedia K* 'e# application is an application that is accessed over a net'or( such as the $nternet or an intranet%L% * portal application is a 'e# applica+ tion that can cohe1ist 'ith )any other applications in a civili7ed 'ay and also that can reuse )any functionalities provided #y the portal platfor) to reduce the develop+ )ent ti)e and deliver a )ore consistent e1perience to end users% $f you are reading this, you pro#a#ly 'ant to 2or need to3 develop an application that runs on top of Liferay 9ortal% *nd you )ight #e loo(ing for an ans'er to the Huestion of what is the best and quickest way to do it? Liferay provides t'o )ain 'ays to develop applications, and #oth are #ased on standards/ 9ortlets/ portlets are s)all 'e# applications 'ritten in Java that follo' a

$ntroduction certain set of rules to allo' coha#itation 'ithin the sa)e portal or even 'ithin the sa)e page% 9ortlets can #e used to #uild applications as co)ple1 as you 'ant since the full suite of technologies and li#raries for the Java platfor) can #e used% ;pen,ocial Gadgets/ gadgets are usually s)all applications, 'ritten us+ ing #ro'ser side technologies such as :&ML and Javascript% ;ne inter+ esting #enefit of gadgets is that they are easy to develop and for that reason there are thousands of the) in repositories such as iGoogle's repository% Fhen the application #eco)es )ore co)plicated you 'ill need a co)ple)entary #ac(end technology, such as portlets or regular Java 'e# applications%

&he follo'ing sections descri#e these options 'ith so)e )ore detail%

Portlets
9ortlets are s)all 'e# applications 'ritten in Java that run in a portion of a 'e# page% &he heart of any portal i)ple)entation is its portlets, #ecause they contain the actual functionality% &he portlet container is only responsi#le for ag+ gregating the set of portlets that are to appear on any particular page% 9ortlets are the least invasive for) of e1tension to Liferay, as they are en+ tirely self contained% ConseHuentially portlets are also the the )ost for'ard co)pati#le develop)ent option% &hey are hot+deployed as plugins into a Liferay instance, resulting in 7ero do'nti)e% * single plugin can contain )ultiple port+ lets, allo'ing you to split up your functionality into several s)aller pieces that can #e arranged dyna)ically on a page% 9ortlets can #e 'ritten using any of the Iava 'e# fra)e'or(s that support portlets develop)ent, including Liferay's spe+ cific fra)e'or(s/ M=C9ortlet or *lloy9ortlet%

OpenSocial Gadgets
Li(e portlets, ;pen,ocial Gadgets are an standard 'ay to develop applica+ tions for a portal environ)ent% Fro) a technology perspective one (ey differ+ ence is that they don't )andate an specific #ac(end technology, such as JavaEE, 9:9, 6u#y, 9ython, etc% *nother difference is that it has #een designed specific+ ally to i)ple)ent social applications, 'hile portlets 'ere designed any type of application% ?ecause of this, ;pen,ocial Gadgets, not only provide set of techno+ logies to develop and run applications #ut also a set of *9$s that allo' the applic+ ation to o#tain infor)ation fro) the social environ)ent such as infor)ation a#out the user profile, his activities or his friends% $t is possi#le to deploy ;pen,ocial Gadgets in Liferay in one of t'o 'ays/ 6e)ote Gadget/ * re)ote gadget is one that is e1ecuted in a re)ote server #ut is sho'n to the user in a given page Iust as if it 'as another application of the platfor)% &his option is very si)ple #ut has the dra'#ac( that the portal depends on the re)ote server for that gadget to 'or(% &his )ight not even #e an option in so)e intranet environ+ )ents in 'hich there isn't full access to $nternet%

"!

Developing applications for Liferay

$ntroduction Local Gadget/ consists in deploying the gadget in the Liferay server in the si)ilarly as portlets are deployed% Gadgets are defined as an CML file so all you need to do is to upload that file to the server% ,o)e people li(e to upload the) directly through the file syste), F&9 or si)ilar protocols% $n so)e other cases, Iust uploading it 'ith theDocu+ )ent Li#rary portlet and copying the -6L is enough% ;nce you have the -6L you can go to the Control 9anel M ;pen,ocial, clic( the K<e' GadgetL #utton and enter the -6L as sho'n in the follo'ing screen+ shot/

*fter this is done, the gadget 'ill appear as an application that page ad)in + istrators can add to their pages% ;ne additional very interesting feature of the latest versions of Liferay is that it is possi#le to e1pose any application developed as portlets, as ;pen,ocial gadgets to the outside 'orld% &hat is, you can develop a portlet and then let any+ one 'ith access to your portlet to add it to the pages of other portals or social net'or(s as a re)ote gadget% <ote that since an ;pen,ocial gadget is defined in an CML file, there is no need to create a plugin 2that is a %'ar file3 in order to deploy it% *ll you need to do is )a(e that CML file accessi#le 'ithin the sa)e or another server and let Liferay (no' the -6L%

Reusing existing web applications


,o)eti)es you don't start fro) scratch, #ut there is an e1isting application that already e1ists and 'hich has not #een i)ple)ented using 9ortlets or ;pen,ocial Gadgets% Fhat can you do in that situationN &here are )any options availa#le% ,o)e of the )ost popular are/ 6e'rite your application as a portlet Create si)ple portlets that interact 'ith your application 2possi#ly us+ ing Fe# ,ervices3 and offer all or part of the functionality to end users%

Developing applications for Liferay

""

$ntroduction Create an ;pen,ocial gadget as a 'rapper for your application% &he Gadget 'ill use an $fra)e to sho' part of your application in the portal page% Create a portlet that integrates the re)ote application either using an ifra)e or an :&&9 pro1y 2For e1a)ple using Liferay's Fe#9ro1y port+ let3% .ou 'ill also need to find a 'ay to achieve transfer the authentica+ tion #et'een the portal and your application%

&here are )any )ore options and )any reasons 'hy you )ay 'ant to choose one or another% 6evie'ing each of the) is out of the scope of this guide% $f the e1isting application has #een developed as a JavaEE application, Liferay provides a technology caled Fe# *pplication $ntegrator that allo's pro+ totyping the integration and provides several nice features% $n order to use Fe# *pplication $ntegrator all you need to do is deploy the F*6 file of your 'e# application as you 'ould do 'ith any Liferay plugin 2for e1a)ple, #y using the control panel or #y copying it to the deploy directory3% *s a result Liferay 'ill auto)atically create a portlet that integrates your applica+ tion using an ifra)e%

Supported Technologies
Liferay as a platfor) strives to provide co)pati#ility 'ith all Java technolo+ gies that a developer )ay 'ant to use to develop their o'n applications% &han(s to the portlet and the JavaEE specifications each portlet application can use its o'n set of li#raries and technologies regardless of 'hether they are 'hat Liferay uses itself or not% &his section refers )ainly to portlet plugins, other plugin types are )ore restricted% For e1a)ple the e1t plugins can only use li#raries that are co)pati#le 'ith the ones used #y the core Liferay code% ,ince the choice of availa#le fra)e'or(s and technologies is very #road, the tas( can #e daunting to ne'co)ers% &his section atte)pts to provide so)e ad+ vice to help developers choose the #est tools for their needs% &his advice can #e grouped in three/ "% % -se 'hat you (no'/ $f you already (no' a fra)e'or(, that can #e your first option 2,truts , ,pring M=C, 9:9, 6u#y%%%3 *dapt to your real needs/ Co)ponent #ased fra)e'or(s 2J,F, =aadin, GF&3 are specially good for des(top+li(e applications% M=C fra)e'or(s on the other hand provide )ore fle1i#ility% Fhen in dou#t, pic( the si)pler solution/ 9ortlet applications are often )uch si)pler than standalone 'e# applications, so, 'hen in dou#t use si)pler fra)e'or(s% 2M=C 9ortlet, *lloy 9ortlet3

5%

,o)e of the fra)e'or(s )entioned a#ove include their o'n Java,cript code to provide a very high degree of interaction% &hat is the case of GF&, =aadin or J,F i)ple)entations such as $ceFaces or 6ich Faces% $n other cases the de+ velopers prefer to 'rite their o'n Java,cript code% $n such cases it's )ost often reco))ended to use one of the availa#le Java,cript li#raries% ,o)e of the )ost

"

Developing applications for Liferay

$ntroduction co))on li#raries that can #e used 'ith Liferay are IOuery, DoIo, .-$, ,encha 2previously (no'n as E1tJs3, ,proutcore, etc% ,tarting 'ith version >, Liferay also provides its o'n li#rary called *lloy-$ 'hich is #ased on .-$ 5 and provides a large set of co)ponents specifically designed for very efficient and interactive applications that 'or( 'ell in portal environ)ents% Liferay's core portlets use *lloy-$ for all Javascript code% Developers can also use *lloy-$ for their custo) portlets or choose any other Java,cript li#rary as long as they )a(e sure that it 'ill not create conflicts 'ith the code of other portlets deployed in the sa)e portal% ?esides the fra)e'or(s and li#raries )entioned in this section, there are literally thousands )ore availa#le to Java developers to handle persistence, caching, connections to re)ote services, and )uch )ore% Liferay does not i)+ pose specific reHuire)ents on the use of any of those fra)e'or(s so that portal developers can choose the #est tools for their proIects%

Extending and customizing Liferay


Liferay provides )any out of the #o1 features, included a fully featured con+ tent )anage)ent syste), a social colla#oration suite and several productivity tools% For so)e portals those functionalities )ight #e e1actly 'hat you need, #ut for so)e others you )ight 'ant to e1tend the) or custo)i7e ho' they 'or( or ho' they loo( #y default% Liferay provides several types of plugins that are speciali7ed for an specific type of custo)i7ation% $t is possi#le to co)#ine several plugin types into a single %'ar file% For e1a)ple it is a co))on practice to co)#ine &he)es and Layout &e)plates% &he follo'ing sections descri#e each type of plugin you )ay need to use%

Customizing the look and feel: Themes


&he)es allo' the loo( of the Liferay portal to #e changed using a co)#ina+ tion of C,, and =elocity te)plates% $n )any cases, it is possi#le to adapt the de+ fault Liferay the)e to the desired loo( using only C,,, providing the )ost for+ 'ard co)pati#ility% $f C,, is not sufficient and )ore )aIor changes are reHuired, Liferay allo's you to include only the te)plates you )odified in your the)e, and it 'ill auto)atically copy the rest fro) the default the)e% Li(e portlets, the)es are hot+deployed as plugins into a Liferay instance%

Adding new predefined page layouts: Layout Templates


Layouts are si)ilar to the)es, e1cept that they change the arrange)ent of portlets on a page rather than its loo(% Layout te)plates are also 'ritten in =elo+ city and are hot+deploya#le%

Customizing or extending the out of the box functionalities: Hook plugins


:oo( plugins are the reco))ended )ethod of custo)i7ing the the core E1tending and custo)i7ing Liferay "5

$ntroduction functionality of Liferay at )any predefined e1tension points% :oo( plugins can #e used to )odify portal properties or to perfor) custo) actions on startup, shutdo'n, login, logout, session creation and session destruction% -sing service 'rappers, it is possi#le for a hoo( plugin to replace any of the core Liferay ser+ vices 'ith a custo) i)ple)entation% :oo( plugins can also replace the J,9 te)+ plates used #y any of the default portlets, allo'ing you to custo)i7e their ap+ pearance as desired% ?est of all, hoo(s are hot+deploya#le plugins Iust li(e port+ lets%

Advanced customization: Ext plugins


E1t plugins provide the largest degree of fle1i#ility in )odifying the Liferay core, and allo' replacing essentially any class 'ith custo) i)ple)entations% &his fle1i#ility co)es at a cost ho'ever, as it is highly unli(ely that an E1t plugin 'ritten for one version of Liferay 'ill continue to 'or( in the ne1t version 'ithout )odification% For this reason, E1t plugins are only reco))ended for cases 'here an advanced custo)i7ation is really needed and there is no other 'ay to acco)plish the sa)e goal% *lso you should )a(e sure that you are fa)ili+ ar 'ith the Liferay core to )a(e sure the E1t plugin doesn't have a negative ef+ fect on e1isting funcitonalities%% Even though E1t plugins are deployed as plu+ gins, the server )ust #e restarted for changes to ta(e effect% For this reason, E1t plugins should not #e co)#ined 'ith other types of plugins% Tip: If you have developed for Liferay 5.2 or before, you may be familiar with what was known as Extension Environment. Ext plugins are a new feature in Liferay 6.0 which replace the extension environment in order to simplify its development. It is possible to automatically convert any existing Extension Environment into a plugin. Check the chapter Migrating old extension environments for detailed instructions.

Choosing the best tool for the job


&he Java ecosyste) is 'ell (no' for providing a 'ide variety of options for al)ost any developer 'or( that )ust #e done% &his is a great advantage #ecause you can find the tool that fits #est your needs and the 'ay you 'or(% For that reason once you have found a tool that you are conforta#le 'ith and have learned to use it you 'ant to (eep using it% ;n the other hand, the 'ide variety of tools is often inti)idating for ne'+ co)ers, #ecause they need to choose 'hen they still don't have the e1perience to decide 'hich option is #etter% $n Liferay 'e have ta(en a prag)atic approach to )a(e sure Liferay de+ velopers can #enefit fro) the variety of options 'hile still provide a learning curve that is as soft as possi#le% &o do that 'e have chosen t'o ;pen ,ource technologies that you can use if you don't have another favorites/ *pache *nt and the 9lugins ,DK/ Liferay provides a develop)ent en+ viron)ent called the 9lugins ,DK that 'ill allo' you to develop all types of plugins #y e1ecuting a set of predefined co))ands 2also Choosing the #est tool for the Io#

"E

$ntroduction (no'n as targets sin *nt's no)enclature3% .ou can use the 9lugins ,DK directly fro) the co))and line, using editors li(e E)acs, =i Edit9lus or even the <otepad% .ou can also integrate it 'ith your favorite $DE, since al)ost all of the) provide support for *pache ant% &he ne1t chapter descri#es ho' to use the 9lugins ,DK in detail% Eclipse and the Liferay $DE/ Eclipse is the )ost popular and 'ell (no'n Java $DE and provides a 'ide variety of features% Liferay $DE is a plugin for Eclipse that e1tend its functionalities to )a(e develop)ent of all types of Liferay plugins )uch easier% Liferay $DE uses the 9lugins ,DK underneath, #ut you don't even need to (no' unless you are trying to perfor) an advanced operation not directly supported #y the $DE%

&his guide 'ill sho' ho' to develop for Liferay using the 9lugins ,DK% Fe have done so to )a(e sure that it 'as useful for as )any developers as possi#le even if they don't li(e $DEs or if they don't use Eclipse% &he guide also has a full chapter on the Liferay $DE% $f you are an $DE person and specially if you are an Eclipse user, you )ay start #y reading that chapter first and then go #ac( to reading fro) the second chapter% $t 'on't #e hard to re + peat the steps descri#ed in the guide using the Liferay $DE% 2hat about i% I don3t like A ache Ant and I re%er to use 4aven5 Many developers prefer one of the alternatives to *pache *nt% &he )ost popular of these alternatives is Maven% &o support developers that 'ant to use Maven 'e have mavenized Liferay artifacts so that they can easily #e referred fro) your po)%1)l% Fe are in the process of 'riting a chapter a#out using Maven for Liferay develop)ent and 'ill #e added to this guide in the future% Mean'hile chec( the follo'ing #log entry fro) &hiago Moreira for )ore infor)ation/ http/44'''%liferay%co)4'e#4thiago%)oreira4#log4+4#logs4liferay+s+arti+ fact+are+no'+)aveni7ed 2hat i% I don3t like *cli se and re%er to use 6etbeans7 Intelli8 ID*A or other ID*5 &here are )any $DEs out there and everyone has its strong aspects% Fe decided to #uild Liferay $DE on top of Eclipse #ecause it is the )ost popular ;pen ,ource option% ?ut 'e also 'ant to )a(e sure developers can use their $DE of choice% $n fact Huite a fe' core developers use <et#eans and $ntelliI $DE* 2'ho has gracefully provided an ;pen ,ource license to Liferay's core developers3% ?oth of these $DEs have support for integration 'ith *pache *nt, so you can use the 9lugins ,DK 'ith the)% *dditionally, ,un Microsyste)s developed an e1ten+ sion to <et#eans called the Portal Pack that is e1plicitly designed to develop plu+ gins for Liferay 2and their Liferay flavour called Fe#,pace3% .ou can find )ore a#out the 9ortal 9ac( in the follo'ing -6L/ http/44net#eans%org4(#4articles4portalpac(%ht)l &hat's it for the introduction% Let's get started 'ith real develop)ent 'or(P

Choosing the #est tool for the Io#

"G

2. THE PLUGINS SDK

Java developers have a 'ide variety of tools and develop)ent environ)ents% Liferay )a(es every effort to re)ain tool agnostic, so that you can choose the tools that 'or(s #est for you% For that reason 'e provide a 9lugins ,oft'are Develop)ent Kit 2,DK3 'hich is #ased on *pache *nt and )ay #e used along 'ith any editor or $n+ tegrated Develop)ent Environ)ent 2$DE3% &he chapters of this guide 'ill use the 9lu+ gins ,DK and a te1t editor, #ut you )ay use 'hatever tool you are co)forta#le 'ith% $n a later chapter 'e also introduce Liferay $DE, a plugin for eclipse that si)plifies de+ velop)ent for Liferay% Tip: If you are an Eclipse user and prefer to start working with it from be very beginning, you can read that chapter first before reading the rest of the guide..

Initial Setup
,etting up your environ)ent for Liferay develop)ent is very straightfor'ard% First, do'nload a fresh copy of Liferay 9ortal #undled 'ith &o)cat fro) the Liferay 'e#site at http/44'''%liferay%co)4do'nloads4% Fe reco))end using &o)cat for de+ velop)ent, as it is s)all, fast, and ta(es up less resources than )ost other servlet con+ tainers% *lso do'nload the 9lugins ,DK fro) the Additional iles page/ "% -n7ip #oth archives to a folder of your choosing% *void using a folder na)e that contains spaces #ecause so)e operating syste)s have pro#+ le)s running Java applications in folders 'ith spaces in the na)e% 2;ptional3 ?y default Liferay 9ortal Co))unity Edition co)es #undled 'ith )any plugins% $t's co))on to re)ove the) to speed up the server startup% &o do this, in the liferay!"ortal!#version$%tomcat!#tomcat! version$%weba""s directory, delete all the directories e1cept for /99T and tunnel:.eb.

&he 9lugins ,DK 5% ,tart Liferay/ Findo's/ navigate 'ith the file #ro'ser to liferay!"ortal!#version$%tomcat!#tomcat! version$%bin and dou#le clic( startu"&bat% &o shut the server do'n later, press Ctrl+C in the ter+ )inal 'indo'% Linu1 and Mac ;, C/ open a ter)inal, navigate to liferay!"ortal!#version$%tomcat!#tomcat!ver! sion$%bin, enter the follo'ing co))and

./startup.sh

;nce Liferay starts your #ro'ser should open to http/44localhost/B!B!4 and you can login 'ith the e)ail test'liferay&com and pass'ord test%

Ant Configuration
?efore you can #egin developing portlets, you )ust first have so)e tools in+ stalled% ?uilding proIects in the 9lugins ,DK reHuires that you have *nt "%@%! or higher installed on your )achine% Do'nload the latest version of *nt fro) http/44ant%apache%org4% Deco)press the archive into a folder of your choosing% <e1t, set an environ)ent varia#le called A6T;(94* 'hich points to the folder to 'hich you installed *nt% -se this varia#le to add the #inaries for *nt to your PAT( #y adding QA6T;(94*<bin to your PAT( environ)ent varia#le% .ou can do this on Linu1 or Mac ;, C #y )odifying your &bash("rofile file as follo's 2assu)ing you installed *nt in %)ava3/
export !"#$%&'(/)ava/apache-ant-*.+.* export , "$(-, "$.- !"#$%&'/bin

Close and reopen your ter)inal 'indo' to )a(e these settings ta(e effect% .ou can do this on Findo's #y going to Start +M Control Panel, and dou#le+ clic(ing the *ystem icon% Go to Advanced, and then clic( the +nvironment ,ariables #utton% -nder *ystem ,ariables, select -ew% Ma(e the =aria#le <a)e A6T;(94* and the =aria#le =alue the path to 'hich you installed *nt 2e%g%, c./)ava/a"ache! ant!0&1&03, and clic( 23% ,croll do'n until you find the PAT( environ)ent varia#le% ,elect it and clic( +dit% *dd =A6T;(94*=>bin to the end of the =aria#le =alue% Clic( 23, and then clic( 23 again% ;pen a co))and pro)pt and type ant :version and press Enter% .ou should get and output si)ilar to this/
pache nt/"&0 version *.+.1 compiled on 2ecember 13 13*3

$f not, chec( your environ)ent varia#le settings and )a(e sure they are pointing to the directory 'here you un7ipped *nt%

"B

$nitial ,etup

&he 9lugins ,DK

Plugins SDK Configuration


<o' that all the proper tools are in place, 'e )ust configure the 9lugins ,DK to #e a#le to deploy into your Liferay instance% .ou 'ill notice that the 9lu+ gins ,DK contains a file called build&"ro"erties% &his file contains the default set+ tings a#out the location of your Liferay installation and your deploy)ent folder% .ou can use this file as a reference, #ut you should not )odify it directly 2$n fact you 'ill see the )essage KD; <;& ED$& &:$, F$LEL at the top if you open it3% $n order to override the default settings, create a ne' file in the sa)e folder called build&45user&name6&"ro"erties, 'here -4user.name5 is your user $D on your )a+ chine% For e1a)ple, if your user na)e is Is)ith 2for John ,)ith3, you 'ould cre+ ate a file called build&)smith&"ro"erties% Edit this file and add the follo'ing line/
app.server.dir(the directory containing your application server

$n our case, a .server.dir should #e the a#solute path to your liferay! "ortal!#version$%tomcat!#tomcat!version$ directory% ,ave the file% .ou are no' ready to start using the 9lugins ,DK%

Structure of the SDK


Each folder in the 9lugins ,DK contains scripts for creating ne' plugins for that type% <e' plugins are placed in their o'n su#directory of the appropriate plugin directory% For instance, a ne' portlet called Kgreeting+portletL 'ould reside in liferay!"lu7ins!sdk!8%"ortlets%7reetin7!"ortlet% &he 9lugins ,DK can house all of your plugin proIects enterprise+'ide, or you can have separate 9lugins ,DK proIects for each plugin% For e1a)ple, if you have an internal $ntranet using Liferay 'ith so)e custo) portlets, you could (eep those portlets and the)es in their o'n 9lugins ,DK proIect in your source code repository% $f you also have an e1ternal instance of Liferay for your pu#lic $nternet 'e# site, you could have a separate 9lugins ,DK 'ith those proIects as 'ell% ;r you could further separate your proIects #y having a different 9lugins ,DK proIect for each portlet or the)e proIect% $t is also possi#le to use use the 9lugins ,DK as a si)ple cross+platfor) pro+ Iect generator% .ou can create a plugin proIect using the 9lugins ,DK and then copy the resulting proIect folder to your $DE of choice% &his )ethod reHuires so)e )anual )odification of the ant scripts, #ut it )a(es it possi#le to confor) to the strict standards so)e organi7ations have for their Java proIects%

,tructure of the ,DK

"A

3. PORTLET DEVELOPMENT

$n this chapter 'e 'ill create and deploy a si)ple portlet using the 9lugins ,DK% $t 'ill allo' a custo)i7ed greeting to #e saved in the portlet's preferences, and then display it 'henever the portlet is vie'ed% Finally 'e 'ill add friendly -6L )apping to the portlet to clean up its -6Ls% $n developing your o'n portlets you are free to use any fra)e'or( you prefer, such as ,truts, ,pring M=C, or J,F% For this portlet 'e 'ill use the Liferay M=C9ortlet fra)e'or( as it is si)ple, light'eight, and easy to understand% *dditionally, Liferay allo's for the consu)ing of 9:9 and 6u#y applications as portlets, so you do not need to #e a Java developer in order to ta(e advan tage of Liferay's #uilt+in features 2such as user )anage)ent, co))unities, page #uilding and content )anage)ent3% .ou can use the 9lugins ,DK to deploy your 9:9 or 6u#y ap+ plication as a portlet, and it 'ill run sea)lessly inside of Liferay% &here are plenty of e1a)ples of thisR to see the), chec( out the directory "lu7ins%trunk fro) Liferay's pu#lic ,u#version repository%

Creating a Portlet
Creating portlets 'ith the 9lugins ,DK is e1tre)ely si)ple% *s noted #efore, there is a "ortlets folder inside of the 9lugins ,DK folder% &his is 'here your portlet proIects 'ill reside% &o create a ne' portlet, first decide 'hat its na)e is going to #e% .ou need #oth a proIect na)e 2'ithout spaces3 and a display na)e 2'hich can have spaces3% Fhen you have decided on your portlet's na)e, you are ready to create the proIect% For the greeting portlet, the proIect na)e is K)y+greetingL, and the portlet title is KMy GreetingL% <avigate to the "ortlets directory in the ter)inal and enter the follo'+ ing co))and 2Linu1 and Mac ;, C3/
./create.sh my-greeting 6&y 7reeting6

;n Findo's enter the follo'ing instead/

9ortlet Develop)ent
create.bat my-greeting 6&y 7reeting6

.ou should get a ?-$LD ,-CCE,,F-L )essage fro) *nt, and there 'ill no' #e a ne' folder inside of the "ortlets folder in your 9lugins ,DK% &his folder is your ne' portlet proIect% &his is 'here you 'ill #e i)ple)enting your o'n func+ tionality% <otice that the 9lugins ,DK auto)atically appends K+portletL to the proIect na)e 'hen creating this folder% *lternatively, if you 'ill not #e using the 9lugins ,DK to house your portlet proIects, you can copy your ne'ly created portlet proIect into your $DE of choice and 'or( 'ith it there% $f you do this, you )ay need to )a(e sure the proIect ref+ erences so)e %Iar files fro) your Liferay installation, or you )ay get co)pile er+ rors% ,ince the ant scripts in the 9lugins ,DK do this for you auto)atically, you don't get these errors 'hen 'or(ing 'ith the 9lugins ,DK% &o resolve the dependencies for portlet proIects, see the class path entries in the build!common&9ml file in the 9lugins ,DK proIect% .ou 'ill #e a#le to deter)+ ine fro) the "lu7in&class"ath and "ortal&class"ath entries 'hich %Iar files are neces+ sary to #uild your ne'ly created portlet proIect% Tip: If you are using a source control system such as Subversion, CVS, Mercurial, Git, etc. this might be a good moment to do an initial check in of your changes. After building the plugin for deployment several additional files will be generated that should not be handled by the source control system.

Deploying the Portlet


Liferay provides a )echanis) called autodeploy that )a(es deploying port+ lets 2and any other plugin type3 a #ree7e% *ll you need to do is drop a F*6 file into a directory and the portal 'ill ta(e care of )a(ing any necessary changes specific to Liferay and then deploy it to the application server% &his 'ill #e the )ethod used throughout this guide% Tip: Liferay supports a wide variety of application servers. Many of them, such as Tomcat or Jboss, provide a simple way to deploy web applications by just copying a file into a folder and Liferay's autodeploy mechanism makes use of that possibility. You should be aware though that some application servers, such as Websphere or Weblogic require the use of specific tools to deploy web applications, so Liferay's autodeploy process won't work for them.

;pen a ter)inal 'indo' in your "ortlet s%my!7reetin7!"ortlet directory and enter this co))and/
ant deploy

.ou should get a ?-$LD ,-CCE,,F-L )essage, 'hich )eans that your port+ Creating a 9ortlet

9ortlet Develop)ent let is no' #eing deployed% $f you s'itch to the ter)inal 'indo' running Liferay, and 'ait for a fe' seconds, you should see the )essage K" portlet for )y+greet+ ing+portlet is availa#le for useL% $f not, so)ething is 'rong and you should dou#le+chec( your configuration% Go to your 'e# #ro'ser and log in to the portal as e1plained earlier% &hen hover over Add at the top of the page, and clic( on :ore% ,elect the *am"le cat+ egory, and then clic( Add ne1t to :y ;reetin7% .our portlet should appear in the page #elo'% Congratulations, you've Iust created your first portletP

Anatomy of a Portlet
* portlet proIect is )ade up at a )ini)u) of three co)ponents/ "% % 5% Java ,ource Configuration files Client+side files 2S%Isp, S%css, S%Is, graphics, etc%3

Fhen using Liferay's 9lugins ,DK these files are stored in a standard direct+ ory structure 'hich loo(s li(e the follo'ing/

/,%8"9'"-! &'/ build.xml /docroot/ /css/ /)s/ /:';-I!</ /src/ /not created by default0 liferay-display.xml liferay-plugin-package.properties liferay-portlet.xml portlet.xml web.xml icon.png view.)sp

&he portlet 'e Iust created is a fully functional portlet 'hich can #e de+ ployed to your Liferay instance% <e' portlets are configured #y default to use the M=C9ortlet fra)e'or(, a very light fra)e'or( that hides part of the co)ple1ity of portlets and )a(es the )ost co))on operations easier% M=C9ortlet uses separate J,9s for each page in the portlet% 9ortlets created in the ,DK are configured #y default to use the M=C9ortlet fra)e'or(, a very light fra)e'or( that hides part of the co)ple1ity of portlets and )a(es the )ost co))on operations easier% M=C9ortlet uses separate J,9s for each page in the portlet% M=C9ortlet uses #y default a J,9 'ith the )ode na)e for each of the registered portlet )odes% For e1a)ple edit%Isp for the edit )ode, help%Isp for the help )ode, etc% *nato)y of a 9ortlet 5

9ortlet Develop)ent &he 8ava Source is stored in the docroot%W+<!I- %src folder &he #on%iguration -iles are stored in the docroot%W+<!I- folder% &he stand+ ard J,6+ B> portlet configuration file "ortlet&9ml is here, as 'ell as three Liferay+ specific configuration files% &he Liferay+specific configuration files are co)+ pletely optional, #ut are i)portant if your portlets are going to #e deployed on a Liferay 9ortal server% liferay!dis"lay&9ml/ &his file descri#es 'hat category the portlet should ap+ pear under in the Add )enu in the doc(#ar 2the hori7ontal #ar that appear at the top of the page to all logged in users3% liferay!"ortlet&9ml/ &his file descri#es so)e optional Liferay+specific en+ hance)ents for J,6+ B> portlets that are installed on a Liferay 9ortal server% For e1a)ple, you can set 'hether a portlet is instancea#le, 'hich )eans that you can place )ore than one portlet instance on a page, and each one 'ill have its o'n separate data% 9lease see the D&D for this file for further details, as there are too )any settings to list here% &he D&D )ay #e found in the definitions folder in the Liferay source code% liferay!"lu7in!"acka7e&"ro"erties/ &his file descri#es the plugin to Liferay's hot deployer% ;ne of the things that can #e configured in this file is dependency %Iars% $f a portlet plugin has dependencies on particular %Iar files that already co)e 'ith Liferay, you can specify the) in this file and the hot deployer 'ill )odify the %'ar file on deploy)ent to copy those %Iars inside% &hat 'ay you don't have to include the %Iars yourself and the %'ar 'ill #e lighter% #lient Side -iles are the %Isp, %css, and Java,cript files that you 'rite to i)+ ple)ent your portlet's user interface% &hese files should go in the docroot folder so)e'here0either in the root of the folder or in a folder structure of their o'n% 6e)e)#er that 'ith portlets you are only dealing 'ith a portion of the :&ML docu)ent that is getting returned to the #ro'ser% *ny :&ML code you have in your client side files should #e free of glo#al tags such as =html> or =head>% *ddi+ tionally, all C,, classes and ele)ent $Ds )ust #e na)espaced to prevent conflicts 'ith other portlets% Liferay provides tools 2a tagli# and *9$ )ethods3 to generate the na)espace that you should use%

A Closer Look at the My Greeting Portlet


$f you are ne' to portlet develop)ent, this section 'ill ta(e a closer loo( at the configuration options of a portlet% docroot<2*1:I6-< ortlet.+!l Fhen using the 9lugins ,DK, the default content of the portlet descriptor is as follo's/
=portlet> =portlet-name>my-greeting=/portlet-name> =display-name>&y 7reeting=/display-name> =portlet-class>com.liferay.util.bridges.mvc.&?@,ortlet=/portletclass> =init-param>

*nato)y of a 9ortlet

9ortlet Develop)ent
=name>view-)sp=/name> =value>/view.)sp=/value> =/init-param> =expiration-cache>3=/expiration-cache> =supports> =mime-type>text/html=/mime-type> =/supports> =portlet-info> =title>&y 7reeting=/title> =short-title>&y 7reeting=/short-title> =keywords>&y 7reeting=/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>

:ere is a #asic su))ary of 'hat each of the ele)ents represents/ The portlet-name element contains the canonical name of the portlet. Each portlet name is unique within the portlet application (that is, within the portlet plugin). This is also referred within Liferay Portal as the portlet id The display-name type contains a short name that is intended to be displayed by tools. It is used by display-name elements. The display name need not be unique. The portlet-class element contains the fully qualified class name that will handle invocations to the portlet. The init-param element contains a name/value pair as an initialization param of the portlet. Expiration-cache defines expiration-based caching for this portlet. The parameter indicates the time in seconds after which the portlet output expires. -1 indicates that the output never expires.

portlet-name

display-name portlet-class init-param

expiration-cache

*nato)y of a 9ortlet

9ortlet Develop)ent The supports element contains the supported mime-type. Supports also indicates the portlet modes a portlet supports for a specific content type. All portlets must support the view mode. The concept of portlet modes is defined by the portlet specification. Modes are used to separate certain views of the portlet from others. What is special about portlet modes is that the portal knows about them and can provide generic ways to navigate between portlet modes (for example through links in the box surrounding the portlet when it is added to a page). For that reason they are useful for operations that are common to all or most portlets. The most common usage is to create an edit screen where each user can specify personal preferences for the portlet. Portlet-info defines portlet information.

supports

portlet-info

The security-role-ref element contains the declaration of a security role reference in the code of the web application. Spesecurity-role-ref cifically in Liferay, the role-name references which roles can access the portlet. docroot<2*1:I6-<li%era&: ortlet.+!l + $n addition to the standard portoptions, there are optional Liferay+specific enhance)ents for Java ,tandard portlets that are installed on a Liferay 9ortal server% ?y default, 9lugins ,DK sets the contents of this descriptor to the follo'ing/
let.xml =liferay-portlet-app> =portlet> =portlet-name>my-greeting=/portlet-name> =icon>/icon.png=/icon> =instanceable>false=/instanceable> =header-portlet-css>/css/main.css=/header-portlet-css> =footer-portlet-)avascript>/)s/main.)s=/footer-portlet)avascript> =css-class-wrapper>my-greeting-portlet=/css-class-wrapper> =/portlet> =role-mapper> =role-name>administrator=/role-name> =role-link> dministrator=/role-link> =/role-mapper> =role-mapper> =role-name>guest=/role-name> =role-link>7uest=/role-link> =/role-mapper> =role-mapper> =role-name>power-user=/role-name> =role-link>,ower Aser=/role-link> =/role-mapper> =role-mapper> =role-name>user=/role-name> =role-link>Aser=/role-link>

>

*nato)y of a 9ortlet

9ortlet Develop)ent
=/role-mapper> =/liferay-portlet-app>

:ere is a #asic su))ary of 'hat so)e of the ele)ents represents% portlet-name icon instanceable header-portlet-css footer-portlet-javascript The portlet-name element contains the canonical name of the portlet. This needs to be the same as the portlet-name given in portlet.xml Path to icon image for this portlet Indicates if multiple instances of this portlet can appear on the same page. The path to the .css file for this portlet to be included in the <head> of the page The path to the .js file for this portlet, to be included at the end of the page before </body>

&here are )any )ore ele)ents that you should #e a'are of for )ore ad+ vanced develop)ent% 9lease see the D&D for this file in the definitions folder in the Liferay source code for )ore infor)ation%

Writing the My Greeting Portlet


<o' that you are fa)iliar 'ith the structure of a portlet, it's ti)e to actually )a(e it do so)ething useful% ;ur portlet 'ill have t'o pages% view&)s" 'ill dis+ play the greeting and provide a lin( to the edit page% +dit&)s" 'ill sho' a for) 'ith a te1t field allo'ing the greeting to #e changed, along 'ith a lin( #ac( to the vie' page% M=C9ortlet class 'ill handle the rendering of our J,9s, so for this e1a)ple 'e 'on't have to 'rite a single Java class% First, 'e don't 'ant )ultiple greetings on the sa)e page, so 'e are going to )a(e the My Greeting portlet non+instancea#le% &o do this, edit liferay!"ortlet&9ml and change the value of the ele)ent instanceable fro) true to false so that it loo(s li(e this/
=instanceable>false=/instanceable>

<e1t, 'e 'ill create our J,9 te)plates% ,tart #y editing view&)s" and replacing its current contents 'ith the follo'ing/
=BC taglib uri(6http.//)ava.sun.com/portlet#1#36 prefix(6portlet6 B> =BC page import(6)avax.portlet.,ortlet,references6 B> =portlet.define%b)ects /> =B ,ortlet,references prefs ( render8eDuest.get,references/0E String greeting ( /String0prefs.get?alue/ 6greeting6, 6$elloF :elcome to our portal.60E B>

Friting the My Greeting 9ortlet

9ortlet Develop)ent
=p>=B( greeting B>=/p> =portlet.renderA89 var(6edit7reetingA896> =portlet.param name(6)sp,age6 value(6/edit.)sp6 /> =/portlet.renderA89> =p>=a href(6=B( edit7reetingA89 B>6>'dit greeting=/a>=/p>

<e1t, create edit&)s" in the sa)e directory as view&)s" 'ith the follo'ing con+ tent/
=BC taglib uri(6http.//)ava.sun.com/portlet#1#36 prefix(6portlet6 B> =BC taglib uri(6http.//liferay.com/tld/aui6 prefix(6aui6 B> =BC page import(6)avax.portlet.,ortlet,references6 B> =portlet.define%b)ects /> =B ,ortlet,references prefs ( render8eDuest.get,references/0E String greeting ( render8eDuest.get,arameter/6greeting60E if /greeting F( null0 4 prefs.set?alue/6greeting6, greeting0E prefs.store/0E B> =p>7reeting saved successfullyF=/p> =B 5 B> =B greeting ( /String0prefs.get?alue/ 6greeting6, 6$elloF :elcome to our portal.60E B> =portlet.renderA89 var(6edit7reetingA896> =portlet.param name(6)sp,age6 value(6/edit.)sp6 /> =/portlet.renderA89> =aui.form action(6=B( edit7reetingA89 B>6 method(6post6> =aui.input label(6greeting6 name(6greeting6 type(6text6 value(6=B( greeting B>6 /> =aui.button type(6submit6 /> =/aui.form> =portlet.renderA89 var(6view7reetingA896> =portlet.param name(6)sp,age6 value(6/view.)sp6 /> =/portlet.renderA89> =p>=a href(6=B( view7reetingA89 B>6>GlarrE ;ack=/a>=/p>

Friting the My Greeting 9ortlet

9ortlet Develop)ent Deploy the portlet again #y entering the co))and ant de lo& in your my! 7reetin7!"ortlet folder% Go #ac( to your 'e# #ro'ser and refresh the pageR you should no' #e a#le to use the portlet to save and display a custo) greeting% Tip: If your portlet deployed successfully, but you don't see any changes in your browser after refreshing the page, Tomcat may have failed to rebuild your JSPs. Simply delete the work folder in liferayportal-[version]/tomcat-[tomcat-version] and refresh the page again to force them to be rebuilt. &here are a fe' i)portant details to notice in this i)ple)entation% First, the lin(s #et'een pages are created using the =portlet.renderA89> tag, 'hich is defined #y the http.//)ava.sun.com/portlet#1#3 tag li#rary% &hese -6Ls have only one para)eter na)ed )s"Pa7e, 'hich is used #y M=C9ortlet to deter)ine 'hich J,9 to render for each reHuest% .ou )ust al'ays use tagli#s to generate -6Ls to your portlet% &his restriction e1ists #ecause the portlet does not o'n the 'hole page, only a frag)ent of it, so the -6L )ust al'ays go to the portal 'ho is responsi#le for rendering, not only your portlet #ut also any others that the user )ight put in the page% &he portal 'ill #e a#le to interpret the tagli# and create a -6L 'ith enough infor)ation to #e a#le to render the 'hole page% ,econd, notice that the for) in edit&)s" has the prefi1 aui, signifying that it is part of the *lloy -$ tag li#rary% *lloy greatly si)plifies the code reHuired to cre+ ate nice loo(ing and accessi#le for)s, #y providing tags that 'ill render #oth the la#el and the field at once% .ou can also use regular :&ML or any other tagli#s to create for)s #ased on your o'n preferences% *nother J,9 tag that you )ay have noticed is =portlet.define%b)ects/>% &he portlet specification defined this tag in order to #e a#le to insert into the J,9 a set of i)plicit varia#les that are useful for portlet developers such as render+ 6eHuest, portletConfig, portlet9references, etc% 9ne .ord o% .arning a#out the portlet 'e have Iust #uilt% For the purpose of )a(ing this e1a)ple as si)ple and easy to follo' as possi#le, 'e have cheated a little #it% &he portlet specification does not allo' to set preferences fro) a J,9, #ecause they are e1ecuted in 'hat is (no'n as the render state% &here are good reasons for this restriction, that are e1plained in the ne1t section%

Understanding the Two phases of Portlet Execution


;ne of the characteristics of portlet develop)ent that confuses )ost de+ velopers used to regular servlet develop)ent or 'ho are used to other environ+ )ents such as 9:9, 9ython or 6u#y is the need for t'o phases% &he good ne's is that once you get used to the) they #eco)e si)ple and useful% &he reason 'hy t'o phases are needed is #ecause a portlet does not o'n a 'hole :&ML page, it only generates a frag)ent of it% &he portal that holds the portlet is the one responsi#le for generating the page #y invo(ing one or several portlets and adding so)e additional :&ML around the)% -sually, 'hen the user interacts 'ith the page, for e1a)ple #y clic(ing a lin( or a #utton, she's doing it 'ithin a specific portlet% &he portal )ust for'ard the action perfor)ed #y the -nderstanding the &'o phases of 9ortlet E1ecution A

9ortlet Develop)ent user to that portlet and after that it )ust render the 'hole page, sho'ing the content of that portlet, 'hich )ay have changed, and also the content of the other portlets% For the other portlets in the page 'hich have not #een invo(ed #y the user, 'hat the portal does to get their content is to repeat the last invoca+ tion again 2since it assu)es it 'ill yield the sa)e result3% <o' i)agine this scenario/ 'e have a page 'ith t'o portlets, a navigation portlet and a shopping portlet% * user co)es to the page and does the follo'ing/ "% % Load the page Clic(s a #utton on the shopping portlet that auto)atically charges an a)ount on her credit card and starts a process to ship her the product she Iust #ought% *fter this operation the portal also in+ vo(es the navigation portlet 'ith its default vie'% Clic( a lin( in the navigation portlet 'hich causes the content of the portlet to change% *fter that the portal )ust also sho' the con+ tent of the shopping portlet, so it repeats the last action 2the one in 'hich the user clic(ed a #utton3, 'hich causes a ne' charge on the credit card and the start of a ne' shipping process%

5%

$ guess that #y no' you can tell that this is not right% ,ince the portal doesn't (no' 'hether the last operation on a portlet 'as an action or not, it 'ould have no option #ut to repeat it over and over to o#tain the content of the portlet again 2at least until the Credit Card reached its li)it3% Fortunately portals don't 'or( that 'ay% $n order to prevent situations li(e the one descri#ed a#ove, the portlet specification defines t'o phases for every reHuest of a portlet, to allo' the portal to differentiate when an action is bein7 "er! formed 2and should not #e repeated3 and when the content is bein7 "roduced 2rendered3/ Action hase/ &he action phase can only #e invo(ed for one port+ let at a ti)e and is usually the result of an user interaction 'ith the portlet% $n this phase the portlet can change its status, for in+ stance changing the user preferences of the portlet% $t is also re+ co))ended that any inserts and )odifications in the data#ase or operations that should not #e repeated are perfor)ed in this phase% /ender hase/ &he render phase is al'ays invo(ed for all portlets in the page after the action phase 2'hich )ay or not e1ist3% &his in+ cludes the portlet that also had e1ecuted its action phase% $t's i)+ portant to note that the order in 'hich the render phase of the portlets in a page gets e1ecutedis not guaranteed #y the portlet specification% Liferay has an e1tension to the specification through the ele)ent render!wei7ht in liferay+portlet%1)l% 9ortlets 'ith a higher render 'eight 'ill #e rendered #efore those 'ith a lo'er value%

$n our e1a)ple, so far 'e have used a portlet class called M=C9ortlet% &hat

5! -nderstanding the &'o phases of

9ortlet Develop)ent is all that the portlet if it only has a render phase% $n order to #e a#le to add cus+ to) code that 'ill #e e1ecuted in the action phase 2and thus 'ill not #e e1ecuted 'hen the portlet is sho'n again3 you need to create a su#class of M=C9ortlet or directly a su#class of Generic9ortlet if you don't 'ant to use the light'eight Liferay's fra)e'or(% ;ur e1a)ple a#ove could #e enhanced #y creating the follo'ing class/
package com.liferay.samplesE import )ava.io.I%'xceptionE import )avax.portlet. ction8eDuestE import )avax.portlet. ction8esponseE import )avax.portlet.,ortlet'xceptionE import )avax.portlet.,ortlet,referencesE import com.liferay.util.bridges.mvc.&?@,ortletE public class &y7reeting,ortlet extends &?@,ortlet 4 C%verride public void process ction/ ction8eDuest action8eDuest, ction8esponse action8esponse0 throws I%'xception, ,ortlet'xception 4 ,ortlet,references prefs ( action8eDuest.get,references/0E String greeting ( action8eDuest.get,arameter/6greeting60E if /greeting F( null0 4 prefs.set?alue/6greeting6, greeting0E prefs.store/0E 5 super.process ction/action8eDuest, action8esponse0E 5 5

&he file portlet%1)l also needs to #e changed so that it points to our ne' class/
=portlet> =portlet-name>my-greeting=/portlet-name> =display-name>&y 7reeting=/display-name> =portlet-class>com.liferay.samples.MyGreetingPortlet=/portletclass> =init-param> =name>view-)sp=/name> =value>/view.)sp=/value> =/init-param>

-nderstanding the &'o phases of 9ortlet E1ecution

5"

9ortlet Develop)ent
H

Finally, you 'ill need to do a )inor change in the edit&)s" file and change the -6L to 'hich the for) is sent to let the portal (no' that it should e1ecute the action phase% &his is the perfect )o)ent for you to (no' that there are three types of -6Ls that can #e generated #y a portlet/ renderU=L/ this is the type of -6L that 'e have used so far% $t in+ vo(es a portlet using only its render phase% actionU=L/ this type of -6L tells the portlet that it should e1ecute its action phase #efore rendering all the portlets in the page% resourceU=L/ this type of -6L can #e used to retrieve i)ages, CML, J,;< or any other type of resource% $t is often used to generate i)+ ages or other )edia types dyna)ically% $t is very useful also to )a(e *J*C reHuests to the server% &he (ey difference of this -6L type in co)parison to the other t'o is that the portlet has full con+ trol of the data that 'ill #e sent in response%

,o 'e )ust change the edit&)s" to use an action-6L #y using the J,9 tag of the sa)e na)e% Fe also re)ove the previous code that 'as saving the prefer+ ence/
=BC taglib uri(6http.//)ava.sun.com/portlet#1#36 prefix(6portlet6 B> =BC taglib uri(6http.//liferay.com/tld/aui6 prefix(6aui6 B> =BC page import(6com.liferay.portal.kernel.util.,aramAtil6 B> =BC page import(6com.liferay.portal.kernel.util.?alidator6 B> =BC page import(6)avax.portlet.,ortlet,references6 B> =portlet.define%b)ects /> =B ,ortlet,references prefs ( render8eDuest.get,references/0E String greeting ( /String0prefs.get?alue/ 6greeting6, 6$elloF :elcome to our portal.60E B> =portlet.actionURL var(6edit7reetingA896> =portlet.param name(6)sp,age6 value(6/edit.)sp6 /> =/portlet.actionURL> =aui.form action(6=B( edit7reetingA89 B>6 method(6post6> =aui.input label(6greeting6 name(6greeting6 type(6text6 value(6=B( greeting B>6 /> =aui.button type(6submit6 /> =/aui.form> =portlet.renderA89 var(6view7reetingA896>

5 -nderstanding the &'o phases of

9ortlet Develop)ent
=portlet.param name(6)sp,age6 value(6/view.)sp6 /> =/portlet.renderA89> =p>=a href(6=B( view7reetingA89 B>6>GlarrE ;ack=/a>=/p>

&ry deploying again the portlet after )a(ing these changes, everything should 'or( e1actly li(e #efore% Fell, al)ost% $f you have paid close attention you )ay have )issed so)e+ thing, no' the portlet is no longer sho'ing a )essage to the user to let hi) (no' that the preference has #een saved right after clic(ing the save #utton% $n order to i)ple)ent that 'e )ust have a 'ay to pass infor)ation fro) the action phase to the render phase, so that the J,9 can (no' that the preference has Iust #een saved and then sho' a )essage to the user%

Passing Information from the Action Phase to the Render Phase


&here are t'o 'ays to pass infor)ation fro) the action phase to the render phase% &he first one is through render para)eters% Fithin the i)ple)entation in the "rocessAction )ethod you can invo(e the set=enderParameter to add a ne' para)eter to the reHuest that the render phase 'ill #e a#le to read/
action8esponse.set8ender,arameter/6parameter-name6, 6value60E

Fro) the render phase 2in our case, the J,93, this value can #e read using the regular para)eter reading )ethod/
render8eDuest.get,arameter/6parameter-name60E

$t is i)portant to #e a'are that 'hen invo(ing an action -6L, the para)et + ers specified in the -6L 'ill only #e reada#le fro) the action phase 2that is the "rocessAction )ethod3% $n order to pass para)eter values to the render phase you )ust read the) fro) the action6eHuest and then invo(e the set=enderParameter )ethod for each para)eter needed% Tip: Liferay offers a convenient extension to the portlet specification through the MVCPortlet class to copy all action parameters directly as render parameters. You can achieve this just by setting the following init-param in your portlet.xml:
=init-param> =name>copy-reDuest-parameters=/name> =value>true=/value> =/init-param>

$ )entioned there 'as a second )ethod and in fact it is a #etter )ethod for 'hat 'e are trying to do in our e1a)ple% ;ne final thing you should (no' a#out

9assing $nfor)ation fro) the *ction 9hase to the 6ender 9hase

55

9ortlet Develop)ent render para)eters is that the portal re)e)#ers the) for all later e1ecutions of the portlet until the portlet is invo(ed again 'ith different para)eters% &hat is, if a user clic(s a lin( in our portlet and a render para)eter is set, and then the user continues #ro'sing through other portlets in the page, each ti)e the page is reloaded the portal 'ill render our portlet using the render para)eters that 'e set% $f 'e used render para)eters in our e1a)ple then the success )essage 'ill #e sho'n not only right after saving, #ut also every ti)e the portlet is rendered until the portlet is invo(ed again 'ithout that render para)eter% &he second )ethod of passing infor)ation fro) the action phase to the render phase is not uniHue to portlets so it )ight #e fa)iliar to you/ using the session% ?y using the session, your code can set an attri#ute in the action6eHuest that is then read fro) the J,9% $n our case the J,9 'ould also i))ediately re+ )ove the attri#ute fro) the session so that the )essage is only sho'n once% Liferay provides a helper class and tagli# to do this operation easily% $n the pro+ cess*ction you need to use the ,essionMessages class/
package com.liferay.samplesE import )ava.io.I%'xceptionE import )avax.portlet. ction8eDuestE import )avax.portlet. ction8esponseE import )avax.portlet.,ortlet'xceptionE import )avax.portlet.,ortlet,referencesE import com.liferay.portal.kernel.servlet.SessionMessages; import com.liferay.util.bridges.mvc.&?@,ortletE public class &y7reeting,ortlet extends &?@,ortlet 4 C%verride public void process ction/ ction8eDuest action8eDuest, ction8esponse action8esponse0 throws I%'xception, ,ortlet'xception 4 ,ortlet,references prefs ( action8eDuest.get,references/0E String greeting ( action8eDuest.get,arameter/6greeting60E if /greeting F( null0 4 prefs.set?alue/6greeting6, greeting0E prefs.store/0E 5 SessionMessages.add(actionRequest !success!";

super.process ction/action8eDuest, action8esponse0E 5 5

5E 9assing $nfor)ation fro) the *ction

9ortlet Develop)ent *lso, in the J,9 you 'ould need to add the liferay+ui/success J,9 tag as sho'n #elo' 2note that you also need to add the tagli# declaration at the top3/
=BC taglib uri(6http.//)ava.sun.com/portlet#1#36 prefix(6portlet6 B> =BC taglib uri(6http.//liferay.com/tld/aui6 prefix(6aui6 B> #$% tagli& uri'!(ttp)**liferay.com*tld*ui! prefi+'!liferay,ui! $=BC page import(6com.liferay.portal.kernel.util.,aramAtil6 B> =BC page import(6com.liferay.portal.kernel.util.?alidator6 B> =BC page import(6)avax.portlet.,ortlet,references6 B> =portlet.define%b)ects /> =B ,ortlet,references prefs ( render8eDuest.get,references/0E String greeting ( /String0prefs.get?alue/ 6greeting6, 6$elloF :elcome to our portal.60E B> #liferay,ui)success key'!success! message'!Greeting saved successfully.! *=portlet.actionA89 var(6edit7reetingA896> =portlet.param name(6)sp,age6 value(6/edit.)sp6 /> =/portlet.actionA89> =aui.form action(6=B( edit7reetingA89 B>6 method(6post6> =aui.input label(6greeting6 name(6greeting6 type(6text6 value(6=B( greeting B>6 /> =aui.button type(6submit6 /> =/aui.form> =portlet.renderA89 var(6view7reetingA896> =portlet.param name(6)sp,age6 value(6/view.)sp6 /> =/portlet.renderA89> =p>=a href(6=B( view7reetingA89 B>6>GlarrE ;ack=/a>=/p>

*fter this change, redeploy the portlet, go to the edit screen and save it% .ou should see a nice )essage that loo(s li(e this/

Illustration 0. >he sam"le ?:y ;reetin7s@ "ortlet showin7 a success messa7e

9assing $nfor)ation fro) the *ction 9hase to the 6ender 9hase

5G

9ortlet Develop)ent &here is also an eHuivalent util class for notifying errors% &his is co))only used after catching an e1ception in the "rocessAction% For e1a)ple%
try 4 prefs.set?alue/6greeting6, greeting0E prefs.store/0E 5 catch/'xception e0 4 Session'rrors.add/action8eDuest, 6error60E 5

tag/

*nd then the error, if it e1ists, is sho'n in the J,9 using the liferay+ui/error

=liferay-ui.error key(6error6 message(6Sorry, an error prevented saving your greeting6 />

Fhen the error occurs you should see so)ething li(e this in your portlet/

Illustration A. >he sam"le ?:y ;reetin7s@ "ortlet showin7 an error messa7e

&he first )essage is auto)atically added #y Liferay% &he second one is the one you entered in the J,9%

Developing a Portlet with Multiple Actions


,o far 'e have developed a portlet that has t'o different vie's, the default vie' and an edit vie'% *dding )ore vie's is easy and all you have to do to lin( to the) is to use the )s"Pa7e para)eter 'hen creating the -6L% ?ut 'e only have one action% :o' do 'e add another action, for e1a)ple for sending an e)ail to the userN .ou can have as )any actions as you 'ant in a portlet, each of the) 'ill need to #e i)ple)ented as a )ethod that receives t'o para)eters, an *ction6e+ Huest and an *ction6esponse% &he na)e of the )ethod can #e 'hatever you 'ant since you 'ill #e referring to it 'hen creating the -6L% Let's re'rite the e1a)ple fro) the previous section to use custo) na)es for the )ethods of the action to set the greeting and add a second action%
public class &y7reeting,ortlet extends &?@,ortlet 4

5> Developing a 9ortlet 'ith Multiple

9ortlet Develop)ent
public void setGreeting/ ction8eDuest action8eDuest, ction8esponse action8esponse0 throws I%'xception, ,ortlet'xception 4 ,ortlet,references prefs ( action8eDuest.get,references/0E String greeting ( action8eDuest.get,arameter/6greeting60E if /greeting F( null0 4 try 4 prefs.set?alue/6greeting6, greeting0E prefs.store/0E Session&essages.add/action8eDuest, 6success60E 5 catch/'xception e0 4 Session'rrors.add/action8eDuest, 6error60E 5 5 5 public void send/mail/ ction8eDuest action8eDuest, ction8esponse action8esponse0 throws I%'xception, ,ortlet'xception 4 // 5 5 dd code here to send an email

<ote ho' 'e no longer need to invo(e the process*ction )ethod of the su + per class, #ecause 'e are not overriding it% &his change of na)e also reHuires a si)ple change in the -6L, to specify the na)e of the )ethod that should #e invo(ed to e1ecute the action% $n the edit%Isp edit the action-6L so that it loo(s li(e this/
=portlet.actionA89 var(6edit7reetingA896 name(6set7reeting6> =portlet.param name(6)sp,age6 value(6/edit.)sp6 /> =/portlet.actionA89>

&hat's it, no' you (no' all the #asics of portlets and are ready to use your Java (no'ledge to #uild portlets that get integrated in Liferay% &he ne1t section e1plains an e1tension provided #y Liferay to the portlet specification to provide pretty -6Ls to your portlets that you can use if desired%

Optional: Adding Friendly URL Mapping to the Portlet


.ou 'ill notice that 'hen you clic( the +dit 7reetin7 lin(, you are ta(en to a page 'ith a -6L si)ilar to this/

;ptional/ *dding Friendly -6L Mapping to the 9ortlet

5@

9ortlet Develop)ent
http.//localhost.+3+3/web/guest/homeI p#p#id(mygreeting#: 8#mygreetingportletGp#p#lifecycle(3Gp#p#state(norma lGp#p#mode(viewGp#p#col#id(column*G#mygreeting#: 8#mygreetingportlet#)sp,age(B1<edit.)sp

$n Liferay > there is a ne' feature that reHuires )ini)al 'or( to change this into/
http.//localhost.+3+3/web/guest/home/-/my-greeting/edit

&his feature, (no'n as friendly -6L )apping, ta(es unnecessary para)eters out of the -6L and allo's you to place the i)portant para)eters in the -6L path rather than the Huery string% &o add this functionality, first edit liferay!"ort! let&9ml and add the follo'ing lines directly after T4iconM and #efore Tinstance+ a#leM% ?e sure to re)ove the line #rea(s and the #ac(slashesP
=friendly-url-mapper-class>com.liferay.portal.kernel.portlet.2efault\ <riendlyA89&apper=/friendly-url-mapper-class> =friendly-url-mapping>my-greeting=/friendly-url-mapping> =friendly-url-routes>com/sample/mygreeting/portlet/my-greetingfriendly-url\ -routes.xml=/friendly-url-routes>

<e1t, create the file 2note the line #rea(3/


my-greeting-portlet/docroot/WEBINF/src/com/sample/mygreeting/portlet/my\ -greeting-friendly-url-routes.xml

Create ne' directories as necessary% 9lace the follo'ing content into the ne' file/
=Ixml version(6*.36I> =F2%@"J,' routes ,A;9I@ 6-//9iferay//2"2 <riendly A89 8outes K.3.3//'!6 6http.//www.liferay.com/dtd/liferay-friendly-url-routes#K#3#3.dtd6> =routes> =route> =pattern>/4)sp,age!ame5=/pattern> =generated-parameter name(6)sp,age6>/ 4)sp,age!ame5.)sp=/generated-parameter> =/route> =/routes>

6edeploy your portlet, refresh the page, and try clic(ing either of the lin(s again% <otice ho' )uch shorter and )ore user+friendly the -6L is, 'ithout even having to )odify the J,9s% For )ore infor)ation on friendly -6L )apping, you can chec( full discussion of this topic in Liferay in Action%

5B ;ptional/ *dding Friendly -6L Mapping

4. CREATING LIFERAY THEMES

&he)es are hot deploya#le plugins 'hich can co)pletely transfor) the loo( and feel of the portal% &he)e creators can )a(e the)es to provide an interface that is uniHue to the site that the portal 'ill serve% &he)es )a(e it possi#le to change the user interface so co)pletely that it 'ould #e difficult or i)possi#le to tell that the site is running on Liferay% Liferay provides a 'ell organi7ed, )odular structure to its the)es% &his allo's the the)e developer to #e a#le to Huic(ly )odify everything fro) the #order around a portlet 'indo' to every o#Iect on the page, #ecause all of the o#+ Iects are easy to find% *dditionally, the)e developers do not have to custo)i7e every aspect of their the)es% * the)e can inherit the styling, i)ages, and te)plates fro) any of the #uilt in the)es, overriding the) only 'here necessary% &his allo's the)es to #e s)aller and less cluttered 'ith e1traneous data that already e1ists in the default the)e 2such as graphics for e)oticons for the )essage #oards portlet3%

Introduction
Liferay's the)es are designed in such 'ay that they can #e very easy to create% .ou can start #y )a(ing changes in C,, files and as your custo)i7ation reHuire)ents gro' you can also )a(e changes to the :&ML that controls the page design% ,o)e of the technologies that you )ay need to (no' in order to )a(e the #est use of the)es are/ C,,/ $f desired you can create a 'hole ne' the)e Iust #y changing a C,, file% =elocity/ a si)ple yet po'erful tool to create te)plates% .ou 'ill need to use it in order to custo)i7e the :&ML generated #y the the)e% Java,cript/ can #e used to add special #ehaviors% CML/ each the)e has a configuration file 'ritten in CML% .ou 'ill use this file to specify so)e settings of the the)e%

Creating Liferay &he)es &o follo' the e1a)ples of this guide you 'ill also need so)e fa)iliarity 'ith using the co))and line% *lternatively you can use the Liferay $DE and use its )enus instead of the co))ands used in the te1t% ?ut let's finish the introduction and get started 'ith our first the)e%

Creating a Theme
&he process for creating a ne' the)e is nearly identical to the one for )a(+ ing a portlet% .ou 'ill need #oth a proIect na)e 2'ithout spaces3 and a display na)e 2'hich can have spaces3% For e1a)ple, the proIect na)e could #e Kdeep+ #lueL, and the the)e title KDeep ?lueL% $n the ter)inal, navigate to the themes directory in the 9lugins ,DK and enter the follo'ing co))and 2Linu1 and Mac ;, C3/
./create.sh deep-blue 62eep ;lue6

;n Findo's enter the follo'ing instead/


create.bat deep-blue 62eep ;lue6

&his co))and 'ill create a #lan( the)e in your themes folder% <otice that the 9lugins ,DK auto)atically appends K+the)eL to the proIect na)e 'hen cre+ ating this folder%

Deploying the Theme


;pen a ter)inal 'indo' in your themes%dee"!blue!theme directory and enter this co))and/
ant deploy

.ou should get a ?-$LD ,-CCE,,F-L )essage, 'hich )eans that your the)e is no' #eing deployed% $f you s'itch to the ter)inal 'indo' running Liferay, and 'ait for a fe' seconds, you should see the )essage K" the)e for deep+#lue+the)e is availa#le for useL% Go to your 'e# #ro'ser and login to the portal as e1plained earlier% &hen hover over 4anage at the top of the page, and clic( on Pa7e% Directly under+ neath the 'ords 4anage 9ages select the Look and eel ta#% ,i)ply clic( on your the)e to activate it%

Anatomy of a Theme
Custo) the)es are #ased on differences fro) one of several #uilt+in Liferay the)es% &he structure of a the)e is designed to separate different types of resources into easily accessi#le folders% &he full structure of the deep #lue the)e is sho'n #elo'/
/deep-blue-theme/ /docroot/ /:';-I!</

E!

*nato)y of a &he)e

Creating Liferay &he)es


liferay-plugin-package.properties /#diffs/ /subfolders not created by default0 /css/ /images/ /)s/ /templates/ /css/ application.css base.css custom.css dockbar.css extras.css forms.css layout.css main.css navigation.css portlet.css /images/ /many directories0 /)s/ main.)s /templates/ init#custom.vm navigation.vm portal#normal.vm portal#pop#up.vm portlet.vm

.ou 'ill notice that there is a #diffs folder inside the docroot directory of your the)eR this is 'here you 'ill place your the)e code% .ou only need to cus+ to)i7e the parts of your the)e that 'ill differ fro) the parent the)e% &o do this, you )irror the directory structure of the parent the)e inside of the #diffs folder, placing only the folders and files you need to custo)i7e there% .ou 'ill also notice that there are several other folders inside docrootR these 'ere copied over fro) the parent the)e in your Liferay #undle 'hen you de+ ployed your the)e% .ou should use these files as the #asis for your )odifica+ tions% For e1a)ple, to custo)i7e the navigation, you 'ould copy navigation.vm fro) deep-blue-theme/docroot/templates/navigation.vm into deep-bluetheme/docroot/#diffs/templates folder 2you )ay have to create this folder first3% .ou can then open this file and custo)i7e it to your li(ing% For custo) styles, create a folder na)ed css inside your #diffs folder and place a single file there called custom.css% &his is 'here you 'ould put all of your ne' styles and all of your overrides of the styles in the parent the)e% @ustom.css is loaded last, and so styles in this file are a#le to override any styles in the parent the)e% ?est practice reco))ends that you )a(e all your custo) the)es using only the custom.css file, and that you not override any of the te)plates unless a#so+ lutely necessary% &his 'ill )a(e future upgrades far easier, as you 'on't have to *nato)y of a &he)e E"

Creating Liferay &he)es )anually )odify your te)plates to add support for ne' Liferay features% Fhenever you )a(e )odifications to your the)e, redeploy it #y opening a ter)inal in themes/deep-blue-theme and entering the co))and ant de lo&% Fait a fe' seconds until the the)e deploys, and then refresh your #ro'ser to see your changes% Tip: If you wish to see changes even more quickly, it is also possible to modify you theme directly in your Liferay bundle. In our example, custom.css is located in liferay-portal-[version]/tomcat6.0.26/webapps/deep-blue-theme/css. However, for modifications made here to appear in your browser as soon as you refresh the page, you must enable Liferay Developer Mode. See the Liferay wiki for more information. Also make sure that you copy any changes you make back into your _diffs folder, or they will be overwritten when you redeploy your theme.

Thumbnails
.ou 'ill notice that in the Look and eel settings the Classic the)e has a thu)#nail previe' of 'hat it loo(s li(e, 'hile our the)e has only a #ro(en i)+ age% &o correct this, ta(e a screenshot of your the)e and save it in #diffs/images 'ith the na)e thumbnail.png% $t )ust have the e1act si7e of "G! pi1els 'ide #y " ! pi1els high% .ou should also save a larger version in the sa)e directory 'ith the na)e screenshot.png% $ts si7e )ust #e e1actly "!B! pi1els 'ide #y B>E pi1els high% *fter redeploying your the)e, it 'ill have a thu)#nail previe' Iust li(e the Classic the)e%

JavaScript
Liferay no' includes its o'n Java,cript li#rary called *lloy, 'hich is an e1+ tension to .ahoo's .-$5 fra)e'or(% Developers can ta(e advantage of the full po'er of either of these fra)e'or(s in their the)es% $nside of the main.)s file, you 'ill find definitions for three Java,cript call#ac(s/
AI/0.ready/ function/0 4 5 0E 9iferay.,ortlet.ready/ /L "his function gets loaded after each and every portlet on the page. portletId. the current portletMs id node. the L/ lloy !ode ob)ect of the current portlet

Java,cript

Creating Liferay &he)es


function/portletId, node0 4 5 0E 9iferay.on/ Mall,ortlets8eadyM, /L "his function gets loaded when everything, including the portlets, is on the page. L/ function/0 4 5 0E

A?I@A.read&@%nAB

&his call#ac( is e1ecuted as soon as the :&ML in the page has finished load+ ing 2)inus any portlets loaded via aIa13% $i%era&.Portlet.read&@%nAB E1ecuted after each portlet on the page has loaded% &he call#ac( receives t'o para)eters/ "ortletId and node% portletId is the id of the portlet that 'as Iust loaded% node is the *lloy <ode o#Iect of the sa)e portlet% $i%era&.on@3allPortlets/ead&37 %nAB E1ecuted after everything0including *J*C portlets0has finished loading%

Settings
Each the)e can define settings to )a(e it configura#le% &hese settings are defined in a file na)ed liferay-look-and-feel.xml inside :';-I!<% &his file does not e1ist #y default, so you should no' create it 'ith the follo'ing content/
=Ixml version(6*.36I> =F2%@"J,' look-and-feel ,A;9I@ 6-//9iferay//2"2 9ook and <eel K.3.3//'!6 6http.//www.liferay.com/dtd/liferay-look-andfeel#K#3#3.dtd6> =look-and-feel> =compatibility> =version>K.3.3N=/version> =/compatibility> =theme id(6deep-blue6 name(62eep ;lue6> =settings> =setting key(6my-setting6 value(6my-value6 /> =/settings> =/theme> =/look-and-feel>

,ettings

E5

Creating Liferay &he)es .ou can define additional settings #y adding )ore TsettingM ele)ents% &hese settings can #e accessed in the the)e te)plates using the follo'ing code/
-theme.getSetting/6my-setting60

For e1a)ple, say 'e need to create t'o the)es that are e1actly the sa)e e1+ cept for so)e changes in the header% ;ne of the the)es has )ore details 'hile the other is s)aller 2and ta(es less screen real estate3% $nstead of creating t'o different the)es, 'e are going to create only one and use a setting to choose 'hich header 'e 'ant% $n the portal#normal.vm te)plate 'e could 'rite/
Oif /-theme.getSetting/6header-type60 (( 6detailed60 Oparse /6-full#templates#path/header#detailed.vm60 Oelse Oparse /6-full#templates#path/header#brief.vm60 Oend

&hen 'hen 'e 'rite the liferay-look-and-feel.xml, 'e 'rite t'o different entries that refer to the sa)e the)e #ut have a different value for the head+ er+type setting/
=theme id(6deep-blue6 name(62eep ;lue6> =settings> #setting key'!(eader,type! value'!detailed! *=/settings> =/theme> =theme id(6deep-blue-mini6 name(62eep ;lue &ini6> =settings> #setting key'!(eader,type! value'!&rief! *=/settings> =/theme>

Color Schemes
Color sche)es are specified using a C,, class na)e, 'ith 'hich you can not only change colors, #ut also choose different #ac(ground i)ages, different #or+ der colors, and so on% $n your liferay-look-and-feel.xml, you can define color sche)es li(e so/
=theme id(6deep-blue6 name(62eep ;lue6> =settings> =setting key(6my-setting6 value(6my-value6 /> =/settings> =color-scheme id(63*6 name(62ay6> =css-class>day=/css-class> =color-scheme-images-path>-4images-path5/color#schemes/-4cssclass5=/color-scheme-images-path> =/color-scheme> =color-scheme id(6316 name(6!ight6> =css-class>night=/css-class>

EE

Color ,che)es

Creating Liferay &he)es


=/color-scheme> =/theme>

$nside of your #diffs/css folder, create a folder called color#schemes% $nside of that folder, place a .css file for each of your color sche)es% $n the case a#ove, 'e 'ould could either have Iust one called night.css and let the default styling handle the first color sche)e, or you could have #oth day.css and night.css% *ssu)ing you follo' the second route, place the follo'ing lines at the #ot+ to) of your custom.css file/
Cimport url/color#schemes/day.css0E Cimport url/color#schemes/night.css0E

&he color sche)e C,, class is placed on the T#odyM ele)ent, so you can use it to identify you styling% $n day.css you 'ould prefi1 all of your C,, styles li(e this/
body.day 4 background-color. OddfE 5 .day a 4 color. OKKaE 5

*nd in night.css you 'ould prefi1 all of your C,, styles li(e this/
body.night 4 background-color. OPPQE color. OQQQE 5 .night a 4 color. ObbdE 5

.ou can also create separate thu)#nail i)ages for each of your color sche)es% &he =color-scheme-images-path> ele)ent tells Liferay 'here to loo( for these i)ages 2note that you only have to place this ele)ent in one of the col+ or sche)es for it to affect #oth3% For our e1a)ple, create the folders #diffs/images/color#schemes/day and #diffs/images/color#schemes/night% $n each of these folders place a thumbnail.png and screenshot.png file 'ith the sa)e si7es as #efore%

Portal Predefined Settings


&he portal defines so)e settings that allo' the the)e to deter)ine certain #ehaviors% ,o far there are only t'o predefined settings #ut this nu)#er )ay gro' in the future% &hese settings can #e )odified fro) liferay-look-andfeel.xml% ortlet:setu :sho.:borders:de%ault $f set to false, the portal 'ill turn off #orders #y default for all the portlets% &he default is true% E1a)ple/
=settings> =setting key(6portlet-setup-show-borders-default6 value(6false6 /> =/settings>

&his default #ehavior can #e overridden for individual portlets using/ U liferay-portlet.xml

9ortal 9redefined ,ettings

EG

Creating Liferay &he)es U 9ortlet C,, popup setting bullet:st&le:o tions &his setting is used #y the -avi7ation portlet to deter)ine the C,, class na)e of the list of pages% &he value )ust #e a co))a separated list of valid #ul+ let styles to #e used% E1a)ple/
=settings> =setting key(6bullet-style-options6 value(6classic,modern,tablemenu6 /> =/settings>

&he #ullet style can #e changed #y the user in the -avi7ation portlet config+ uration% &he chosen style 'ill #e applied as a C,, class on the TdivM containing the navigation% &his class 'ill #e na)ed in the follo'ing pattern/
.nav-menu-style-4;A99'"#S"J9'#%,"I%!5 4 ... @SS selectors ... 5

:ere is an e1a)ple of the :&ML code that you 'ould need to add style through C,, code% $n this case the #ullet style option is !odern/
=div class(6nav-menu nav-menu-style-modern6> =ul class(6breadcrumbs lfr-component6> ... =/ul> =/div>

-sing C,, and4or so)e uno#trusive Javascript it's possi#le to i)ple)ent any type of )enu%

Theme inheritance
?y default the)es are #ased on the ;st&led the)e, 'hich provides only #asic styling of portlets% $f you open the build.xml file in your the)e's directory, you 'ill see the follo'ing/
=pro)ect name(6theme6 basedir(6.6 default(6deploy6> =import file(6../build-common-theme.xml6 /> =property name(6theme.parent6 value(6#styled6 /> =/pro)ect>

&he theme.parent property deter)ines 'hich #uilt+in the)e your the)e 'ill inherit fro)% $n addition to the ;st&led the)e, you )ay also choose to in+ herit fro) the ;unst&led the)e, 'hich contains no styling 'hatsoever% &his in+ volves )ore 'or(, #ut in e1change you get full fle1i#ility to design your o'n C,, files fro) scratch% .ou can also use the default Liferay the)e, called classic, as the parent of your the)es% -sing this approach allo's you to start 'ith a loo( and feel that already 'or(s and get nice results Huic(ly% &he dra'#ac( is that since there is so )uch done already for you, there 'on't #e as )uch fle1i#ility to #uild the de+ E> &he)e inheritance

Creating Liferay &he)es sired design% $t's a co)pro)ise #et'een creating a the)e as Huic(ly as possi#le versus having full control of the result% $t's your choice%

&he)e inheritance

E@

5. HOOKS

Liferay :oo(s are the ne'est type of plugin 'hich Liferay 9ortal supports% &hey 'ere introduced late in the develop)ent cycle for Liferay 9ortal G%"%1, and are no' the preferred 'ay to custo)i7e Liferay's core features% *s 'ith portlets, layout te)+ plates, and the)es, they are created using the 9lugins ,DK% :oo(s can fill a 'ide variety of the co))on needs for overriding Liferay core functionality% Fhenever possi#le, hoo(s should #e used in place of E1t plugins, as they are hot+deploya#le and )ore for'ard co)pati#le% ,o)e co))on scenarios 'hich reHuire the use of a hoo( are the need to perfor) custo) actions on portal startup or user login, over'rite or e1tend portal J,9s, )odify portal properties, or re+ place a portal service 'ith your o'n i)ple)entation%

Creating a Hook
:oo(s are stored 'ithin the hooks directory of the plugins directory% <avigate to this directory in ter)inal and enter the follo'ing co))and to create a ne' hoo( 2Linu1 and Mac ;, C3/
./create.sh example 6'xample6

;n Findo's enter the follo'ing instead/


create.bat example 6'xample6

.ou should get a ?-$LD ,-CCE,,F-L )essage fro) *nt, and there 'ill no' #e a ne' folder inside of the hooks folder in your 9lugins ,DK% <otice that the 9lugins ,DK auto)atically appends K+hoo(L to the proIect na)e 'hen creating this folder%

Deploying the Hook


;pen a ter)inal 'indo' in your hooks%e9am"le!hook directory and enter this co)+ )and/

:oo(s
ant deploy

.ou should get a ?-$LD ,-CCE,,F-L )essage, 'hich )eans that your hoo( is no' #eing deployed% $f you s'itch to the ter)inal 'indo' running Liferay, and 'ait for a fe' seconds, you should see the )essage K:oo( for e1a)ple+hoo( is availa#le for use%L :o'ever, unli(e portlets or the)es, your ne' hoo( doesn't actually do anything yet%

Overriding a JSP
;ne of the si)plest tas(s a hoo( can perfor) is replacing a portal J,9% $n this e1a)ple 'e 'ill )odify the &er)s of -se page% First, create the directory hooks/example-hook/docroot/&'" -I!</custom#)sps% <e1t, edit hooks/example-hook/docroot/:';-I!</liferay-hook.xml, and add the follo'ing #et'een =hook>=/hook>/
=custom-)sp-dir>/&'" -I!</custom#)sps=/custom-)sp-dir>

<o', any J,9 you place inside the custom()s"s directory 'ill replace its ori+ ginal inside your Liferay instance 'hen your hoo( is deployed% &he directory structure inside this folder )ust )irror the one 'ithin liferay!"ortal! #version$%tomcat!8&B&A8%weba""s%=22> % &o override the &er)s of -se, copy liferay! "ortal!#version$%tomcat!8&B&A8%weba""s%=22>%html%"ortal%terms(of(use&)s" to
hooks/example-hook/docroot/&'" -I!</custom#)sps/html/portal/terms#of#use.)sp% .ou

'ill have to create all the inter+

vening directories first% <e1t, open your copy of the terms#of#use.)sp and )a(e a fe' changes% De+ ploy your hoo( and 'ait until it is deployed successfully% &hen, create a ne' user and try to log in% Fhen you get to the &er)s of -se page, you 'ill see your ver+ sion instead of the default% 9lease note that this is not the reco))ended 'ay of changing the &er)s of -se, it is si)ply a convenient e1a)ple% .ou can actually replace the &er)s of -se 'ith 'e# content #y setting t'o properties in portalext.properties% * hoo( is not necessary% the liferay-portal-RversionS/tomcatdirectory you 'ill see that there are no' t'o ter)s of use files, one called terms#of#use.)sp and another called terms#of#use.portal.)sp% terms#of#use.)sp is the version fro) your hoo(, 'hile terms#of#use.portal.)sp is the original% $f you no' undeploy your hoo( #y deleting its directory in webapps, you 'ill see that your replace)ent J,9 is re+ )oved and the .portal.)sp file is rena)ed again to ta(e its place% $n this )an+ ner, you can override any J,9 in the Liferay core, 'hile also #eing a#le to revert your changes #y undeploying your hoo(% <ote ho'ever that it is not possi#le to override the sa)e J,9 fro) )ultiple hoo(s, as Liferay 'ill not (no' 'hich ver+ sion to use%
K.3.1K/webapps/8%%"/html/portal

$f

you

loo(

inside

Customizing JSPs without overriding the original


&he dra'#ac( of overridding a J,9 is that if the original changes 2for e1+ a)ple to fi1 a #ug3 then you have to also change your custo)i7ed file in order to #enefit fro) the original change% G! ;verriding a J,9

:oo(s $f you 'ish to avoid this dra'#ac( and )a(e your J,9 )odifications even less invasive, it is possi#le to render the original J,9 into a string, and then )odify it dyna)ically after'ards% &his )a(es it possi#le to change )inor ele+ )ents of a J,9, such as adding a ne' heading or #utton, 'ithout needing to 'orry )odifying your hoo( every ti)e you upgrade Liferay% :ere is an e1a)ple that custo)i7es the search portlet to re)ove the a#ility to a search provider in the #ro'ser/
=liferay-util.buffer var(6html6> /> =liferay-util.include page(6/html/portlet/search/search.portal.)sp6

=/liferay-util.buffer> =B int x ( html.index%f/6=div class(\6add-search-provider\6>60E int y ( html.index%f/6=/div>6, x0E if /x F( -*0 4 html ( StringAtil.remove/html, html.substring/x, y N K0, String,ool.;9 !T0E 5 B> =B( html B>

,ince this techniHue involves ,tring )anipulation it is )ainly useful 'hen the a)ount of changes desired are s)all%

Performing a Custom Action


*nother co))on use of hoo(s is to perfor) custo) actions on certain co)+ )on portal events, such as user log in or syste) startup% &he actions that are perfor)ed on each of these events are defined in portal.properties, 'hich )eans that in order to create a custo) action 'e 'ill also need to e1tend this file% Fortunately, this is e1tre)ely easy using a hoo(% First, create the directory example-hook/docroot/:';I!</src/com/sample/hook, and create the file 9ogin ction.)ava inside it 'ith the follo'ing content/
package com.sample.hookE import com.liferay.portal.kernel.events. ctionE import )avax.servlet.http.$ttpServlet8eDuestE import )avax.servlet.http.$ttpServlet8esponseE public class 9ogin ction extends ction 4

public void run/$ttpServlet8eDuest reD, $ttpServlet8esponse res0 4 System.out.println/6OO &y custom login action60E 5 5

9erfor)ing a Custo) *ction

G"

:oo(s <e1t, create the file portal.properties I!</src 'ith the follo'ing content/ inside
example-hook/docroot/:';-

login.events.pre(com.sample.hook.9ogin ction

Finally, edit liferay-hook.xml inside example-hook/docroot/:';-I!< and add the follo'ing line a#ove =custom-)sp-dir>/
=portal-properties>portal.properties=/portal-properties>

Deploy your hoo( again and 'ait for it to co)plete% &hen log out and #ac( in, and you should see our custo) )essage in the ter)inal 'indo' running Liferay% &here are several other events that you can define custo) actions for using hoo(s% ,o)e of these actions )ust e1tend fro) com.liferay.portal.kernel.events. ction, 'hile others )ust e1tend com.liferay.portal.struts.Simple ction% For )ore infor)ation on these events, see the portal.properties configuration file for your version of Liferay in/ http/44'''%liferay%co)4co)+ )unity4'i(i4+4'i(i4Main49ortalV9roperties

Extending and Overriding portal.properties


$n our hoo(, 'e )odified the login.events.pre portal property% ,ince this property accepts a list of values, our value 'as appended to the e1isting values% $t is safe to )odify these portal properties fro) )ultiple hoo(s, and they 'ill not interfere 'ith one another% ,o)e portal properties only accept a single value, such as the terms.of.use.reDuired property, 'hich can #e either true or %alse% .ou should only )odify these properties fro) one hoo(, other'ise Liferay 'ill not (no' 'hich value to use% .ou can deter)ine 'hich type a particular prop+ erty is #y loo(ing in portal.properties% <ot all portal properties can #e overridden in a hoo(% * co)plete list of the availa#le properties can #e found in the D&D for liferay-hook.xml in the definitions folder of the Liferay source code% $n addition to defining custo) actions, hoo(s can also override portal properties to define )odel listeners, validators, generators, and content saniti7ers%

Overriding a Portal Service


*ll of the functionality provided #y Liferay is encapsulated #ehind a layer of services that is accessed fro) the frontend layer 2the portlets3% ;ne of the #ene+ fits of this architecture is that it is possi#le to change ho' a core portlet of Liferay #ehaves 'ithout changing the portlet itself, custo)i7ing the #ac(end services that it uses% &his section e1plains ho' to do that fro) a hoo( plugin% Liferay auto)atically generates du))y 'rapper classes for all of its ser+ vices, for e1a)ple Aser9ocalService:rapper is created as a 'rapper of the Aser9ocalService that is used to add, re)ove and retrieve user accounts% &o )odify the functionality of Aser9ocalService fro) our hoo(, all 'e have to do is create a class that e1tends fro) Aser9ocalService:rapper, override so)e of its )eth+ ods, and then instruct Liferay to use our class instead of the original%

;verriding a 9ortal ,ervice

:oo(s First, inside example-hook/docroot/:';-I!</src/com/sample/hook create a ne' file called &yAser9ocalServiceImpl.)ava 'ith the follo'ing content/
package com.sample.hookE import com.liferay.portal.kernel.exception.,ortal'xceptionE import com.liferay.portal.kernel.exception.System'xceptionE import com.liferay.portal.model.AserE import com.liferay.portal.service.Aser9ocalServiceE import com.liferay.portal.service.Aser9ocalService:rapperE public class &yAser9ocalServiceImpl extends Aser9ocalService:rapper 4 public &yAser9ocalServiceImpl/Aser9ocalService user9ocalService0 4 super/user9ocalService0E 5 public Aser getAser;yId/long userId0 throws ,ortal'xception, System'xception 4 System.out.println/ 6OO &yAser9ocalServiceImpl.getAser;yId/6 N userId N 6060E return super.getAser;yId/userId0E 5 5

Tip: Note that the wrapper class (MyUserLocalServiceImpl in this example) will be loaded in the hook's class loader. That means that it will have access to any other class included within the same WAR file, but it won't have access to internal classes of Liferay.

<e1t, edit liferay-hook.xml inside the follo'ing after =/custom-)sp-dir>/


=service>

example-hook/docroot/:';-I!<

and add

=service-type>com.liferay.portal.service.Aser9ocalService=/servicetype> =service-impl>com.sample.hook.&yAser9ocalServiceImpl=/service-impl> =/service>

6edeploy your hoo(, then refresh your #ro'ser% $n the ter)inal 'indo' containing Liferay you should see the )essages printed #y our hoo(% :ere are so)e other services of Liferay that you )ay need to e1tend to )eet advanced reHuire)ents/ ;rgani7ationLocal,ervice/ add, delete and retrieve organi7ations% *lso assign users to organi7ations and retrieve the list of organi7ations of a given user%

;verriding a 9ortal ,ervice

G5

:oo(s GroupLocal,ervice/ add, delete and retrieve co))unities% LayoutLocal,ervice/ add, delete, retrieve and )anage pages of co)+ )unities, organi7ations and users%

For a co)plete list of the services availa#le and the )ethods of each of the) chec( the Iavadocs distri#uted 'ith your version of Liferay%

Overriding a Language.properties File


$n addition to the three capa#ilities of hoo(s already discussed, it is also pos+ si#le to override 9anguage.properties files fro) a hoo(, allo'ing you to change any of the )essages displayed #y Liferay to suit your needs% &he process is e1+ tre)ely si)ilar to any of the ones 'e have Iust descri#ed% *ll you need to do is to create a Language file for the language 'hose )essages you 'ant to custo)i7e and then refer to it fro) the liferay-hook.xml% For e1a)ple to override the translations to ,panish and French the follo'ing t'o lines 'ould #e added to the file/
=hook> ... =language-properties>content/9anguage#es.properties=/languageproperties> =language-properties>content/9anguage#fr.properties=/languageproperties> ... =/hook>

GE

;verriding a Language%properties File

6. EXT PLUGINS

E1t plugins provide the )ost po'erful )ethod of e1tending Liferay% &his co)es 'ith so)e tradeoffs in co)ple1ity, and so E1t plugins are designed to #e used only in special scenarios in 'hich all other plugin types cannot )eet the needs of the proIect% ?efore deciding to use an E1t plugin it's i)portant to understand the costs of us+ ing such a po'erful tool% &he )ain one is the cost in ter)s of )aintenance% ?ecause E1t plugins allo' using internal *9$s or even over'riting files provided in the Liferay core, it's necessary to revie' all the changes done 'hen updating to a ne' version of Liferay 2even if it's a )aintenance version or a service pac(3% *lso, unli(e the other types of plugins, E1t plugins reHuire the server to #e restarted after deploy)ent, as 'ell as reHuiring additional steps 'hen deploying or redeploying to production sys+ te)s% &he )ain use cases in 'hich an E1t plugin )ay #e needed are/ Custo)i7ing gins
portal.properties

that are not supported #y :oo( 9lu+

Custo)i7ing ,truts *ctions 9roviding custo) i)ple)entations for any of the Liferay #eans de+ clared in Liferay's ,pring files 2use service 'rappers fro) a hoo( in+ stead if possi#le3 *dding J,9s that are referenced fro) portal properties that can only #e changed fro) an e1t plugin 2#e sure to chec( if the property can #e )odified fro) a hoo( plugin #efore doing this3 Direct over'riting of a class 2not reco))ended unless it's strictly ne+ cessary3

E1t plugins

Creating an Ext plugin


E1t plugins are stored 'ithin the ext directory of the 9lugins ,DK% <avigate to this directory in a ter)inal and enter the follo'ing co))and to create a ne' E1t plugin 2Linu1 and Mac ;, C3/
./create.sh example 6'xample6

;n Findo's enter the follo'ing instead/


create.bat example 6'xample6

.ou should get a ?-$LD ,-CCE,,F-L )essage fro) *nt, and there 'ill no' #e a ne' folder inside of the ext folder in your 9lugins ,DK% <otice that the 9lu+ gins ,DK auto)atically appends K+e1tL to the proIect na)e 'hen creating this folder% ;nce the target has #een e1ecuted successfully you 'ill find a ne' folder called e1a)ple+e1t 'ith the follo'ing structure/
/ext-example/ /docroot/ /:';-I!</ /sDl/ /ext-impl/ /src/ /ext-lib/ /global/ /portal/ /ext-service/ /src/ /ext-util-bridges/ /src/ /ext-util-)ava/ /src/ /ext-util-taglib/ /src/ /ext-web/

&he )ost significant directories in this structure are the ones inside the directory% $n particular you should #e fa)iliar 'ith the follo'+ ing directories/
docroot/:';-I!<

e+t:i! l<srcC Contains the portal-ext.properties configuration file, custo) i)ple)entation classes, and in advanced scenarios, classes that override core classes 'ithin portal-impl.)ar. e+t:lib<globalC 9lace here any li#raries that should #e copied to the glo#al classloader of the application server upon deploy)ent of the e1t plugin%

G>

Creating an E1t plugin

E1t plugins e+t:lib< ortalC 9lace here any li#raries that should #e copied in+ side Liferay's )ain application% -sually these li#raries are needed #ecause they are invo(ed fro) the classes added 'ithin extimpl/src% e+t:service<srcC 9lace here any classes that should #e availa#le to other plugins% Fhen using ,ervice ?uilder, it 'ill put the inter+ faces of each service here% *lso in advanced scenarios, this direct+ ory 'ill contain classes that over'rite the classes of portal-service.)ar% e+t:.eb<docrootC Contains configuration files for the 'e# applic+ ation, including :';-I!</struts-config-ext.xml 'hich 'ill allo' custo)i7ing Liferay's o'n core struts actions% .ou can also place any J,9s needed #y your custo)i7ations here% 9therC ext-util-bridges, ext-util-)ava and ext-util-taglib are only needed in advanced scenarios in 'hich you need to custo)+ i7e the classes of three li#raries provided 'ith Liferay/ utilbridges.)ar, util-)ava.)ar and util-taglib.)ar respectively% $n )ost scenarios you can Iust ignore these directories%

?y default, several files are added to the plugin% :ere are the )ost signific+ ant ones/ $nside docroot/:';-I!</ext-impl/src/
portal,e+t.properties/

this file can #e used to over'rite any configuration property of Liferay, even those that cannot #e overridden #y a hoo( plugin 2'hich is al'ays preferred 'hen possi#le3% <ote that if this file is included it 'ill #e read in+ stead of any other portal-ext.properties in the application server% ?ecause of that you )ay need to copy into it the prop+ erties related to the data#ase connection, file syste) patches, etc%
portlet,e+t.+ml/

$nside docroot/:';-I!</ext-web/docroot/:';-I!</ Can #e used to over'rite the definition of a Liferay portlet% $n order to do this, copy the co)plete defini+ tion of the desired portlet fro) portlet-custom.xml 'ithin Liferay's source code and then apply the necessary changes%
liferay,portlet,e+t.+ml/

,i)ilar to the file a#ove, #ut for the additional definition ele)ents that are specific to Liferay% $n order to override it, copy the co)plete definition of the desired portlet fro) liferay-portlet.xml 'ithin Liferay's source code and then apply the necessary changes% and tiles,defs,e+t.+ml/ Can #e used to custo)i7e the struts actions used #y Liferay's core port+ lets%
struts,config,e+t.+ml

Tip: after creating an Ext plugin, remove all of the files added by de-

Creating an E1t plugin

G@

E1t plugins fault that are not necessary for the extension. This is important because Liferay keeps track of the files deployed by each Ext plugin and it won't allow deploying two Ext plugins if they override the same file to avoid collisions. By removing any files not really necessary from an ext plugin it will be easier to use along with other Ext plugins.

Developing an Ext plugin


Developing an E1t plugin is slightly different than 'or(ing 'ith other plu+ gin types% &he )ain reason for the difference is that an E1t plugin 'hen de+ ployed 'ill )a(e changes to the Liferay 'e# application itself, instead of staying as a separate co)ponent that can #e re)oved at any ti)e% $t's i)portant to re+ )e)#er that once an +9t "lu7in has been de"loyedC some of its files are co"ied inside the Liferay installationC so the only way to remove its chan7es is to rede"loy an unmodi! fied Liferay a""lication a7ain& &he 9lugins ,DK contains several *nt targets that help 'ith the tas( of de+ ploying and redeploying during the develop)ent phase% $n order to do this it re+ Huires a .Uip file of a &o)cat > #ased Liferay #undle% &he *nt targets 'ill un7ip and clean up this installation 'henever needed to guarantee that any change done to the E1t plugin during develop)ent is properly applied and previous changes that have #een re)oved are not left #ehind% &his is part of the added co)ple1ity 'hen using E1t plugins, and so it is reco))ended to use another plugin type to acco)plish your goals if it is at all possi#le%

Set up
?efore atte)pting to deploy an E1t plugin, it's necessary to edit the file in the root folder of the 9lugins ,DK% $f this file doesn't e1ist yet you should create it% ,u#stitute 4username5 'ith the your user $D on your co)puter% ;nce the file is open, add the follo'ing three properties to the file, )a(ing sure the individual paths point to the right locations on your syste)/
build.4username5.properties app.server.dir(4...5/liferay-portal-K.3.K/tomcat-K.3.1K app.server.Uip.name(4...5/liferay-portal-tomcat-K.3.K.Uip ext.work.dir(4...5/work app.server.Uip.name should point to a .Uip 'ith a #undle of Liferay% &he directory denoted #y the property ext.work.dir 'ill #e used to un7ip the #undle as 'ell as re)ove it and un7ip again as needed% app.server.dir should point to the &o)cat directory inside the 'or( directory%

For e1a)ple, if ext.work.dir points to @.\ext-work, and app.server.Uip.name points to @.\files\liferay-portal-tomcat-K.3--4lp.version5.Uip, then app.server.dir should point to @.\ext-work\liferay-portal-4lp.version5\tomcat-K.3.*+%

Initial deployment
;nce the environ)ent is set up, 'e are ready to start custo)i7ing% Fe'll GB Developing an E1t plugin

E1t plugins sho' the full process 'ith a si)ple e1a)ple, custo)i7ing the sections of a user profile% Liferay allo's doing that through the portal-ext.properties configura+ tion file, #ut 'e'll #e changing a property that cannot #e changed fro) a hoo( plugin% $n order to )a(e this change, open the docroot/:';-I!</extimpl/src/portal-ext.properties file and paste the follo'ing contents inside/
users.form.update.main(details,password,organiUations,communities,roles

&his line re)oves the sections for user groups, pages and categori7ations% Fe )ight 'ant to )a(e this change #ecause 'e don't 'ant the) in our portal% ;nce 'e've )ade this change, 'e are ready to deploy% ;pen a ter)inal 'in+ do' in your ext/example-ext directory and enter this co))and/
ant deploy

.ou should get a ?-$LD ,-CCE,,F-L )essage, 'hich )eans that your plu+ gin is no' #eing deployed% $f you s'itch to the ter)inal 'indo' running Liferay and 'ait for a fe' seconds, you should see the )essage KE1tension environ)ent for e1a)ple+e1t has #een applied% .ou )ust restart the server and redeploy all other plugins%L 6edeploying all other plugins is not strictly )andatory, #ut you should do it if so)e changes applied through the E1t plugin )ay affect the de+ ploy)ent process itself% &he ant deploy target #uilds a .war file 'ith all the changes you have )ade and copies the) to the auto deploy directory inside the Liferay installation% Fhen the server starts, it detects the .war file, inspects it, and copies its content to the appropriate destinations 'ithin the deployed and running Liferay inside your application server% .ou )ust no' restart your application server% ;nce the server has started, log in as an ad)inistrator and go to Control Pan! el !D Users% Edit an e1isting user and verify that the right navigation )enu only sho's the five sections that 'ere referenced fro) the users.form.update.main property% ;nce 'e've applied this si)ple )odification to Liferay, 'e can go ahead 'ith a slightly )ore co)ple1 custo)i7ation% &his 'ill give us an opportunity to learn the proper 'ay to redeploy an E1t plugin, 'hich is different fro) the initial de+ ploy)ent% For this e1a)ple 'e'll custo)i7e the details vie' of the user profile% Fe could do that Iust #y over'riting its J,9, #ut this ti)e 'e'll use a )ore po'erful )ethod 'hich also allo's adding ne' sections or even )erging the e1isting ones% Liferay allo's referring to custo) sections fro) the portal-ext.properties and i)ple)enting the) Iust #y creating a J,9% $n our case 'e'll )odify the property users.form.update.main once again to set the follo'ing value/
users.form.update.main(&asic,password,organiUations,communities,roles

&hat is, 'e re)oved the section details and added a ne' custo) one called basic% Fhen Liferay's user ad)inistration reads this property it loo(s for the i) + ple)entation of each section #ased on the follo'ing conventions/ &he section should #e i)ple)ented in a J,9 inside the directory/ ht)l4portlet4enterpriseJad)in4user

Developing an E1t plugin

GA

E1t plugins &he na)e of the J,9 should #e li(e the na)e of the section plus the .)sp e1tension% &here is one e1ception% $f the section na)e has a dash sign 2K+L3, it 'ill #e converted to an underscore sign 2KJL3% For e1a)ple, if the section is called my!info, the J,9 should #e na)ed my#info.)sp% &his is done to co)ply to co))on standards of J,9 na)ing% &he na)e of the section that 'ill #e sho'n to the user 'ill #e loo(ed for in the language #undles% Fhen using a (ey4value that is not already a)ong the ones included 'ith Liferay, you should add it to the 9anguage-ext.properties and each of the language vari+ ants for 'hich 'e 'ant to provide a translation% Fithin the E1t plugin these files should #e placed 'ithin ext-impl/src%

$n our e1a)ple, 'e'll need to create a file 'ithin the E1t plugin in the fol+ lo'ing path/
ext-web/docroot/html/portlet/enterprise#admin/user/basic.)sp

For the contents of the file, you can 'rite the) fro) scratch or )a(e a copy of the details.)sp file fro) Liferay's source code and )odify fro) there% $n this case 'e've decided to do the latter and then re)ove so)e fields to si)plify the creation of a user% &he result is this/
=BC include file(6/html/portlet/enterprise#admin/init.)sp6 B> =B Aser selAser ( /Aser0reDuest.get ttribute/6user.selAser60E B> =liferay-ui.error-marker key(6errorSection6 value(6details6 /> =aui.model-context bean(6=B( selAser B>6 model(6=B( Aser.class B>6 /> =hV>=liferay-ui.message key(6details6 />=/hV> =aui.fieldset column(6=B( true B>6 css@lass(6aui-wW36> =liferay-ui.error exception(6=B( 2uplicateAserScreen!ame'xception.class B>6 already-taken6 /> message(6the-screen-name-you-reDuested-is-

=liferay-ui.error exception(6=B( 8eservedAserScreen!ame'xception.class B>6 reserved6 /> message(6the-screen-name-you-reDuested-is-

=liferay-ui.error exception(6=B( AserScreen!ame'xception.class B>6 message(6please-enter-a-valid-screen-name6 /> =aui.input name(6screen!ame6 /> =liferay-ui.error exception(6=B( 2uplicateAser'mail ddress'xception.class B>6

>!

Developing an E1t plugin

E1t plugins
message(6the-email-address-you-reDuested-is-

already-taken6 />

=liferay-ui.error exception(6=B( 8eservedAser'mail ddress'xception.class B>6 reserved6 /> B>6 message(6the-email-address-you-reDuested-is-

=liferay-ui.error exception(6=B( Aser'mail ddress'xception.class message(6please-enter-a-valid-email-address6 /> =aui.input name(6email ddress6 /> =liferay-ui.error exception(6=B( @ontact<irst!ame'xception.class message(6please-enter-a-valid-first-name6 />

B>6

=liferay-ui.error exception(6=B( @ontact<ull!ame'xception.class B>6 essage(6please-enter-a-valid-first-middle-and-

last-name6 />

=aui.input name(6first!ame6 /> =liferay-ui.error exception(6=B( @ontact9ast!ame'xception.class B>6 message(6please-enter-a-valid-last-name6 /> =aui.input name(6last!ame6 /> =/aui.fieldset>

$n our case, 'e don't need to add a ne' (ey to 9anguage-ext.properties, #e+ cause K#asicL is already included in Liferay's language #undle% Fe are ready to redeploy%

Redeployment
,o far, the process has #een very si)ilar to that of other plugin types% &he differences start 'hen redeploying an E1t plugin that has already #een de+ ployed% *s )entioned earlier, 'hen the plugin 'as first deployed some of its files were co"ied within the Liferay installation& *fter )a(ing any change to the plugin the reco))ended steps to redeploy are first to stop the application server, and then to e1ecute the follo'ing ant targets/
ant clean-app-server direct-deploy

&hese ant targets first re)ove the 'or( #undle 2un7ipping the one that 'as referred to through build.4username5.properties3, and then deploy all the changes directly to the appropriate directories% &he direct-deploy target is faster #ecause the changes are applied directly%, 'hile the Liferay server does it on start up if you use the deploy target% For that reason it is usually preferred during develop)ent% .ou can deploy several E1t plugins to the sa)e server, #ut you 'ill have to redeploy each of the) after e1ecuting the clean-app-server target%

Developing an E1t plugin

>"

E1t plugins ;nce you have finished the develop)ent of the plugin you can e1ecute the follo'ing ant target to generate a .war file for distri#ution/
ant war

&he file 'ill #e availa#le 'ithin the dist directory in the root of the plugins ,DK%

Advanced customization techniques


&his section covers additional custo)i7ation techniHues that are possi#le through an E1t plugin% *s )entioned a#ove, you can change al)ost everything 'ithin Liferay 'hen using the E1t plugin, therefore #e careful 'hen using such a po'erful tool% *l'ays (eep in )ind that 'ith ever ne' Liferay version, i)ple)entation classes )ay have changed% &hus if you've changed Liferay source code directly, you )ay have to )erge your changes into the ne'er Liferay version% General ap+ proach for )ini)i7ing conflicts is W don't change anything, only e1tend% &he alternative is to e1tend the class you 'ant to change and override )eth+ ods needed% &hen use so)e of Liferay's configuration files to reference your su#+ class as a replace)ent of the original class% &his and other advanced techniHues are descri#ed in detail in the follo'ing sections%

Advanced configuration files


Liferay uses several internal configuration files for easier )aintenance and also to configure the li#raries and fra)e'or(s it depends on, such as ,truts or ,pring% For advanced custo)i7ation needs it )ay #e useful to override the con+ figuration specified in these files, so Liferay provides a clean 'ay to do that fro) an E1t plugin 'ithout )odifying the original files% <e1t is a list of all of these files, along 'ith a description and a reference to the original file in the path 'here they can #e found in the source code of Liferay 2you )ay need to loo( at the) for reference3/ e1t+i)pl4src4ME&*+$<F4e1t+)odel+hints%1)l Description/ &his file allo's over'riting the default proper+ ties of the fields of the data )odels used #y Liferay's core portlets% &hese properties deter)ine ho' the for) to create or edit each )odel is rendered% ;riginal file in Liferay/ portal+i)pl4src4ME&*+$<F4portal+ )odel+hints%1)l Description/ &his file allo's over'riting the ,pring configura+ tion used #y Liferay and any of its core portlets% &he )ost co))on usage is to configure specific datasources or to s'ap the i)ple)entation of a given service 'ith a custo) one% Developing an E1t plugin

e1t+i)pl4src4ME&*+$<F4e1t+spring%1)l

>

E1t plugins ;riginal files spring%1)l in Liferay/ portal+i)pl4src4ME&*+$<F4S+

e1t+i)pl4src4content4Language+e1tJS%properties Description/ &his file allo's over'riting the value of any (ey used #y Liferay's -$ to support I01-% ;riginal file in Liferay/ portal+i)pl4src4content4Language+ S%properties Description/ &his file allo's over'riting the logEI configura+ tion% &he )ost co))on usage is to increase or decrease the log level of a given pac(age or class to o#tain )ore infor)a+ tion or hide unneeded infor)ation fro) the logs respectively% ;riginal file in Liferay/ portal+i)pl4src4ME&*+$<F4portal+lo+ gEI%1)l

e1t+i)pl4src4ME&*+$<F4portal+logEI+e1t%1)l

e1t+i)pl4src4co)4liferay4portal4Icr4Iac(ra##it4dependencies4re+ pository+e1t%1)l Description/ &his file allo's over'riting the configuration of the Jac(ra##it repository% 6efer to the Jac(ra##it configura+ tion docu)entation for details 2http/44Iac(ra#+ #it%apache%org4Iac(ra##it+configuration%ht)l3 ;riginal file in Liferay/ portal+ i)pl4src4co)4liferay4portal4Icr4Iac(ra##it4dependencies4re pository%1)l Description/ &his file allo's over'riting the declaration of the core portlets included in Liferay% &he )ost co))on usage is to change the init para)eters or the roles specified% ;riginal file in Liferay/ portal+'e#4docroot4FE?+$<F4portlet+ custo)%1)l Description/ &his file allo's over'riting the Liferay+specific declaration of the core portlets included in Liferay% 6efer to the liferay+portlet+appJ>J!J!%dtd file for details on all the availa#le options% -se this file 'ith care since the code of the portlets )ay #e assu)ing so)e of these options to #e set to certain values% ;riginal file in Liferay/ portal+'e#4docroot4FE?+$<F4liferay+ portlet%1)l Description/ &his file allo's over'riting the portlets that 'ill >5

e1t+'e#4docroot4FE?+$<F4portlet+e1t%1)l

e1t+'e#4docroot4FE?+$<F4liferay+portlet+e1t%1)l

e1t+'e#4docroot4FE?+$<F4liferay+display%1)l

Developing an E1t plugin

E1t plugins #e sho'n in the K*dd applicationL pop+up and the categories in 'hich they'll #e organi7ed% &he )ost co))on usage is to change the categori7ation, hide so)e portlets or )a(e so)e Control 9anel portlets availa#le to #e added to a page% ;riginal file in Liferay/ portal+'e#4docroot4FE?+$<F4liferay+ display%1)l Description/ &his file allo's specifying custo) te)plate files for each of the layout te)plates provided #y default 'ith Liferay% .ou should not need to do this e1cept for very ad+ vanced needs% ;riginal file in Liferay/ portal+'e#4docroot4FE?+$<F4liferay+ layout+te)plates%1)l Description/ &his file allo's changing the properties of the de+ fault the)es provided #y default 'ith Liferay% .ou should not need to do this e1cept for very advanced needs% ;riginal file in Liferay/ portal+'e#4docroot4FE?+$<F4liferay+ loo(+and+feel%1)l

e1t+'e#4docroot4FE?+$<F4liferay+layout+te)plates+e1t%1)l

e1t+'e#4docroot4FE?+$<F4liferay+loo(+and+feel+e1t%1)l

Changing the API of a core service


;ne advanced custo)i7ation need that appears in so)e scenarios is to change the *9$ of a )ethod provided #y one of Liferay's services, for e1a)ple the -serLocal,ervice% $s it possi#le to do thatN &he short ans'er is no% &he long ans'er is that you can #ut it 'ill reHuire )odifying Liferay's source code directly and )a(e )anual changes to Huite a fe' files% &he good ne's is that there is a #etter alternative to achieve the end goal% &he #est 'ay to e1tend an e1isting service is to create a co)ple)entary cus+ to) service, for e1a)ple a My-serLocal,ervice that includes all the ne' )eth+ ods% .our custo) code can invo(e this service instead of the default service and the i)ple)entation of your service can invo(e the original service as needed% <ote that this techniHue does not reHuire an E1t plugin since it can #e done fro) portlet plugins% $n fact, using service+#uilder for E1t plugin is deprecated #ut is supported for )igration fro) the old e1tension environ)ent% $n so)e advanced circu)stances it's desired to change the i)ple)entation of the original service to call your custo) one, 'hich can only #e done fro) an E1t plugin% &o achieve this, override spring definition for -serLocal,ervice-til in e1t+spring%1)l and point it to your 4&-serLocal,ervice$)pl 2instead of -ser+ Local,ervice$)pl3% &his 'ay #oth My-serLocal,ervice-til and -serLocal,er+ vice-til 'ill use the sa)e spring #ean/ your ne' i)ple)entation% >E Developing an E1t plugin

E1t plugins

Replacing core classes in portal-impl


$f you really need to change core portal+i)pl class and this class that cannot #e replaced in any configuration file, then #est 'ay to avoid conflicts and easily )erge 'ith a ne' portal version is to/ "% % 5% E% G% 6ena)e original class 2e%g% Deploy-til MyDeploy-til3 Create ne' su#class 'ith old na)e 2e%g Deploy-til e1tends MyDe+ ploy-til3 ;verride )ethods you need to change Delegate static )ethods -se logger 'ith appropriate class na)e for #oth classes 2e%g% De+ ploy-til3

&his strategy 'ill help you deter)ine 'hat you 'ill need to )erge in the fu+ ture 'hen a ne' version of Liferay is released%

Tip: This is a very advanced technique that may have a high impact on the maintainability of your code, especially if abused. Try to look for alternatives and if you confirm that this is your only alternative try to apply only for the short term and get in touch with Liferay's developers to apply the necessary changes to the product source code.

Licencing and Contributing


Liferay 9ortal is ;pen ,ource soft'are licensed under the LG9L %" license 2http/44'''%gnu%org4licenses4lgpl+ %"%ht)l3% $f you reuse any code snippet and redistri#ute it either pu#licly or to an specific custo)er, you need to )a(e sure that those )odifications are co)pliant 'ith this license% * co))on 'ay to do this is to )a(e the source code of your )odifications availa#le to the co))unity under the sa)e license, #ut )a(e sure to read the license te1t yourself to find the #est option that fits your needs% $f the goal of the changes 'as to fi1 a #ug or to )a(e an i)prove)ent that could #e of interest to a #roader audience, consider contri#uting it #ac( to the proIect% &hat 'ould #enefit all other users of the product and also 'ould #e good for you since you 'on't have to )aintain the changes 'hen ne' versions of Liferay co)e out% .ou can notify Liferay of #ugs or i)prove)ents in is+ sues%liferay%co)% &here is also a 'i(i page 'ith instructions on ho' to contri#+ ute to Liferay/ http/44'''%liferay%co)4co))unity4'i(i4+4'i(i4Main4Contri#uting

Deploying in production
$n production or pre+production environ)ents it's often not possi#le to use *nt to deploy 'e# applications% *lso, so)e application servers such as Fe#+

Deploying in production

>G

E1t plugins ,phere or Fe#logic have their o'n deploy)ent tools and it isn't possi#le to use Liferay's autodeploy process% &his section descri#es t'o )ethods for deploying and redeploying E1t plugins in production that can #e used in each of these scenarios%

Method 1: Redeploying Liferay's web application


&his )ethod can #e used in any application server that supports auto de+ ploy, such as &o)cat or J?oss% $ts )ain #enefit is that the only artifact that needs to #e transferred to the production syste) is the .war file 'hich the E1t plugin produced using the ant war target, 'hich is usually a s)all file% :ere are the steps that need to #e e1ecuted on the server/ "% 6edeploy Liferay% &o do this, follo' the sa)e steps you used 'hen first deploying Liferay on the app server% $f you are using a #undle, you can Iust un7ip the #undle again% $f you've installed Liferay )anually on an e1isting application server, you'll need to redeploy the .war file and copy the glo#al li#raries to the appro+ priate directory 'ithin the application server% $f this is the first ti)e the E1t plugin is deployed, you can s(ip this step% Copy the E1t plugin .war into the auto deploy directory% For a #undled Liferay distri#ution, the de"loy folder is in the root folder% ;nce the E1t plugin is detected and deployed #y Liferay, restart the Liferay server%

% 5%

Method 2: Generate an aggregated WAR file


&his )ethod can #e used for application servers that do not support autode+ ploy, such as Fe#,phere or Fe#logic% $ts )ain #enefit is that all E1t plugins are )erged #efore deploy)ent to production, so a single .war file 'ill contain Liferay plus the changes fro) one or )ore E1t plugins% ?efore deploying the .war file, you'll need to copy the dependency .)ars for #oth Liferay and the E1t plugin to the glo#al application server class loader in the production server% &his location varies fro) server to serverR please see the Liferay Portal AdministratorEs ;uide for further details for your application server% &o create the aggregated .war file, deploy the E1t plugin first to the Liferay #undle you are using in your develop)ent environ)ent 2using for e1a)ple, &o)cat3% ;nce it's deployed, restart the server so that the plugin is fully deploy and shut it do'n again% <o' the aggregated file is ready% Create a .war file #y 7ip+ ping the webapps/8%%" folder of &o)cat% *lso, copy all the li#raries fro) the lib/ext directory of &o)cat that are associated to all the E1t plugins to your ap+ plication server's glo#al classpath, as noted a#ove% &hese steps 'ill #e auto)ated 'ith *nt targets in the ne1t version of Liferay, #ut for no', they need to #e done )anually% ;nce you have the aggregated .war file follo' these steps on the server/ "% % >> 6edeploy Liferay using the aggregated F*6 file% ,top the server and copy the ne' version of the glo#al li#raries to Deploying in production

E1t plugins the appropriate directory in the application server%

Deploying in production

>@

Migrating old extension environments


E1t plugins have #een created as an evolution of the e1tension environ)ent provided in Liferay G% and previous versions of Liferay% ?ecause of this a co))on need for proIects up + grading fro) previous versions )ight #e to )igrate E1tension environ)ents into E1t plugins% &he good ne's is that this tas( is auto)ated and thus relatively easy% Tip: When migrating an extension environment, it's worth considering if all or at least some of its features can be moved into other types of plugins such as portlets and hooks. The benefit of using portlets and hooks is that since they are focused on specific goals they are easier to learn. Additionally they are cheaper to maintain since they often require fewer changes when upgrading to a new version of Liferay. &he process of )igrating consists of e1ecuting a target 'ithin the e1t directory fro) 9lu+ gins ,DK, pointing to the old e1tension environ)ent and na)ing the ne' plugin/
ant upgrade-ext -2ext.dir(/pro)ects/liferay/ext -2ext.name(my-ext -2ext.display.name(6&y 'xt6

:ere is a description of the three para)eters used/


ext.dir is

a co))and line argu)ent to the location of the old E1tension Environ+ the na)e of the E1t plugin that you 'ant to create the display na)e

)ent%
ext.name is ext.display.name is

*fter e1ecuting the target you should see the logs of several copy operations that 'ill ta(e files fro) the e1tension environ)ent and copy the) into the eHuivalent directory 'ithin the E1t plugin 2read the section KCreating an E1t pluginL for an e1planation of the )ain directories 'ithin the plugin3% Fhen the )igration process is co)plete, so)e additional tas(s 'ill #e needed to upgrade the code to the ne' version of Liferay% ,o)e of the )ost typical tas(s are/ 6evie' the uses of Liferay's *9$s and adapt the) accordingly% 6evie' the changes to the J,9s and )erge your changes into the J,9s of the ne' Liferay version% Fhen using ,ervice ?uilder you 'ill need to run ant build-service again% $t's also reco))ended to consider )oving this code to a portlet plugin, #ecause it is no' as po'erful and allo's for greater )odularity and )aintaina#ility% $f you've i)ple)ented portlets in E1t, )igrate the) to portlet plugins, as this capa#ility is deprecated and is not guaranteed to #e availa#le in future releases%

Conclusions
E1t plugins are a very po'erful 'ay of e1tending Liferay% &here are no li)its in 'hat can #e custo)i7ed using the) and for that reason they have to #e used carefully% $f you find your + self using an E1t plugin, verify if all or part of the desired functionality can #e i)ple)ented through portlets, hoo(s or 'e# plugins instead% $f you really need to use an E1t plugin )a(e it as s)all as possi#le and )a(e sure you fol+ lo' the instructions in this guide carefully to avoid issues%

7. LIFERAY IDE

Liferay's developers use a variety of tools to develop the product and as a con + seHuence of that they have al'ays tried hard to allo' other developers to use any tools they 'anted for their o'n develop)ent% ?ecause of this you can develop portals #ased on Liferay 'ith co)ple1 $DEs Eclipse, <et#eans or $ntelliJ $dea or Iust use te1t editors such as <otepad% .ou can 'rite your persistence layer directly using ,OL and JD?C or you can use advanced o#Iect+relational )apping li#raries such as hi#ernate or i?atis% ?ut 'hile #eing agnostic is great, specially for )ore e1perienced developers 'ho can reuse their e1isting (no'ledge, it can #e over'hel)ing for ne'co)ers% For that reason Liferay has also develped specific develop)ent tools that can #e used to ease the learning curve 'hen developing portlets 'ith Liferay% &he )ost significant of these tools is Liferay $DE, a fully featured $ntegrated Develop)ent Environ)ent #ased on Eclipse% Liferay $DE is an e1tension for the Eclipse platfor) that supports develop)ent of plugin proIects for the Liferay 9ortal platfor)% $t is availa#le as a set of Eclipse plugins installa#le fro) an update+site% &he latest version supports developing G Liferay plu+ gin types/ portlets, hoo(s, layout te)plates, the)es, and e1t plugins% Liferay $DE re+ Huires the Eclipse Java EE developer pac(age using either Galileo or :elios versions% &he first t'o sections #elo' sho' ho' to install and set+up Liferay $DE 'ithin your environ)ent% $f you are using a copy of Liferay Developer ,tudio, 'hich co)es 'ith Liferay 9ortal Enterprise Edition, you can s(ip directly to the section titled K&esting the Liferay portal serverL since it co)es already preconfigured%

Liferay $DE

Installation
&his section is a detailed guide to install Liferay $DE%

Requirements
Java G%! J6E Eclipse :elios Java EE for developers pac(age

Installation steps
"% % 5% $nstall Eclipse :elios or Galileo 2un7ip do'nload file fro) a#ove3 6un eclipse e1ecuta#le 2eclipse%e1e3 Fhen eclipse opens, go to :elp M $nstall <e' ,oft'are%%%

E%

$n the KFor( 'ithL field, paste in one of the follo'ing update sites/ a3 http/44releases%liferay%co)4tools4ide4eclipse4helios4sta#le4

#3 http/44releases%liferay%co)4tools4ide4eclipse4helios4nightly4 2<ightly #uilds are unsta#le #ut contain ne' features )ore Huic(ly3 G% *fter pasting in -6L press enter

@!

$nstallation

Liferay $DE

>% &he Liferay $DE features should #e detected, select it #efore clic(ing <e1t

@% *fter calculating dependencies, clic( <e1t to co)plete installation% B% *fter installation restart Eclipse to verify installation is co)plete% A% *fter restarting Eclipse go to :elp M *#out and you should see and icon #adge for Liferay $DE that sho's you have it properly installed

Alternative installation
&he ne1t set of instructions descri#e ho' to install Liferay $DE 'ithout typ+ ing the -6L of an update site/ "% $nstead of typing in a -6L, you can do'nload the the archived update site fro) this lin( liferay+ide+eclipse+updatesite+"% % %7ip %

$nstallation

@"

Liferay $DE % $n *dd ,ite dialog, clic( the X*rchiveX #utton and #ro'se to the loca+ tion of the do'nloaded 7ip file% 5% $nstallation proceeds the sa)e as previous section%

Set up
&his section descri#es the setup necessary to #egin doing Liferay develop+ )ent and testing your develop)ents%

Requirements
?efore getting started you should satisfy the ne1t reHuire)ents/ "% % 5% Liferay 9ortal >%! 2>%!%G or greater3 do'nloaded and un7ipped Liferay plug+ins ,DK 2>%!%G or greater3 do'nloaded and un7ipped Eclipse :elios Java EE Developers V Liferay $DE 2see the $nstallation steps3

Note: Earlier versions of Liferay, eg 5.2.x, are not supported yet by the Liferay IDE

Liferay Plugins SDK Setup


?efore you can #egin creating ne' Liferay plugin proIects, a Liferay 9lugins ,DK and Liferay 9ortal )ust #e installed and configured in the $DE% "% ;pen Eclipse 'ith Liferay $DE installed% % ;pen 9reference page for Liferay M $nstalled ,DKs 2Go to Findo' M 9ref+ erences M Liferay M $nstalled ,DKs3

5%

*dd your ,DK using the add #utton 'hich #rings up the *dd ,DK Dialog

,et up

Liferay $DE

E%

?ro'se to the location of your 9lug+ins ,DK installation

G% &he default na)e is the na)e of the directory #ut you can change it if you 'ish >% ,elect ;K and you should see your ,DK in the list of $nstalled ,DKs

Note: multiple SDKs can be added to the preferences but you will need to select at least one SDK to be the default which is represented by the SDK that has the checkbox selected.

Liferay Portal Tomcat Runtime / Server Setup


"% $n Eclipse open the 6unti)e environ)ents preference page 2Go to Fin+ do' M 9references M ,erver M 6unti)e environ)ents3

,et up

@5

Liferay $DE

% Clic( *dd to add a ne' Liferay runti)e and find KLiferay v>%! 2&o)cat >3L under the Liferay, $nc% category and clic( <e1t%

@E

,et up

Liferay $DE 5% Clic( ?ro'se and select the location of the liferay+portal+>%!%1 directory

E% ;nce you have selected the Liferay portal directory, if a #undle J6E is present, this #undle 'ill #e auto)atically selected as the J6E to use for launch+ ing the server% :o'ever, if there is no J6E #undle 2Mac and Linu1 users3 then you 'ill need to select the J6E to use for launch%

,et up

@G

Liferay $DE

G% Clic( finish and you should see the Liferay portal runti)e in the list of runti)es in the preference page

>% Clic( o( to save the runti)e preferences% @% $f you didn't choose to create a server you 'ill need to create one fro) the servers vie' #efore you can test the server%

B% Find the Liferay, $nc category and select the Liferay v> ,erver and choose the Liferay v> 6unti)e that you had previously created

@>

,et up

Liferay $DE

Testing/Launching Liferay Tomcat Server


;nce your Liferay 9ortal ,erver setup is co)plete you can launch the server fro) the servers ta# of Eclipse% ,i)ply select the server and then clic( on the green K,tart the ,erver #utton%L ;nce the server is running a red K&er)inateL #utton 'ill appear 'hich you can use to stop the server

&esting4Launching ,erver

Liferay

&o)cat

@@

Liferay $DE

*lternatively, you can start4stop the server #y selecting K6unL or K&er)inateL fro) the 6un )enu of Eclipse% ;nce the server is finish launching you can open the portal ho)e fro) the conte1t )enu of the Liferay &o)cat server in the ,ervers vie'/

Creating New Liferay Projects


<o' that an ,DK and portal server have #een configured you can create a ne' Liferay plug+in proIect% Go to File M <e' 9roIect%%% M Liferay M Liferay 9lug+in 9roIect%

@B

Creating <e' Liferay 9roIects

Liferay $DE

$n the Liferay proIect 'i7ard page, the ne'ly configured ,DK and Liferay 6unti)e should #e pre+selected% *lso the plugin type KportletL is the default% ,i)ply type in a proIect na)e and cooresponding display na)e and clic( Finish%

Creating <e' Liferay 9roIects

@A

Liferay $DE $f it 'or(ed you should see a ne' plugin proIect in the pac(age e1plorer%

Deploying New Liferay Projects to Liferay Server


<o' 'ith the ne'ly created proIect, right+clic( the Liferay ,erver in the ,ervers vie' and select K*dd and 6e)ove%%%L

,elect the ne' proIect and clic( K*ddL to )ove it to #e deployed to the server%

B! Deploying <e' Liferay 9roIects to

Liferay $DE

and then clic( XFinishX .ou should see the proIect get deployed to Liferay &o)cat server and in the console see a )essage a#out " ne' portlet #eing availa#le/

;pen Liferay 9ortal :o)e http/44localhost/B!B!4 in )ost cases and login 'ithin the follo'ing credentials/ user/ testDli%era&.co! pass'ord/ test Clic( *dd M More, e1pand the ,a)ple Category and clic( the *dd lin( ne1t to the Deploying <e' Liferay 9roIects to Liferay ,erver B"

Liferay $DE De)o application% .ou should see the correctly deployed portlet on the page%

Importing Existing Projects into Liferay IDE


$f you have #een follo'ing the e1a)ples of this guide using the 9lugins ,DK or have previous plugins developed 'ith it that you 'ant to (eep developing 'ith Liferay $DE then this section is for you% $t also sho's other options to i)port% ,pecifically it sho's ho' to i)port fro)/ "% % 5% E1isting Liferay proIects that are not in Eclipse 'or(space 9roIects already in Eclipse #ut not Liferay $DE 2donYt have Liferay facet or target runti)e3 E1isting Liferay $DE proIects fro) another version of Liferay $DE or 'or(space

&he follo'ing su#sections descri#e the steps for each of the) 'ith )ore detail%

Importing existing Liferay Project from a Plugins SDK


*n e1isting Liferay proIect that has #een created #y the 9lugins ,DK #ut has not yet #een added to an Eclipse 'or(space or have not #een added to the current 'or(space open in Eclipse4Liferay $DE% &hese proIects )ay or )ay not have %proIect or %classpath files% Fhether they do or donYt 'e 'ill follo' the sa)e steps and use the sa)e 'i7ard% &here are t'o options to create proIects fro) e1isting sources, depending on 'hether you 'ant to create one single proIect or )ultiple proIects fro) the sa)e ,DK% Let's see #oth in detail% Note: The two next sections assume that you have Liferay plug-ins SDK directory structure and you have previously created projects inside of that directory structure

Create one single project from one plugin in an existing sources


&his option 'ill create one proIect for a single plugin that already e1ists in+ B $)porting E1isting 9roIects into Liferay

Liferay $DE side a 9lugins ,DK% "% $n Eclipse, go to File M <e' M 9roIect%%% M Liferay M Liferay 9roIect fro) E1isting ,ource

;r you can invo(e the sa)e 'i7ard fro) the Liferay shortcut #ar

?ro'se to the location of the proIect folder% <ote/ the proIect folder should #e a su#+directory of one of the plugin types, e%g% portlets, hoo(s, the)es, etc% $f not it 'ill not #e a#le to #e i)ported correctly%;nce you select the plugin proIect folder you should see the plugin type and ,DK version values get updated to correct values% $f the ,DK is not recent enough or proIect type is not correct it 'ill #e )ar(ed 'ith an error%

$)porting E1isting 9roIects into Liferay $DE

B5

Liferay $DE 5% Once you select the plugin project folder you should see the plugin type and SDK version values get updated to correct values. If the SDK is not recent enough or project type is not correct it will be marked with error

E%

<e1t you 'ill need to select a Liferay 6unti)e to configure on the proIect once it is i)ported% $f you donYt have a Liferay 6unti)e, use the <e'%%% #utton to create a ne' Liferay portal runti)e 2to)cat #undle only supported3%

G% >%

Clic( Finish to perfor) the i)port 6ead the section #elo' on verifying the success of an i)port process to )a(e sure that your proIect 'as configured correctly as a Liferay $DE proIect%

Create multiple projects for all plugins in a Plugins SDK


&his option 'ill transverse an e1isting 9lugins ,DK and 'ill allo' creating one proIect for each of the plugins it finds inside in one single step% "% $n Eclipse go to File M $)port%%% M Liferay M Liferay 9lugin ,DK proIects

BE $)porting E1isting 9roIects into Liferay

Liferay $DE % First you )ust select the 9lugins ,DK that you 'ant to i)port proIects fro) in the co)#o #o1 at the top of the 'i7ard%

5%

$f you donYt have any ,DKs configured in Liferay $DE use the KconfigureL lin( to add a setting that points to the 9lugins ,DK that you 'ant to i)port proIects fro)% &o configure a 9lugins ,DK on the $nstalled ,DKs on the pref page Iust clic( K*ddL and then ?ro'se to the directory of the 9lugins ,DK root directory% ;nce you have a configured 9lugins ,DK, you can select it in the Co)#o #o1 and then the ,DK location and version 'ill #e filled in% $f either are not valid it 'ill #e )ar(ed 'ith an error%

E%

G%

>%

*fter the ,DK is selected the list of proIects that are availa#le for i)port 'ill #e sho'n in the ta#le% $f the proIects are already in the 'or(space they 'ill #e disa#led% $f the proIect is availa#le for i)port it 'ill have a e)pty chec(#o1 that can #e selected%

$)porting E1isting 9roIects into Liferay $DE

BG

Liferay $DE

@% B% A%

,elect 'hich proIects that you 'ish to i)port% ,elect the Liferay runti)e that you 'ant to setup for the i)ported proIects% $f you donYt have a liferay runti)e you can add one 'ith the K<e'%%%L #utton%

"!% Clic( Finish% ""% 6ead the section #elo' on verifying the success of an i)port process to )a(e sure that your proIect 'as configured correctly as a Liferay $DE proIect%

Importing an existing Eclipse Project that is not aware of the Liferay IDE
$f your proIect is not in your Eclipse 'or(space, you can use the first set of steps a#ove% $f your proIect is already in your 'or(space 2see it in proIect e1plorer3 #ut is not yet a Liferay $DE proIect, the follo'ing steps can #e used to convert the proIect% "% $n Eclipse, right clic( the eclipse proIect that you 'ant to convert, select Liferay M Convert to Liferay plug+in proIect% Note: If you dont have a convert action available it means the project is either already a Liferay IDE project or it is not a faceted project with Java and Dynamic Web project facets configured and will need to be configured accordingly B> $)porting E1isting 9roIects into Liferay

Liferay $DE

Fhen the convert dialog 'i7ard opens your proIect should #e auto+ selected and the ,DK location and ,DK version should #e auto+detected% $f they are not valid an error )essage 'ill #e displayed%

5%

,elect the Liferay runti)e that you 'ish to set on the proIect% $f you donYt have a Liferay 6unti)e define use the K<e'%%%L action to create one%

E% G%

Clic( Finish% 6ead the section #elo' on verifying the success of an i)port process to )a(e sure that your proIect 'as configured correctly as a Liferay $DE proIect%

Importing an existing Liferay IDE project


&his section descri#es the steps that can #e follo'ed if you have previously created or converted a Liferay $DE proIect in your 'or(space #ut it is no longer in the current 'or(space there are a couple of options for i)porting this proIect% "% % ;pen Liferay $DE, go to File M $)port %%% M General M E1isting 9roIects into For(space -se option ,elect root directory, then clic( ?ro'se B@

$)porting E1isting 9roIects into Liferay $DE

Liferay $DE

5% E% G% >%

,elect the directory of the previous Liferay $DE proIect &hen in the list of proIects you should see the one proIect you selected Clic( Finish 6ead the section #elo' on verifying the success of an i)port process to )a(e sure that your proIect 'as configured correctly as a Liferay $DE proIect%

$f you have any errors, it )ay #e that either the ,DK na)e used in that proIect or the runti)e id used doesnYt e1ist in your ne' 'or(space% .ou can )odify the ,DK na)e in the 9roIect 9roperties M Liferay page and you can )odify the targeted runti)e in the 9roIect properties M &argeted 6unti)es page%

Verifying that the import has succeeded


Follo' the follo'ing steps to verify that either of the previous i)port pro+ cesses has #een successful% "% ;nce the proIect i)port process is finished, you should see a ne' proIect inside Eclipse and it should have a KLL overlay i)age to sho' its a Liferay proIect%

,econdly, to )a(e sure the proIect is no' a KLiferay $DEL proIect is to chec( the target runti)e proIect property 2right+clic( proIect M properties M target runti)es3 and also chec( the proIect facets to )a(e sure #oth Liferay runti)e and Liferay plug+in facets are properly configured%

BB $)porting E1isting 9roIects into Liferay

8. LIFERAY APIS AND FRAMEWORKS

&his chapter provides you 'ith a #rief overvie' of several of the essential *9$s and fra)e'or(s provided #y Liferay to developers% *n *9$ is any progra)ing inter+ face that you can invo(e fro) your o'n code either directly through a Java invoca+ tion or through 'e# services to perfor) a certain action% * fra)e'or(, in this con + te1t, is a set of *9$s and configuration that is designed for an specific purpose such as enhancing your applications 'ith a per)ission syste), 'ith tags, 'ith categories, co))ents, etc% &his chapter 'ill (eep evolving 'ith )ore infor)ation a#out the e1isting *9$s and fra)e'or(s and ho' to use it% ,o loo( #ac( for )ore infor)ation often%

Security and Permissions


J,6+ B> 2and J,6+">B3 define si)ple security sche)e using portlet roles and their )apping to portal roles% ;n top of that Liferay i)ple)ents a fine+grained per)issions syste), 'hich developers can use to i)ple)ent access security in their custo) port+ lets% &his section of the docu)ent provides an overvie' of the J,6+ B> 2J,6+">B3 se+ curity syste), Liferay's per)ission syste), and ho' to i)ple)ent the) in your o'n portlets%

JSR Portlet Security


&he J,6 specification defines the )eans to specify the roles that 'ill #e used #y each portlet 'ithin its definition in portlet%1)l% For e1a)ple, the ?logs portlet defini+ tion included in Liferay references 5 roles.
=portlet> =portlet-name>VV=/portlet-name>

Liferay *9$s and Fra)e'or(s


=display-name>;logs=/display-name> class> =portlet-class>com.liferay.portlet.Struts,ortlet=/portlet=init-param> =name>view-action=/name> =value>/blogs/view=/value> =/init-param> =expiration-cache>3=/expiration-cache> =supports> =mime-type>text/html=/mime-type> =/supports> =resourcebundle>com.liferay.portlet.Struts8esource;undle=/resource-bundle> =security-role-ref> =role-name>guest=/role-name> =/security-role-ref> #security,role,ref#role,name-po0er,user#*role,name#*security,role,ref=security-role-ref> =role-name>user=/role-name> =/security-role-ref> =/portlet>

&hese roles need to #e )apped to specific roles 'ithin the portal% &he reason for this )apping is to allo' the deployer of a portlet to solve conflicts if t'o portlets fro) t'o different developers use the sa)e role na)e for different pur+ poses% Tip: Liferay provides an additional behavior to the roles referenced in the portlet.xml file using the security-role-ref element. Each of those roles will be given the permission to "Add to a page" those portlets by default. $n order to do the )apping it is necessary to use portal+specific configura+ tion files% $n the case of Liferay you can define )apping in liferay+portlet%1)l% For e1a)ple see definition of )apping inside liferay+portlet%1)l in portal+
'e#4docroot4FE?+$<F/ =role-mapper> =role-name>administrator=/role-name> =role-link> dministrator=/role-link> =/role-mapper> =role-mapper> =role-name>guest=/role-name> =role-link>7uest=/role-link> =/role-mapper> #role,mapper#role,name-po0er,user#*role,name#role,link-Po0er User#*role,link#*role,mapper-

A!

,ecurity and 9er)issions

Liferay *9$s and Fra)e'or(s


=role-mapper> =role-name>user=/role-name> =role-link>Aser=/role-link> =/role-mapper>

&his )eans that if a portlet definition references the role Kpo'er+userL it 'ill #e )apped to the Liferay role in its data#ase called K9o'er -serL% $n your portlet's code you can then use )ethods as defined in portlet spe+ cification/ U get6e)ote-ser 23 U is-ser$n6ole23 U get-ser9rincipal 23 For e1a)ple to chec( if the current user has the K9o'er -serL role the follo'ing code could #e used/
if /render8eDuest.isAserIn8ole/Xpower-userY00 4 // H. 5

<ote that Liferay doesn't use the is-ser$n6ole23 )ethod in any of the port+ lets provided #y default% $nstead it uses Liferay's per)ission ,yste) directly, to achieve )ore finegrained security% &he ne1t section descri#es this syste) and ho' to use it in your portlets, so that you can decide 'hich option fits your needs #etter%

Liferay's Permission System Overview


*dding per)issions to custo) portlets consists of four )ain steps 2also (no'n as D6*C3/ "% % 5% E% Define all resources and their per)issions% /egister all the resources defined in step " in the per)issions sys+ te)% &his is also (no'n as Kadding resources%L Associate the necessary per)issions 'ith resources% #hec( per)ission #efore returning resources%

Implementing Permissions
?efore you can add per)issions to a portlet, t'o critical ter)s )ust #e defined% /esource + * generic ter) for any o#Iect represented in the portal% E1+ a)ples of resources include portlets 2e%g%, Message ?oards, Calendar, etc%3, Java classes 2e%g%, Message ?oard &opics, Calendar Events, etc%3, and files 2e%g%, docu+ )ents, i)ages, etc%3

,ecurity and 9er)issions

A"

Liferay *9$s and Fra)e'or(s Per!ission + *n action acting on a resource% For e1a)ple, the view in Kvie'+ ing the calendar portletL is defined as a per)ission in Liferay% Keep in )ind that per)issions for a portlet resource are i)ple)ented a little differently fro) other resources such as Java classes and files% $n each of the su#sections #elo', the per)ission i)ple)entation for the portlet resource is e1plained first, then the )odel 2and file3 resource% &he first step in i)ple)enting per)issions is to define your resources and per)issions% .ou can see e1a)ples of ho' this is acco)plished for the #uilt+in portlets #y chec(ing out a copy of the Liferay source code and loo(ing in the portal-impl/src/resource-actions directory% For an e1a)ple of ho' per)is+ sions 'or( in the conte1t of a portlet plugin, chec(out plugins/trunk fro) the Liferay pu#lic ,u#version repository, and loo( in the portlet sam"le!"ermis! sions!"ortlet% LetYs ta(e a loo( at blogs.xml in portal-impl/src/resource-actions and see ho' the #logs portlet defines these resources and actions%
=Ixml version(6*.36I> =resource-action-mapping> =portlet-resource> =portlet-name>VV=/portlet-name> =permissions> =supports> =action-key> @@'SS#I!#@%!"8%9#, !'9=/action-key> =action-key> 22#"%#, 7'=/action-key> =action-key>@%!<I7A8 "I%!=/action-key> =action-key>?I':=/action-key> =/supports> =community-defaults> =action-key>?I':=/action-key> =/community-defaults> =guest-defaults> =action-key>?I':=/action-key> =/guest-defaults> =guest-unsupported> =action-key> @@'SS#I!#@%!"8%9#, !'9=/action-key> =action-key>@%!<I7A8 "I%!=/action-key> =/guest-unsupported> =/permissions> =/portlet-resource> =model-resource> =model-name>com.liferay.portlet.blogs=/model-name> =portlet-ref> =portlet-name>VV=/portlet-name> =/portlet-ref> =permissions> =supports> =action-key> 22#'!"8J=/action-key>

,ecurity and 9er)issions

Liferay *9$s and Fra)e'or(s


=action-key>,'8&ISSI%!S=/action-key> =action-key>SA;S@8I;'=/action-key> =/supports> =community-defaults /> =guest-defaults /> =guest-unsupported> =action-key> 22#'!"8J=/action-key> =action-key>,'8&ISSI%!S=/action-key> =action-key>SA;S@8I;'=/action-key> =/guest-unsupported> =/permissions> =/model-resource> =model-resource> name> =model-name>com.liferay.portlet.blogs.model.;logs'ntry=/model=portlet-ref> =portlet-name>VV=/portlet-name> =/portlet-ref> =permissions> =supports> =action-key> 22#2IS@ASSI%!=/action-key> =action-key>2'9'"'=/action-key> =action-key>2'9'"'#2IS@ASSI%!=/action-key> =action-key>,'8&ISSI%!S=/action-key> =action-key>A,2 "'=/action-key> =action-key>A,2 "'#2IS@ASSI%!=/action-key> =action-key>?I':=/action-key> =/supports> =community-defaults> =action-key> 22#2IS@ASSI%!=/action-key> =action-key>?I':=/action-key> =/community-defaults> =guest-defaults> =action-key>?I':=/action-key> =/guest-defaults> =guest-unsupported> =action-key> 22#2IS@ASSI%!=/action-key> =action-key>2'9'"'=/action-key> =action-key>2'9'"'#2IS@ASSI%!=/action-key> =action-key>,'8&ISSI%!S=/action-key> =action-key>A,2 "'=/action-key> =action-key>A,2 "'#2IS@ASSI%!=/action-key> =/guest-unsupported> =/permissions> ... =/model-resource> =/resource-action-mapping>

9er)issions in the #logs portlet are defined at several different levels, coin+

,ecurity and 9er)issions

A5

Liferay *9$s and Fra)e'or(s ciding to the different sections of the CML file% First, in the =portlet-resource> section, actions and default per)issions are defined on the portlet itself% Changes to portlet level per)issions are perfor)ed on a per+co))unity #asis% &he settings here affect 'hether users can add the portlet to a page, edit its con+ figuration, or vie' the portlet at all, regardless of content% *ll these actions are defined inside the =supports> tag% &he default portlet+level per)issions for )e)#ers of the co))unity are defined inside the =community-defaults> tag% $n this case, )e)#ers of a co))unity should #e a#le to vie' any #logs in that co)+ )unity% Li(e'ise, default guest per)issions are defined in =guest-defaults>% =guest-unsupported> contains per)issions that a guest )ay never #e granted, even #y an ad)inistrator% For the #logs portlet, guests can never #e given per+ )ission to configure the portlet or access it in the control panel% &he ne1t level of per)issions is #ased on the scope of an individual instance of the portlet% &hese per)issions are defined in the first =model-resource> sec+ tion% <otice that the =model-name> is not the na)e of an actual Java class, #ut si)ply of the #logs pac(age% &his is the reco))ended convention for per)is+ sions that refer to an instance of the portlet as a 'hole% Tip: A scope in Liferay is simply a way of specifying how widely the data from an instance of a portlet is shared. For instance, if I place a blogs portlet on a page in the guest community, and then place another blogs portlet on another page in the same community, the two blogs will share the same set of posts. This is the default or community-level scope. If I then configure one of the two blogs and change its scope to the current page, it will no longer share content with any of the other blogs in that community. Thus, with respect to permissions, an instance of a blogs portlet could exist on only one page, or span an entire community. &he difference #et'een the portlet instance per)issions defined in this sec+ tion, and the portlet per)issions in the =portlet-resource> #loc( is su#tle, #ut critical% .ou 'ill notice that per)issions such as adding an entry or su#scri#ing are defined at the portlet instance level% &his )a(es it possi#le to have )ultiple distinct #logs 'ithin a co))unity, each 'ith different per)issions% For in+ stance, a food co))unity could have one #log that every co))unity )e)#er could post recipes to, #ut also have a separate #log containing updates and in+ for)ation a#out the site itself that only ad)inistrators can post to% *fter defining the portlet and portlet instance as resources, 'e )ove on to define )odels 'ithin the portlet that also reHuire per)issions% &he )odel re+ source is surrounded #y the =model-resource> tag% Fithin this tag, 'e first define the )odel na)e% &his )ust #e the fully Hualified Java class na)e of the )odel% <e1t 'e define the portlet na)e that this )odel #elongs to under the portlet-ref tag% &hough unli(ely, a )odel can #elong to )ultiple portlets, 'hich you )ay use )ultiple =portlet-name> tags to define% ,i)ilar to the portlet resource ele)ent, the )odel resource ele)ent also allo's you to define a sup+ ported list of actions that reHuire per)ission to perfor)% .ou )ust list out all the perfor)a#le actions that reHuire a per)ission chec(% *s you can see for a #log entry, a user )ust have per)ission in order to add co))ents to an entry, delete an entry, change the per)ission setting of an entry, update an entry, or si)ply to vie' an entry% &he =community-defaults> tag, the =guest-defaults>

AE

,ecurity and 9er)issions

Liferay *9$s and Fra)e'or(s tag, and the =guest-unsupported> tag are all si)ilar in )eaning to 'hatYs e1+ plained a#ove for a portlet resource% *fter defining your per)ission sche)e for your custo) portlet, you then need to tell Liferay the location of this file% For Liferay core, the CML file 'ould nor)ally reside in portal/portal-impl/classes/resource-actions and a refer+ ence to the file 'ould appear in the default.xml file% For a plugin, you should put the file in a directory that is in the class path for the proIect% &hen create a properties file for your portlet 2the one in the ,a)ple 9er)issions 9ortlet is si)ply called portlet.properties3 and create a property called resource.actions.configs 'ith a value that points to the the CML file% ?elo' is an e1a)ple fro) the ,a)ple 9er)issions 9ortlet/
resource.actions.configs(resource-actions/default.xml

Permission Algorithms
&here are > per)ission algorith)s that Liferay has used during ti)e for chec(ing per)issions% Liferay G introduced algorith) G that is #ased on 6?*C syste)% Liferay > opti)i7ed algorith) G into version >, 'hich included i)port+ ant perfor)ance i)prove)ents #y using a reduced set of data#ase ta#les% $t's i)portant to note that once a per)ission algorith) is configured and re+ sources are created it cannot #e changed, or the e1isting per)issions 'ill #e lost 2and so)e syste) features )ay fail3% For all ne' deploy)ents it is strongly reco))ended to use algorith) >% For deploy)ents that 'ere using other algorith)s it's reco))ended to use the )i+ gration tools provided fro) the Control 9anel M ,erver *d)inistration M Migra+ tion% For )ore info see per)issions%user%chec(%algorith) option in portal%proper+ ties file%

Adding a Resource
*fter defining resources and actions, the ne1t tas( is to 'rite code that adds resources into the per)issions syste)% * lot of the logic to add resources is en+ capsulated in the 8esource9ocalServiceImpl class% ,o adding resources is as easy as calling the add resource )ethod in 6esourceLocal,ervice-til class%
public void add8esources/ String companyId, String groupId, String userId, String name, String primTey, boolean portlet ctions, boolean add@ommunity,ermissions, boolean add7uest,ermissions0E

For all the Java o#Iects that reHuire access per)ission, you need to )a(e sure that they are added as resources every ti)e a ne' one is created% For e1+ a)ple, every ti)e a user adds a ne' entry to her #log, the add6esources2Z3 )ethod is called to add the ne' entry to the resource syste)% :ereYs an e1a)ple of the call fro) the ;logs'ntry9ocalServiceImpl class%
8esource9ocalServiceAtil.add8esources/

,ecurity and 9er)issions

AG

Liferay *9$s and Fra)e'or(s


entry.get@ompanyId/0, entry.get7roupId/0, entry.getAserId/0, ;logs'ntry.class.get!ame/0, entry.get'ntryId/0, false, add@ommunity,ermissions, add7uest,ermissions0E

&he para)eters companyId, groupId, and userId should #e self e1planatory% &he na)e para)eter is the fully Hualified Java class na)e for the resource o#Iect #eing added% &he primTey para)eter is the pri)ary (ey of the resource o#Iect% *s for the portlet ctions para)eter, set this to true if youYre adding portlet ac+ tion per)issions% $n our e1a)ple, 'e set it to false #ecause 'eYre adding a )odel resource, 'hich should #e associated 'ith per)issions related to the )odel ac+ tion defined in blogs.xml% &he add@ommunity,ermissions and the add7uest,ermissions para)eters are inputs fro) the user% $f set to true, 8esource9ocalService 'ill then add the default per)issions to the current co))unity group and the guest group for this resource respectively% $f you 'ould li(e to provide your user the a#ility to choose 'hether to add the default co))unity per)ission and the guest per)ission for the resources 'ithin your custo) portlet, Liferay has a custo) J,9 tag you )ay use to Huic(ly add that functionality% ,i)ply insert the =liferay-ui.input-permissions /> tag into the appropriate J,9 and the chec(#o1es 'ill sho' up on your J,9% ;f course, )a(e sure the tag is 'ithin the appropriate =form> tags% Fhen re)oving entities fro) data#ase it is also good to re)ove per)issions )apped directly to the entity% &o prevent having a lot of dead resources ta(ing up space in the 6esourceJ data#ase ta#le, you )ust re)e)#er to re)ove the) fro) the 6esourceJ ta#le 'hen the resource is no longer applica#le% &o perfor) this operation call the delete8esource/H0 )ethod in 8esource9ocalServiceAtil% :ereYs an e1a)ple of a #logs entry #eing re)oved/
8esource9ocalServiceAtil.delete8esource/ entry.get@ompanyId/0, ;logs'ntry.class.get!ame/0, 8esource.S@%,'#I!2I?I2A 9, entry.get'ntryId0E

Liferay Co))unity Edition >%!%G has a (no'n #ug 2http/44issues%liferay%co)4#ro'se4L9,+"E"5G3 that causes this )ethod to leave so)e data #ehind in the data#ase% &his error does nos affect the latest Enterprise Edition 2>%!%"" and later3 and it has also #een fi1ed in the latest release of the Co))unity Edition 2>%!%> at the ti)e of this 'riting3

Adding Permission
;n the portlet level, no code needs to #e 'ritten in order to have the per+ )ission syste) 'or( for your custo) portlet% .our custo) portlet 'ill auto)at+ ically have all the per)ission features% $f youYve defined any custo) per)issions 2supported actions3 in your portlet-resource tag, those are auto)atically added to a list of per)issions and users can readily choose the)% ;f course, for your custo) per)issions to have any value, youYll need to sho' or hide certain func+ tionality in your portlet% .ou can do that #y chec(ing the per)ission first #efore perfor)ing the intended functionality% $n order to allo' a user to set per)issions on the )odel resources, you 'ill A> ,ecurity and 9er)issions

Liferay *9$s and Fra)e'or(s need to e1pose the per)ission interface to the user% &his can #e done #y adding t'o Liferay -$ tags to your J,9% &he first one is the =liferay-security.permissionsA89> tag 'hich returns a -6L that ta(es the user to the page to configure the per)ission settings% &he second tag is the =liferay-ui.icon> tag that sho's a per)ission icon to the user% ?elo' is an e1a)ple found in the file view#entry#content.)spf%
=liferay-security.permissionsA89 model8esource(6=B( ;logs'ntry.class.get!ame/0 B>6 model8esource2escription(6=B( entry.get"itle/0 B>6 resource,rimTey(6=B( entry.get,rimaryTey/0.toString/0 B>6 var(6entryA896 /> =liferay-ui.icon image(6permissions6 url(6=B( entryA89 B>6 />

&he attri#utes you need to provide to the first tag are model8esource, modand var% &he model8esource attri#ute is the fully Hualified Java o#Iect class na)e% $t then gets translated in 9anguage.properties to a )ore reada#le na)e%
el8esource2escription, resource,rimTey,

*s for the model8esource2escription attri#ute, you can pass in anything that #est descri#es this )odel instance% $n the e1a)ple, the #logs title 'as passed in% &he resource,rimTey attri#ute is si)ply the pri)ary (ey of your )od+ el instance% &he var attri#ute is the varia#le na)e this -6L ,tring 'ill get as+ signed to% &his varia#le is then passed to the =liferay-ui.icon> tag so the per+ )ission icon 'ill have the proper -6L lin(% &hereYs also an optional attri#ute re+ direct thatYs availa#le if you 'ant to override the default #ehavior of the upper right arro' lin(% &hat is all you need to do to ena#le users to configure the per+ )ission settings for )odel resources%

Checking Permissions
&he last )aIor step to i)ple)enting per)issions to a custo) portlet is to add so)e chec(s that guarantee that the configured per)issions are )et% &his )ay #e done in a couple of places% For e1a)ple, your #usiness layer should chec( for per)ission #efore deleting a resource, or your user interface should hide a #utton that adds a )odel 2e%g%, a calendar event3 if the user does not have per+ )ission to do so% ,i)ilar to the other steps, the default per)issions for the portlet resources are auto)atically chec(ed for you% .ou do not need to i)ple)ent anything for your portlet to discri)inate 'hether a user is allo'ed to vie' or to configure the portlet itself% :o'ever, you do need to i)ple)ent any custo) per)ission you have defined in your resource+actions CML file% $n the #logs portlet, one cus+ to) supported action is *DDJE<&6.% &here are t'o places in the source code to chec( for this per)ission% &he first place to chec( for the add per)ission is in your J,9 files% &he presence of the add entry #utton is contingent on 'hether the user has per)ission to add entry%
=B if /permission@hecker.has,ermission/

,ecurity and 9er)issions

A@

Liferay *9$s and Fra)e'or(s


scope7roupId, Xcom.liferay.portlet.blogs.modelY, scope7roupId, Y 22#'!"8JY0 4 // Show add entry button 5 B>

&he second place to chec( for the add entry per)ission is in the #usiness lo+ gic% $f the chec( fails, a ,rincipal'xception is thro'n and the add entry reHuest is a#orted%
if /Fpermission@hecker.has,ermission/ scope7roupId, Xcom.liferay.portlet.blogs.modelY, scope7roupId, YADD_EN !"#00 4 throw new ,rincipal'xception/0E 5 blogs'ntry9ocalService.add'ntry/...0E

&he ,ermission@hecker class has a )ethod called has,ermission/H0 that chec(s 'hether a user )a(ing a resource reHuest has the necessary access per+ )ission% $f the user is not signed in 2guest user3, it chec(s for guest per)issions% ;ther'ise, it chec(s for user per)issions% Let's do a Huic( revie' of the para+ )eters of this )ethod/
groupId/

represents the scope in 'hich the per)ission chec( is #eing perfor)ed% $n Liferay, the scopes can #e a specific co))unity, an or+ gani7ation, a personal site of a user, etc% &his is i)portant #ecause a user )ay #e allo'ed to add #log entries in a given co))unity #ut not in another% For resources that do not #elong to an scope li(e those )entioned, the value of this para)eter should #e 3% &here are several 'ays to o#tain the groupId of the current scope/ J,9 that uses the =theme.define%b)ects/> tag/ there is an i)plicit varia#le called scope7roupId% ?usiness logic class/ Fhen using the ,erviceConte1t pattern, it can #e o#tained using service@ontext.getScope7roupId/0% ;ther cases/ it can #e o#tained fro) the the)e display reHuest o#+ Iect/
:ebTeys."$'&'#2IS,9 J0E long scope7roupId ( theme2isplay.getScope7roupId/0

"heme2isplay theme2isplay ( /"heme2isplay0reDuest.get ttribute/

name/

&he na)e of the resource as specified in the CML file of the pre+ vious sections%
primTey/ &he pri)ary (ey of the resource% $n this

e1a)ple, since the re+ source doesn't e1ist as an entry in the data#ase 'e use the group$d again% $f 'e 'ere chec(ing for a per)ission on a given #log entry, 'e 'ould use the pri)ary (ey of that #log entry instead%
actionId/

&he na)e of the action as entered in the CML file% $t is a ,ecurity and 9er)issions

AB

Liferay *9$s and Fra)e'or(s co))on practice to create a helper class 'ith constants for all the ac+ tions defined, so that it's easier to search usages% $n the e1a)ples a#ove, 'e are assu)ing that there is a varia#le called perauto)atically creates a ,ermishas all the necessary infor)ation fro) the user and caches the security chec(s to ensure good perfor)ance% &here are several 'ays to o#tain this instance/
mission@hecker already availa#le% Liferay sion@hecker instance for every reHuest that

$n a J,9 that uses the =theme.define%b)ects/> tag/ there is an i)plicit varia#le called permission@hecker% Fhen using ,ervice?uilder, every service i)ple)entation class can ac+ cess the ,ermission@hecker instance #y using the )ethod get,ermission@hecker/0% ;ther cases/ it can #e o#tained fro) the the)e display reHuest o#Iect/
"heme2isplay theme2isplay ( /"heme2isplay0reDuest.get ttribute/ :ebTeys."$'&'#2IS,9 J0E ,ermission@hecker permission@hecker ( theme2isplay.get,ermission@hecker/0

Creating Helper Classes for Permission Checking


;ften, it is a good practice to create helper classes that encapsulate the use of per)issionChec(er and the na)es of the resources for an specific portlet% &his is specially useful 'hen there are co)ple1 parent4child relationships or if your per)ission logic calls for chec(ing )ultiple action types% ;logs,ermission is an e1a)ple of a per)ission helper class% ,ee ho' ;logs,ermission )ay #e used in a J,9%
=B if /;logs,ermission.contains/permission@hecker, scope7roupId, ctionTeys. 22#'!"8J00 4 // show add entry button 5 B>

<o', let's ta(e a loo( at ho' a ServiceImpl class ;logs'ntryServiceImpl uses the ;logs,ermission helper class% $n )ethod ;logs'ntryServiceImpl.add'ntry/...0, a call is )ade to chec( 'hether the inco)ing reHuest has per)is+ sion to add entry% &he chec( is done using helper class ;logs,ermission% $f the chec( fails, it thro's a ,rincipal'xception and the add entry reHuest a#orts%
public ;logs'ntry add'ntry/ String title, String description, String content, int display2ate&onth, int display2ate2ay, int display2ateJear, int display2ate$our, int display2ate&inute, boolean allow,ingbacks, boolean allow"rackbacks, StringRS trackbacks, boolean smallImage, String smallImageA89, <ile small<ile, Service@ontext service@ontext0

,ecurity and 9er)issions

AA

Liferay *9$s and Fra)e'or(s


throws ,ortal'xception, System'xception 4 ;logs,ermission.c$ec%/ get,ermission@hecker/0, service@ontext.getScope7roupId/0, ctionTeys.ADD_EN !"0E return blogs'ntry9ocalService.add'ntry/ getAserId/0, title, description, content, display2ate&onth, display2ate2ay, display2ateJear, display2ate$our, display2ate&inute, allow,ingbacks, allow"rackbacks, trackbacks, smallImage, smallImageA89, small<ile, service@ontext0E 5

<ote the para)eters passed into the check/...0 )ethod% *gain, the get,er)ethod is readily availa#le in all ServiceImpl classes% &he #logs entry $D is availa#le in the service@ontext indicating that the per)ission chec( is against the #logs portlet% ctionTeys. 22#'!"8J is a static ,tring to in+ dicate the action reHuiring the per)ission chec(% Li(e'ise, you are encouraged to use custo) portlet action (eys%
mission@hecker/0

LetYs revie' 'hat 'eYve Iust covered% $)ple)enting per)ission into your custo) portlet consists of four )ain steps% First step is to define any custo) re+ sources and actions% <e1t step is to i)ple)ent code to register 2or add3 any ne'ly created resources such as a ;logs'ntry o#Iect% &he third step is to provide an interface for the user to configure per)ission% Lastly, i)ple)ent code to chec( per)ission #efore returning resources or sho'ing custo) features% &'o )aIor resources are portlets and Java o#Iects% &here is not a lot that needs to #e done for the portlet resource to i)ple)ent the per)ission syste) since Liferay 9ortal has a lot of that 'or( done for you% .ou )ainly focus your efforts on any custo) Java o#Iects youYve #uilt% .ouYre no' 'ell eHuipped to i)ple)ent secur+ ity in your custo) Liferay portletsP

Asset Framework
&he asset fra)e'or( provides a set of functionalities that are co))on to several different content types% $t 'as initially created to #e a#le to add tags to #log entries, 'i(i pages, 'e# content, etc 'ithout having to rei)ple)ent this sa)e functionality over and over% ,ince then, it has gro'n to add )ore function+ alities and it has #een )ade possi#le to use the fra)e'or( for custo) applica+ tions even if they are i)ple)ented 'ithin a plugin% &he ter) asset is used as a generic 'ay to refer to any type of content re+ gardless of 'hether it's purely te1t, an e1ternal file, a -6L, an i)age, an record in an online #oo( li#rary, etc% Fro) no' on, 'henever the 'ord asset is used, thin( of it as a generic 'ay to refer to docu)ents, #log entries, #oo()ar(s, 'i(i pages, etc% :ere are the )ain functionalities that you 'ill #e a#le to reuse than(s to the asset fra)e'or(/ *ssociate tags to custo) content types 2ne' tags 'ill #e created auto+

"!!

*sset Fra)e'or(

Liferay *9$s and Fra)e'or(s )atically 'hen the author assigns the) to the content3% *ssociate categories to custo) content types 2authors 'ill only #e al+ lo'ed to select fro) predefined categories 'ithin several predefined voca#ularies3 Manage tags fro) the control panel 2including )erging tags3 Manage categories fro) the control panel 2including creating co)ple1 hierachies3% Keep trac( of the nu)#er of visuali7ations of an asset% 9u#lish your content using the *sset 9u#lisher portlet% *sset 9u#lisher is a#le to pu#lish dyna)ic lists of assets or )anually selected lists of assets% $t is also a#le to sho' a su))ary vie' of an asset and offer a lin( to the full vie' if desired% ?ecause of this it 'ill save you ti)e since for )any use cases it 'ill )a(e it unnecessary to develop custo) portlets for your custo) content types%

$f these functionalities see) useful for your case, then you )ight #e 'ondering, 'hat do $ have to do to #enefit fro) the)N &he follo'ing su#sections descri#e the steps involved in using the asset fra)e+ 'or(% &he first one is )andatory and consists on letting the fra)e'or( (no' 'henever one of your custo) content entries is added, updated or deleted% &he second part is optional #ut can save a lot of ti)e so )ost developers 'ill pro#+ a#ly )a(e use of it% $t consists on using a set of tagli#s to provide 'idgets that al+ lo' authors to enter tags and categories as 'ell as ho' to sho' the entered tags and categories along 'ith the content% &he rest of the sections are also optional #ut offer interesting functionalities such as ho' to allo' your custo) assets to #e pu#lished through the *sset 9u#lisher%

Adding, updating and deleting assets


Fhenever one of your custo) content is created you need to let the asset fra)e'or( (no'% Don't 'orry, it is si)ple% .ou Iust need to invo(e a )ethod of the asset fra)e'or(% Fhen invo(ing this )ethod you 'ill also let the fra)e'or( (no' a#out the tags and4or categories of the content that 'as Iust authored% *ll the )ethods that you 'ill need to invo(e are part of the *ssetEntryLoc+ al,ervice% $n particular you should access these )ethods using either the static )ethods of *ssetLocal,ervice-til or #y using an instance of the *ssetEntryLoc+ al,ervice inIected #y ,pring% &o )a(e this section si)pler 'e 'ill #e using the for)er, since it doesn't reHuire any special setup in your application% &he )ethod that you need to invo(e 'hen one of your custo) content has #een added or updated is the sa)e and is called update*sset% :ere is the full sig+ nature/
sset'ntry update'ntry/ long userId, long groupId, String class!ame, long class,T, String classAuid, longRS categoryIds, StringRS tag!ames, boolean visible, 2ate start2ate, 2ate end2ate,

*sset Fra)e'or(

"!"

Liferay *9$s and Fra)e'or(s


2ate publish2ate, 2ate expiration2ate, String mime"ype, String title, String description, String summary, String url, int height, int width, Integer priority, boolean sync0 throws ,ortal'xception, System'xception

Here is an e ample invocation to this method e tracted out from the blogs port! lets that comes bundled with "iferay#
asset'ntry9ocalService.update'ntry/ userId, entry.get7roupId/0, ;logs'ntry.class.get!ame/0, entry.get'ntryId/0, entry.getAuid/0, asset@ategoryIds, asset"ag!ames, visible, null, null, entry.get2isplay2ate/0, null, 3, @ontent"ypes."'Z"#$"&9, entry.get"itle/0, null, summary, null, 3, null, false0E

Here is a $uick summary of the most important parameters of this method# userId# is the identifier of the user who created the content groupId# identifies the scope in which the content has been created. If your content does not support scopes% you can just pass & as the value. className# identifies the type of asset. 'y convention we recommend that it is the name of the (ava class that represents your content type% but you can actually use any String you want as long as you are sure that it is uni$ue. classPK# identifies the specific content being created among any other of the same type. It is usually the primary key of the table where the custom content is stored. )he classUuid parameter can optionally be used to spe! cify a secondary identifier that is guaranteed to be uni$ue universally. Having this type of identifier is specially useful if your contents will be e ported and imported across separate portals. assetCategoryIds and assetTagNames# represent the categories and tags that have been selected by the author of the content. )he asset framework will sotre them for you. visible# specifies whether this content should be shown at all by *sset +ublisher. title, description and summary: are descriptive fields that will be used by the *sset +ublisher when displaying entries of your content type. publishDate and expirationDate: can be optionally specified to let *sset +ublisher know that it should not show the content before a given public! ation date of after a given e piration date. *ll other fields are optional and might not make sense in all cases. )he sync parameter should always be false unless you are doing something very advanced ,look at the code if you are really curious-.

"!

*sset Fra)e'or(

Liferay *9$s and Fra)e'or(s .hen one of your custom content is deleted you should also let the *sset /ramework know% to clean up the information stored and also to make sure that the *sset +ublisher doesn0t show any information for a content that has been deleted. )he signature of method to do this is#
void delete'ntry/ String class!ame, long class,T0 throws ,ortal'xception, System'xception

:ere is an e1a)ple invocation e1tracted again fro) the #logs portlet/


asset'ntry9ocalService.delete'ntry/ ;logs'ntry.class.get!ame/0, entry.get'ntryId/00E

Entering and displaying tags and categories


&he previous section sho'ed ho' you can let the asset fra)e'or( (no' a#out the tags and categories that have #een associated 'ith a given asset, #ut ho' does a content author specify such tags and categoriesN &he ans'er is that you can choose any )ethod that you prefer, #ut Liferay provides a set of J,9 tags that you can use to )a(e this tas( very easy% &he fol+ lo'ing tags can #e used 'ithin the for) you have created to create your type of content to allo' entering tags or selecting a predefined category/
=label>"ags=/label> =liferay-ui.asset-tags-selector class!ame(6=B( entry.get@lass/0.get!ame/0 B>6 class,T(6=B( entry.get,rimaryTey/0 B>6 /> =label>@ategories=/label> =liferay-ui.asset-categories-selector class!ame(6=B( entry.get@lass/0.get!ame/0 B>6 class,T(6=B( entry.get,rimaryTey/0 B>6 />

&hese t'o tagli#s 'ill create appropriate for) controls that allo' the user to enter any tag 2even if it doesn't e1ist3 or search and select one of the e1isting categories% Tip: If you are using Liferay's Allow Form taglibs, then creating a field to enter tags or categories is even simpler. You just need to use =aui.input name(6tags6 type(6asset"ags6 /> and =aui.input name(6categories6 type(6asset@ategories6 /> respectively.

;nce the tags and categories have #een entered you 'ill 'ant to sho' the) so)e'here along 'ith the content of the asset, there are another pair of tags that you can use to do so/ *sset Fra)e'or( "!5

Liferay *9$s and Fra)e'or(s


=label>"ags=/label> =liferay-ui.asset-tags-summary class!ame(6=B( entry.get@lass/0.get!ame/0 B>6 class,T(6=B( entry.get,rimaryTey/0 B>6 /> =label>@ategories=/label> =liferay-ui.asset-categories-summary class!ame(6=B( entry.get@lass/0.get!ame/0 B>6 class,T(6=B( entry.get,rimaryTey/0 B>6 />

$n #oth tags you can also use an optional para)eter called portlet-6L% Fhen specifying this para)eter each of the tags 'ill #e a lin( #uilt 'ith the provided -6L and adding a KtagL para)eter or a Kcategory$dL para)eter% &his is very use+ ful in order to provide support for tags navigation and categories navigation 'ithin your portlet% ?ut you 'ill need to ta(e care of i)ple)enting this func+ tionality yourself in the code of the portlet #y reading the values of those t'o para)eters and using the *ssetEntry,ervice to Huery the data#ase for entries #ased on the specified tag or category%

Publishing assets with Asset Publisher


;ne of the nice #enefits of using the asset fra)e'or( is the possi#ility of us+ ing the *sset 9u#lisher portlet, 'hich is part of the Liferay distri#ution, to pu#+ lish lists of your custo) asset types% &hese lists can #e dyna)ic 2for e1a)ple #ased on the tags or categories that the asset has3 or )anually selected #y an ad+ )inistrator% $n order to #e a#le to display your assets the *sset 9u#lisher needs to (no' ho' to access so)e )etadata of the) and also needs you to provide te)plates for the different type of vie's that it can display 2a#stract and full vie'3% .ou can provide all this infor)ation to the *sset 9u#lisher through a pair of classes that i)ple)ent the *sset6endererFactory interface and the *s+ set6enderer interface/ *sset6endererFactory/ this is the class that (no's ho' to retrieve spe+ cific assets fro) the persistent storage fro) the class9K 2that is usually the pri)ary (ey, #ut can #e anything you have chosen 'hen invo(ing the update*sset )ethod used to add or update the asset3% &his class should #e a#le to gra# the asset fro) a group$d 2that identifies an scope of data3 and a url&itle 2'hich is a title that can #e used in friendly -6Ls to refer uniHuele to the asset 'ithin a given scope3% Fi+ nally, it can also provide a -6L that the *sset 9u#lisher can use 'hen a user 'ants to add a ne' asset of your custo) type% &his -6L should point to your o'n portlet% &here are other less i)portant )ethods, #ut you can avoid i)ple)enting the) #y e1tending fro) ?ase*sset6endererFactory% E1tending fro) this class, instead of i)ple+ )enting the interface directly 'ill also )a(e your code )ore ro#ust if there are changes in the interface in future versions of Liferay, since the #ase i)ple)entation 'ill provide custo) i)ple)entations for *sset Fra)e'or(

"!E

Liferay *9$s and Fra)e'or(s the)% *sset6enderer/ this is the class that provides )etadata infor)ation a#out one specific asset and is also a#le to chec( for per)issions to edit or vie' it for the current user% $t is also reponsi#le for rendering the asset for the different te)plates 2a#stract, and full content3, #y for+ 'arding to an specific J,9% $t is also reco))ended that instead of i)+ ple)enting the interface directly, you e1tend fro) the ?ase*sset6enderer class, that provides 'ith nice defaults and )ore ro+ #ustness for )ethods that could #e added to the interface in the fu+ ture%

Let's seen an e1a)ple of these t'o classes% *gain 'e 'ill pic( Liferay's ?logs portlet% Lets start 'ith the i)ple)entation for the *sset6endererFactory/
public class ;logs'ntry sset8enderer<actory extends ;ase sset8enderer<actory 4 public static final String @9 SS#! &' ( ;logs'ntry.class.get!ame/0E public static final String "J,' ( 6blog6E public sset8enderer get sset8enderer/long class,T, int type0

throws ,ortal'xception, System'xception 4 ;logs'ntry entry ( ;logs'ntry9ocalServiceAtil.get'ntry/class,T0E return new ;logs'ntry sset8enderer/entry0E 5 public url"itle0 sset8enderer get sset8enderer/long groupId, String

throws ,ortal'xception, System'xception 4 ;logs'ntry entry ( ;logs'ntryServiceAtil.get'ntry/ groupId, url"itle0E return new ;logs'ntry sset8enderer/entry0E 5 public String get@lass!ame/0 4 return @9 SS#! &'E 5 public String get"ype/0 4 return "J,'E 5 public ,ortletA89 getA89 dd/ 9iferay,ortlet8eDuest liferay,ortlet8eDuest,

*sset Fra)e'or(

"!G

Liferay *9$s and Fra)e'or(s


9iferay,ortlet8esponse liferay,ortlet8esponse0 throws ,ortal'xception, System'xception 4 $ttpServlet8eDuest reDuest ( liferay,ortlet8eDuest.get$ttpServlet8eDuest/0E "heme2isplay theme2isplay ( /"heme2isplay0reDuest.get ttribute/ :ebTeys."$'&'#2IS,9 J0E if /F;logs,ermission.contains/ theme2isplay.get,ermission@hecker/0, 4 theme2isplay.getScope7roupId/0, ctionTeys. 22#'!"8J00

return nullE 5 ,ortletA89 portletA89 ( ,ortletA89<actoryAtil.create/ reDuest, ,ortletTeys.;9%7S, get@ontrol,anel,lid/theme2isplay0, ,ortlet8eDuest.8'!2'8#,$ S'0E portletA89.set,arameter/6struts#action6, 6/blogs/edit#entry60E return portletA89E 5 public boolean has,ermission/ ,ermission@hecker permission@hecker, long class,T, String actionId0 throws 'xception 4 return ;logs'ntry,ermission.contains/ permission@hecker, class,T, actionId0E 5 protected String getIcon,ath/"heme2isplay theme2isplay0 4 return theme2isplay.get,ath"hemeImages/0 N 6/blogs/blogs.png6E 5 5

*nd here is the *sset6enderer i)ple)entation/


public class ;logs'ntry sset8enderer extends ;ase sset8enderer 4 public ;logs'ntry sset8enderer/;logs'ntry entry0 4 #entry ( entryE 5

"!>

*sset Fra)e'or(

Liferay *9$s and Fra)e'or(s

public long get@lass,T/0 4 return #entry.get'ntryId/0E 5 public String get2iscussion,ath/0 4 if /,rops?alues.;9%7S#'!"8J#@%&&'!"S#'! ;9'20 4 return 6edit#entry#discussion6E 5 else 4 return nullE 5 5 public long get7roupId/0 4 return #entry.get7roupId/0E 5 public String getSummary/9ocale locale0 4 return $tmlAtil.strip$tml/#entry.get@ontent/00E 5 public String get"itle/9ocale locale0 4 return #entry.get"itle/0E 5 public ,ortletA89 getA89'dit/ 9iferay,ortlet8eDuest liferay,ortlet8eDuest, 9iferay,ortlet8esponse liferay,ortlet8esponse0 4 ,ortletA89 portletA89 ( liferay,ortlet8esponse.create8enderA89/ ,ortletTeys.;9%7S0E portletA89.set,arameter/6struts#action6, 6/blogs/edit#entry60E portletA89.set,arameter/ 6entryId6, String.value%f/#entry.get'ntryId/000E return portletA89E 5 public String getArl"itle/0 4 return #entry.getArl"itle/0E 5 public String getA89?iewIn@ontext/ 9iferay,ortlet8eDuest liferay,ortlet8eDuest, 9iferay,ortlet8esponse liferay,ortlet8esponse, String noSuch'ntry8edirect0 4

*sset Fra)e'or(

"!@

Liferay *9$s and Fra)e'or(s


"heme2isplay theme2isplay ( /"heme2isplay0liferay,ortlet8eDuest.get ttribute/ :ebTeys."$'&'#2IS,9 J0E return theme2isplay.get,ortalA89/0 N theme2isplay.get,ath&ain/0 6/blogs/find#entryInoSuch'ntry8edirect(6 N N 5 public long getAserId/0 4 return #entry.getAserId/0E 5 public String getAuid/0 4 return #entry.getAuid/0E 5 public boolean has'dit,ermission/,ermission@hecker permission@hecker0 4 return ;logs'ntry,ermission.contains/ permission@hecker, #entry, 5 public boolean has?iew,ermission/,ermission@hecker permission@hecker0 4 return ;logs'ntry,ermission.contains/ permission@hecker, #entry, 5 public boolean is,rintable/0 4 return trueE 5 public String render/ 8ender8eDuest render8eDuest, 8ender8esponse render8esponse, String template0 throws 'xception 4 if /template.eDuals/"'&,9 "'# ;S"8 @"0 [[ template.eDuals/"'&,9 "'#<A99#@%!"'!"00 4 render8eDuest.set ttribute/:ebTeys.;9%7S#'!"8J, #entry0E return 6/html/portlet/blogs/asset/6 N template N 6.)sp6E 5 else 4 ctionTeys.?I':0E ctionTeys.A,2 "'0E $ttpAtil.encodeA89/noSuch'ntry8edirect0 N 6GentryId(6 #entry.get'ntryId/0E

"!B

*sset Fra)e'or(

Liferay *9$s and Fra)e'or(s


return nullE 5 5 protected String getIcon,ath/"heme2isplay theme2isplay0 4 return theme2isplay.get,ath"hemeImages/0 N 6/blogs/blogs.png6E 5 private ;logs'ntry #entryE 5

<ote that in the render )ethod, there is a for'ard to a J,9 in the case of the a#stract and the full content te)plates% &he a#stract is not )andatory and if it is not provided, the *sset 9u#lisher 'ill sho' the title and the su))ary o#+ tained through the appropriate )ethods of the renderer% &he full content te)+ plate should al'ays #e provided% :ere is ho' it loo(s li(e for #logs entries/
=BC include file(6/html/portlet/blogs/init.)sp6 B> =B ;logs'ntry entry ( /;logs'ntry0reDuest.get ttribute/:ebTeys.;9%7S#'!"8J0E B> =B( entry.get@ontent/0 B> =liferay-ui.custom-attributes-available class!ame(6=B( ;logs'ntry.class.get!ame/0 B>6> =liferay-ui.custom-attribute-list class!ame(6=B( ;logs'ntry.class.get!ame/0 B>6 class,T(6=B( /entry F( null0 I entry.get'ntryId/0 . 3 B>6 editable(6=B( false B>6 label(6=B( true B>6 /> =/liferay-ui.custom-attributes-available>

&hat's a#out it% $t 'asn't that hard, rightN <o' you can start enIoying the #e+ nefits of the asset fra)e'or( in your custo) portlets%

Service Builder
,ervice ?uilder is a )odel+driven code generation tool #uilt #y Liferay to auto)ate the creation of interfaces and classes for data#ase persistence and a service layer% ,ervice ?uilder 'ill generate )ost of the co))on code needed to i)ple)ent find, create, update, and delete operations on the data#ase, allo'ing you to focus on the higher level aspects of service design% &he service layer generated #y ,ervice ?uilder, has an i)ple)entation class that is responsi#le to handle retrieving and storing data classes and adding the ,ervice ?uilder "!A

Liferay *9$s and Fra)e'or(s necessary #usiness logic around the)% &his layer can optionally #e co)posed of t'o layers, the local service and the re)ote service% &he local service contains the #usiness logic and accesses the persistence layer% $t can #e invo(ed #y client code running in the sa)e Java =irtual Machine% &he re)ote service usually ads a code to chec( security and is )eant to #e accessi#le fro) any'here over the $n + ternet or your local net'or(% ,ervice ?uilder auto)atically generates the code necessary to allo' access to the re)ote services using ,;*9, J,;< and Java 6M$%

Define the Model


&he first step in using ,ervice ?uilder is to define your )odel classes and their attri#utes in a service.xml file% For convenience, 'e 'ill define the service 'ithin the !&:greeting portlet, although it should #e placed inside a ne' port+ let% Create a file na)ed service.xml in portlets/my-greeting-portlet/docroot/:';-I!< inside the 9lugins ,DK and add the follo'ing content/
=Ixml version(6*.36I> =F2%@"J,' service-builder ,A;9I@ 6-//9iferay//2"2 Service ;uilder K.3.3//'!6 6http.//www.liferay.com/dtd/liferay-servicebuilder#K#3#3.dtd6> =service-builder package-path(6com.sample.portlet.library6> =namespace>9ibrary=/namespace> =entity name(6;ook6 local-service(6true6 remote-service(6true6> =F-- ,T fields --> =column name(6bookId6 type(6long6 primary(6true6 /> =F-- 7roup instance --> =column name(6groupId6 type(6long6 /> =F-udit fields -->

=column name(6companyId6 type(6long6 /> =column name(6userId6 type(6long6 /> =column name(6user!ame6 type(6String6 /> =column name(6create2ate6 type(62ate6 /> =column name(6modified2ate6 type(62ate6 /> =F-- %ther fields --> =column name(6title6 type(6String6 /> =/entity> =/service-builder>

Overview of service.xml
=service-builder package-path(6com.sample.portlet.li&rary6>

""!

,ervice ?uilder

Liferay *9$s and Fra)e'or(s &his specifies the pac(age path that the class 'ill generate to% $n this e1+ a)ple, classes 'ill generate to :';-I!</src/com/sample/portlet/library/
=namespace>Li&rary=/namespace>

&he na)espace ele)ent )ust #e a uniHue na)espace for this co)ponent% &a#le na)es 'ill #e prepended 'ith this na)epace%
=entity name(61ook6 local-service(6true6 remote-service(6false6>

&he entity na)e is the data#ase ta#le you 'ant to create%


=column name(6title6 type(6String6 />

Colu)ns specified in service.xml 'ill #e created in the data#ase 'ith a data type appropriate to the Java type% *ccessors 'ill #e auto)atically generated for these attri#utes in the )odel class% Tip: Always consider adding two long fields called groupId and companyId to your data models. These two fields will allow your portlet to support the multi-tenancy features of Liferay so that each community or organization (for each portal instance) can have its own independent data.

Generate the Service


;pen a ter)inal 'indo' in your and enter this co))and/
ant build-service portlets/my-greeting-portlet

directory

&he service has #een generated successfully 'hen you see K?-$LD ,-CCE,,+ F-L%L $n the ter)inal 'indo', you should see that a large nu)#er of files have #een generated% *n overvie' of these files is provided #elo'/ 9ersistence ?oo(9ersistence + #oo( persistence interface [generated ?oo(9ersistence$)pl + #oo( persistence [generated ?oo(-til + #oo( persistence util, instances ?oo(9ersistence$)pl [generated 1ook$ocalServiceI! l + local service i)ple)entation% &his is the only class 'ithin the local service that you 'ill #e a#le to )odify )anually% .our #usiness logic 'ill #e here% ?oo(Local,ervice + local service interface [generated ?oo(Local,ervice?ase$)pl + local service #ase [generated [a#+ stract ?oo(Local,ervice-til + local service util, instances ?oo(Local,er+ vice$)pl [generated ?oo(Local,erviceFrapper + local service 'rapper, 'raps ?oo(Loc+ """

Local ,ervice

,ervice ?uilder

Liferay *9$s and Fra)e'or(s al,ervice$)pl [generated 6e)ote ,ervice 1ookServiceI! l + re)ove service i)ple)entation% 9ut here the code that adds additional security chec(s and invo(es the local service% ?oo(,ervice + re)ote service interface [generated ?oo(,ervice?ase$)pl + re)ote service #ase [generated [a#stract ?oo(,ervice-til + re)ote service util, instances ?oo(,ervice$)pl [generated ?oo(,erviceFrapper + re)ote service 'rapper, 'raps ?oo(,er+ vice$)pl [generated ?oo(,ervice,oap + soap re)ote service, pro1ies ?oo(,ervice-til [generated ?oo(,oap + soap #oo( )odel, si)ilar to ?oo(Model$)pl, does not i)ple)ent ?oo( [generated ?oo(,ervice:ttp + http re)ote service, pro1ies ?oo(,ervice-til [generated ?oo(J,;<,eriali7er + Ison seriali7er, converts ?oo( to J,;< array [generated ?oo(Model + #oo( #ase )odel interface [generated ?oo(Model$)pl + #oo( #ase )odel [generated ?oo( + #oo( )odel interface [generated 1ookI! l + #oo( )odel i)ple)entation% .ou can use this class to add additional )ethods to your )odel other than the autogener+ ated field getters and setters% ?oo(Frapper + #oo( 'rapper, 'raps ?oo( [generated

Model

;ut of all of these classes only three can #e )anually )odified/ ?oo(Loc+ al,ervice$)pl, ?oo(,ervice$)pl and ?oo($)pl%

Write the Local Service Class


$n the file overvie' a#ove, you 'ill see that 1ook$ocalService is the inter+ face for the local service% $t contains the signatures of every )ethod in 1ook$oc: alService1aseI! l and 1ook$ocalServiceI! l% 1ook$ocalService1aseI! l contains a fe' auto)atically generated )ethods providing co))on functional+ ity% ,ince this class is generated, you should never )odify it, or your changes 'ill #e over'ritten the ne1t ti)e you run ,ervice ?uilder% $nstead, all custo) code should #e placed in 1ook$ocalServiceI! l%

""

,ervice ?uilder

Liferay *9$s and Fra)e'or(s ;pen the follo'ing file/


/docroot/:';-I!</src/com/sample/portlet/library/service/impl/;ook9ocalServiceImpl.)ava

Fe 'ill #e adding the data#ase interaction )ethods to this service layer class% *dd the follo'ing )ethod to the 1ook$ocalServiceI! l class/
public ;ook add;ook/long userId, String title0 throws ,ortal'xception, System'xception 4 Aser user ( AserAtil.find;y,rimaryTey/userId0E 2ate now ( new 2ate/0E long bookId ( @ounter9ocalServiceAtil.increment/;ook.class.get!ame/00E ;ook book ( book,ersistence.create/bookId0E book.set"itle/title0E book.set@ompanyId/user.get@ompanyId/00E book.setAserId/user.getAserId/00E book.setAser!ame/user.get<ull!ame/00E book.set@reate2ate/now0E book.set&odified2ate/now0E book.set"itle/title0E return book,ersistence.update/book0E 5

?efore you can use this ne' )ethod, you )ust add its signature to the 1ook$ocalService interface #y running service #uilder again% <avigate to the root folder of your portlet in the ter)inal and run/
ant build-service

,ervice ?uilder loo(s through 1ook$ocalServiceI! l and auto)atically copies the signatures of each )ethod into the interface% .ou can no' add a ne' #oo( to the data#ase #y )a(ing the follo'ing call
;ook9ocalServiceAtil.add;ook/userId, X new titleY0E

Built-In Liferay Services


$n addition to the services you create using ,ervice ?uilder, your portlets )ay also access a variety of services #uilt into Liferay% &hese include AserService, %rganiUationService, 7roupService, @ompanyService, ImageService, 9ayoutService, %rganiUationService, ,ermissionService, Aser7roupService, and 8oleService% For )ore infor)ation on these services, see Liferay in Action and Liferay's Javadocs%

Other frameworks
Liferay has a 'ide variety of fra)e'or(s that )a(e it )uch easier to devel+

;ther fra)e'or(s

""5

Liferay *9$s and Fra)e'or(s op co)ple1 functionalities for your o'n applications 'ith little effort% &hese fra)e'or(s have evolved fro) the applications #undled 'ith Liferay out of the #o1 so they have #een proven in the real 'orld, even in very high perfor)ance portals% &his chapter is a placeholder that provides a Huic( description to the )ain fra)e'or(s provided 'ith Liferay >% <ote that 'hat follo's is a 'or( in pro + gress since )ore sections 'ill #e added over ti)e and so)e of the current sec+ tions 'ill evolve into its o'n chapter as 'e add )ore infor)ation and detailed instructions on ho' to use the) over ti)e% File ,torage Fra)e'or(/ *llo's storing files using the #ac(end of the Docu)ent Li#rary% ?y using this fra)e'or( you 'on't have to 'orry yourself a#out clustering or #ac(ups since that 'ill already #e ta(en care of for the Docu)ent Li#rary itself% &his fra)e'or( is used, for e1+ a)ple, #y the 'i(i and the )essage #oards of Liferay to store attached files in pages and posts respectively% .ou can chec( the sourcecode of these t'o portlets for great real+life e1a)ples of ho' to use the fra)e+ 'or(% For(flo' Fra)e'or(/ *llo's adding For(flo' functionality to your o'n portlets% ;ne great #enefit of using this fra)e'or( is that you 'ill #e a#le to reuse all of the 'or(flo' )anage)ent -$s provided #y Liferay% *lso you 'ill #e a#le to a#stract your code fro) the specific 'or(flo' engine that 'ill #e used 2J?9M, Liferay Kaleo, Z3% Many Liferay portlets use this fra)e'or(% $f you 'ant a si)ple e1a)ple to learn ho' to use it, the #logs portlet is a good start% Co))ents Fra)e'or(/ *llo's adding co))ents easily in any portlet 'ithout any data#ase code% Many Liferay portlets use this functional+ ity, for e1a)ple the #logs portlet for the co))ents of each entry% Custo) fields/ * portlet that uses custo) fields 'ill allo' the end user to e1tend the fields of its data entries 'ith custo) ones defined #y the end user% &o see a list of data types in Liferay that support this func+ tionality Iust go to the Control 9anel M Custo) Fields% 6eport a#use/ *llo' end users to report that so)e infor)ation pu#+ lished in a page should not #e there% $nline per)issions Fra)e'or(/ *llo's enhancing your ,OL Hueries so that the data#ase ta(es care of chec(ing for vie' per)issions% &his is particularly useful 'hen doing Hueries for data entries that could res+ ult in a large nu)#er of ite)s 2and thus chec(ing of per)issions after+ 'ards 'ould #e very ineficient3 or 'hen you 'ant to i)ple)ent pagin+ ation 2'hich 'ould not 'or( fine if per)issions are chec(ed after+ 'ards and an ite) is re)oved3% &he Docu)ent Li#rary or the Message ?oards of Liferay are e1a)ples of portlets that use this functionality% ,erviceConte1t/ &he ,erviceConte1t o#Iect contains a set of fields that are co))on to )any different services% $t is used, for e1a)ple to carry tags, categories, per)issions infor)ation, Z $t is not a fra)e'or( in it+ self #ut rather a utility o#Iect that helps usage of the other fra)e+ ;ther fra)e'or(s

""E

Liferay *9$s and Fra)e'or(s 'or(s% Chec( in the near future for ne' editions of the Developer's Guide for e1ten+ ded infor)ation on each of these fra)e'or(s%

;ther fra)e'or(s

""G

9. RESOURCES FOR LIFERAY DEVELOPERS

&he follo'ing are useful reference resources for developers 'or(ing 'ith the Liferay 9latfor)/ Liferay specific resources/ 2hat is a ortal5 http/44'''%liferay%co)4products4'hat+is+a+portal Plat%or! 8avadocsC http/44docs%liferay%co)4portal4>%!4Iavadocs4 /e%erence docu!entation %or $i%era&3s E4$ %ilesC http/44docs%liferay%co)4portal4>%!4definitions4 /e%erence docu!entation %or $i%era&3s taglibsC http/44docs%liferay%co)4portal4>%!4tagli#s4 ,ources for version > 2use your liferay%co) account to access the)3/ http/44svn%liferay%co)4repos4pu#lic4portal4#ranches4>%!%>4 ,ources of the develop)ent version/ http/44svn%liferay%co)4#ro'se4portal Java G Javadocs/ http/44do'nload%oracle%co)4Iavase4"%G%!4docs4api4 JavaEE G Javadocs/ http/44do'nload%oracle%co)4Iavaee4G4api4 JavaEE ;vervie'/

6elated specifications and standards/

6esources for Liferay Developers http/44'''%oracle%co)4technet'or(4Iava4Iavaee4tech4in+ de1%ht)l 9ortlet ,pecification %! 2J,6+ B>3/ http/44Icp%org4en4Isr4detailNid\ B> Fe# ,ervices for 6e)ote 9ortlets 2F,693/ http/44'''%oasis+open%org4co))ittees4'srp4 Java Content 6epository 2J,6+"@!3/ http/44Icp%org4en4Isr4detailNid\"@! Java ,erver Faces "% 2J,6+ G 3/ http/44'''%Icp%org4en4Isr4detailNid\ G Java ,erver Faces %! 2J,6+5"E3/ http/44'''%Icp%org4en4Isr4detailNid\5"E ;pen,ocial/ http/44'''%opensocial%org4 ,ite)ap protocol/ http/44site)aps%org4 Fe#D*=/ http/44'e#dav%org4 ,;*9/ http/44'''%'5%org4&64 !!@46EC+soap" +part!+ !!@!E @4 :&ML G/ http/44ht)lG%org4 FC*G %!/ http/44'''%'5%org4F*$4intro4'cag !%php ,pring Fra)e'or(/ http/44'''%springsource%org4 :i#ernate/ http/44'''%hi#ernate%org4 ,truts "/ http/44struts%apache%org4"%14 Lucene/ http/44lucene%apache%org4 Ouart7/ http/44'''%Huart7+scheduler%org *lloy -$/ http/44alloy%liferay%co)4 .-$ 5/ http/44developer%yahoo%co)4yui454 IOuery/ http/44IHuery%co)4 $ceFaces/ http/44'''%icefaces%org4)ain4ho)e4 9ortletFaces/ http/44'''%portletfaces%org4 =aadin/ http/44vaadin%co)4ho)e

6elated and co))only used technologies/

""B

6esources for Liferay Developers

6esources for Liferay Developers ;penCava/ http/44'''%open1ava%org4'e#4guest4liferay *pache ant/ http/44ant%apache%org4 Maven/ http/44)aven%apache%org4 ,eleniu)/ http/44seleniu)hH%org4 &o)cat/ http/44to)cat%apache%org4 J?oss *pplication ,erver/ http/44'''%I#oss%org4

6esources for Liferay Developers

""A

10. CONCLUSIONS

Liferay 9ortal is a very fle1i#le platfor) that allo's creating a 'ide variety of portals and 'e#sites% $t is the developer through custo) applications and custo)i7a+ tions 'ho gives it the shape desired #y the end users of the portal% Liferay provides several tools 29lugins ,DK and Liferay $DE3 to ease this tas(% $t also provides the foundations and fra)e'or(s to either i)ple)ent co)pletely ne' applications 2port+ let plugins3 or custo)i7e the core functionalities and applications provided 'ith Liferay 2hoo( plugins and e1t plugins3% *s the official Developer's Guide for Liferay, this docu)ent has offered a descrip+ tion of each of the tools and fra)e'or(s that you as a developer can use to #uild the #ests portals out there% ;f course, 'hile this docu)ent is large, it is Iust the #egin+ ning, the )ore you learn, the )ore efficient you 'ill #e 'hile developing and the )ore interesting applications and custo)i7ations you 'ill create% :ere are so)e sug+ gestions to learn )ore after reading this guide/ 6ead the KLiferay in *ctionL #oo(% &his #oo(, 'ritten #y 6ich ,e7ov, Liferay's Kno'ledge Manager, provides a very e1tensive step #y step guide of Liferay's develop)ent technologies% -se Liferay's Co))unity Foru)s, not only to as( Huestions #ut also to to ans'er the)% .ou 'ill #e surprised ho' )uch you can learn 'hile trying to help others% 6ead the source% Liferay is ;pen ,ource, and you can leverage that to learn as )uch as you 'ant a#out it% Do'nload the code if you haven't done it yet and read it% Lin( it 'ithin your $DE so that you can enter Liferay's code 'hile de#ugging your o'n code% $t 'ill give you a great opportunity to learn as )uch as the greatest e1pert of Liferay in the 'orld% Go to the 'e#sites of the standards and li#raries that Liferay is #ased on and read their docu)entation% ,o)e e1a)ples are/ ,pring, :i#ernate, 9ortlet ,pecification, etc%

INDEX

114

AJAX.....................................................32, 43 css.....13, 23, 24, 26, 27, 39, 41, 42, 44-46, 60 Asset Publisher......................4, 101-104, 109 D auto deploy..........................................59, 66 Document Library...............................11, 114

backup.....................................................114 email...........................................................7 blog........15, 22, 66, 89, 90, 92-100, 102, 103, 105-109, 114 H blogs....15, 89, 90, 92-100, 102, 103, 105-109, Hibernate....................................69, 118, 121 114 hot deploy...........................................24, 39 bundle...17, 41, 42, 58, 60, 61, 66, 75, 84, 90, html......10, 15, 24, 25, 29, 39, 43, 46, 50, 51, 102, 114 59, 60, 63, 65, 90, 102, 107-109, 118

C
caching................................................13, 25 calendar.........................................91, 92, 97 categories...................4, 64, 89, 101-104, 114 clustering.................................................114 communities..................................21, 54, 59 Community. 7, 17, 52, 65, 92-96, 98, 111, 121

J
jackrabbit...................................................63 jar file..................................................22, 24 Javascript. 3, 10, 12, 13, 24, 26, 27, 39, 42, 46 jboss.............................................22, 66, 119 jcr..............................................................63

jsp...3, 14, 23-25, 27-29, 31-38, 49-53, 55, 57, content management system....................13 59, 60, 68, 96-99, 103, 105, 108, 109 Control Panel. .11, 12, 18, 59, 64, 94, 95, 101, " 5

JSR-168.......................................................89 57, 63, 89, 90 JSR-170.....................................................118 JSR-286......................................7, 24, 89, 118

R
RoleS...........................26, 59, 63, 89, 90, 113

K
Kaleo........................................................114

S
Scope...........12, 94, 96, 98-100, 102, 104, 106 Service Builder......4, 8, 57, 68, 109, 110, 112,

Language........................4, 54, 60, 61, 63, 97 113 Language.properties.........................4, 54, 97 Servlet...............................17, 29, 34, 51, 106 LayoutS..........................................3, 13, 113 shopping....................................................30 Liferay......................................................2, 7 sitemap....................................................118 Liferay Portal. 4, 6, 7, 9, 13, 17, 24-26, 49, 65, Spring............12, 21, 55, 62-64, 101, 118, 121 66, 69, 72, 73, 75-77, 81, 84, 100, 121 structure...3, 19, 23, 24, 27, 39-41, 50, 56, 82 liferay-display.xml....................23, 24, 63, 64 liferay-portlet.xml...23, 24, 26, 27, 30, 38, 45, tag.4, 14, 21, 24, 27-29, 32, 34-36, 42, 56, 57, 57, 63, 90 89, 94-104, 114, 117 logs........15, 63, 68, 89, 90, 92-100, 102, 103, template. 3, 13, 14, 27, 39, 41, 42, 44, 49, 64, 105-109, 114 69, 104, 105, 108, 109 look and feel.............3, 13, 39, 40, 42, 43, 46 Theme......3, 13, 19, 39-47, 49, 50, 64, 69, 83, lucene......................................................118 98, 99, 106, 108, 109

M
mail.............................................................7

tomcat.....4, 17-19, 22, 29, 42, 50, 58, 66, 73, 74, 77, 78, 81, 84, 119

Message Boards...........................39, 91, 114 U

N
navigation.........................30, 41, 46, 59, 104

upgrade..........................................41, 51, 68 user.............................................................7 user groups...............................................59 users...........................................................7

O P

OrganizationS....................19, 53, 54, 59, 113 V Velocity................................................13, 39 permissions......4, 8, 89, 91-98, 105, 113, 114 W

plugin...3, 4, 7, 9-15, 17-19, 21-26, 39-41, 49, 52, 55-62, 64, 66, 68, 69, 72, 79, 80, 82-85, WAR file......4, 9, 11-13, 22, 24, 53, 59, 62, 66 92, 95, 100, 110, 121 web content.......................................50, 100 Portal...........................................................7 WEB-INF..23, 24, 26, 38, 40, 43, 50-53, 56, 57, portal.properties...................3, 51, 52, 55, 95 59, 63, 64, 90, 110, 111, 113 Portlet......3, 4, 7, 9-14, 18, 19, 21-43, 45, 46, web.xml.....................................................23 49-52, 57, 59, 60, 62-64, 68, 69, 79, 81-83, webdav....................................................118 89-111, 113, 114, 118, 121 Weblogic..............................................22, 66 portlet.xml. .23, 24, 26, 27, 30, 31, 33, 38, 45, " E

WebSphere.....................................22, 65, 66 XML.....4, 11, 15, 22-24, 26, 27, 30-33, 38, 39, wiki.............................9, 42, 52, 65, 100, 114 43-46, 50, 52-54, 57, 62-64, 89, 90, 92, 94-98, 110, 111, 117 workflow..................................................114

Z
zip............................17, 18, 58, 61, 66, 70-72

" G

You might also like