You are on page 1of 40

ecmarchitect.

com
Alfresco Developer Series
Developing Custom Actions
2
nd
Edition
January, 2012
Jeff Potts
This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. To view a copy o this
license! visit http"##creativecommons.or$#licenses#by-sa#3.0# or send a letter to Creative Commons! %%% Castro Street!
Suite &00! 'ountain (iew! Caliornia! &%0%)! USA.
ecmarchitect.com
Alfresco Developer Series
Developing Custom Actions
2
nd
Edition
January, 2012
Jeff Potts
About the Second Edition
This tutorial was ori$inally written in *anuary o +00,. - think it was actually the irst Alresco tutorial
- wrote even thou$h - think o .Custom Content Types/ as the lo$ical place to start rom the
perspective o someone rampin$ up on the platorm.
The ori$inal version was very short0it ocused only on how to make a custom action coni$urable
within a rule in Alresco 12plorer.
The second edition $reatly e2pands on the irst by buildin$ on the SomeCo e2ample started in the
.Custom Content Types/ tutorial and addin$ a second action e2ample that sets a custom property
deined in the e2ample SomeCo model.
Similar to the second edition o .content types/! my main intent o writin$ this revision was to
illustrate how to use the action coni$uration new to Alresco % to wire the actions into the Alresco
Share user interace.
The old Alresco 12plorer instructions still e2ist. -3ve moved those to the Appendi2. They work ine in
Alresco %! so i you are stuck on 12plorer! but have up$raded to Alresco %! you3ll still ind it useul.
The new action-related e2tension points in Alresco % make it much! much easier to add shortcuts and
other usability improvements to Share with drastically less code than you3d need to do the same thin$
in older versions. Ater you read this tutorial! you3ll be able to add all sorts o cool thin$s to your
Alresco installation. - you do! - hope you consider packa$in$ them up as an A'4! puttin$ the source
somewhere public! and listin$ them on http"##addons.alresco.com.
As always! please let me know i you ound this helpul. Any and all eedback is welcome on my blo$
at http"##ecmarchitect.com.
5ave un6
*e
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e + o %0
ecmarchitect.com
Table of Contents
About the Second 1dition..................................................................................................................... +
-ntroduction........................................................................................................................................... 7
Setup.......................................................................................................................................................... 8
4art )" -mplementin$ an Action................................................................................................................. 8
9hat is an Action:................................................................................................................................ 8
12ample )" 'ove ;eplaced..............................................................................................................&
12ample +" Set 9eb <la$............................................................................................................... )0
-mplementin$ the 'ove ;eplaced Action...........................................................................................)0
Step )" 9rite the action e2ecuter class........................................................................................... ))
Step +" Coni$ure the action in Sprin$........................................................................................... )+
-mplementin$ the Set 9eb <la$ action............................................................................................... )3
Step )" 9rite the Set9eb<la$ action e2ecuter class.......................................................................)3
Step +" Coni$ure the action in Sprin$........................................................................................... )7
*ava versus Server-side *avaScript......................................................................................................)7
4art +" Coni$urin$ the Action3s <ront-1nd in Share............................................................................... )7
Coni$urin$ the ;eplaceable Aspect in Share..................................................................................... )8
Coni$urin$ the 'ove ;eplaced ;ule Action in Share.......................................................................),
Step )" Speciy the custom client-side component and set the action order...................................),
Step +" Add a reerence to the custom client-side *avaScript ile to the head................................ )=
Step 3" -mplement the custom client-side *avaScript component.................................................. )&
Coni$urin$ the Set 9eb <la$ U- Action in Share.............................................................................. +)
Step )" Create two new repository tier actions............................................................................... ++
Step +" Update share-coni$-custom.2ml with the action coni$uration........................................ +3
Step 3" Create icons and locali>e the strin$s.................................................................................. +%
<inishin$ Touches" 1valuators ? -ndicators....................................................................................... +7
Step )" @eclare a new evaluator in Sprin$ coni$.......................................................................... +7
Step +" Update the action coni$ in share-coni$-custom.2ml....................................................... +8
Step 3" Update the share-coni$-custom.2ml ile to show a document library indicator...............+,
@eploy ? Test.................................................................................................................................+,
Conclusion............................................................................................................................................... +&
9here to ind more inormation..........................................................................................................+&
About the Author................................................................................................................................. +&
Appendi2.................................................................................................................................................. 30
Coni$urin$ the ;eplaceable Aspect in 12plorer................................................................................ 30
Coni$urin$ the 'ove ;eplaced ;ule Action in 12plorer.................................................................. 30
Step )" Create an action handler class............................................................................................ 3)
Step +" Create a correspondin$ *S4 pa$e....................................................................................... 3)
Step 3" Locali>e the 'ove ;eplaced Action.................................................................................. 3+
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 3 o %0
ecmarchitect.com
Coni$urin$ the Set 9eb <la$ U- Action in 12plorer......................................................................... 3%
Step )" Create a *S<-mana$ed Aean...............................................................................................3%
Update web-client-coni$-custom.2ml with the new U- action.....................................................38
Locali>in$ the Set 9eb <la$ action................................................................................................ 3=
Coni$urin$ the 1valuator to Show#5ide the Set 9eb <la$ U- Action in 12plorer...........................3=
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e % o %0
ecmarchitect.com
Introduction
Alresco is a le2ible platorm or developin$ content mana$ement applications. Clients have several
options to consider when selectin$ a user interace approach. Alresco comes with two web clients that
can be used as-is or customi>ed. Alternatively! developers can create custom applications usin$ the
Content 'ana$ement -nteroperability Services BC'-SC A4-! web scripts! the web services A4- or the
oundation A4-.
'any times! the out-o-the-bo2 web client is suicient! even i it has to be customi>ed sli$htly to it
your reDuirements. This is particularly true when your reDuirements closely resemble the all-purpose
document mana$ement use case.
@ecidin$ whether to $o with the out-o-the-bo2 web client! a customi>ed web client! or buildin$ your
own user interace rom scratch reDuires careul thou$ht and analysis that is beyond the scope o this
document.
This article is the second in a series that covers Alresco rom a coni$uration and customi>ation
perspective. The irst article discussed how to create custom content types and then e2pose those to the
Alresco user interace. The ocus in this article is on developin$ custom actions and coni$urin$ the
user interace to show those custom actions.
-t is important to note that i you are lookin$ or Duick-and-dirty ways to operate a$ainst documents in
the repository! you may not need a custom action. <or e2ample! you could create some server-side
*avaScript that $ets called rom the .12ecute Script/ action. Er! you could run server-side *avaScript
usin$ the *avaScript Console add-on available rom Share 12tras Bsee .9here to ind more
inormation/ or a linkC. There are C'-S A4-s that allow you to perorm bulk operations rom the
command line.
Actions are useul when"
Fou want to deine one or more operations that can be e2ecuted repeatedly
Fou want to make it easy or end-users to invoke common operations! either by clickin$ a menu
item or by coni$urin$ a rule on a older that will e2ecute the operations automatically
Fou want to perorm one or more operations on a schedule Bwhich isn3t covered in this
documentC
4art ) o this document e2plains how to implement the .back-end/ piece o the action. The document
includes two dierent e2amples. Ene action! called .'ove ;eplaced/ will be used as a .;ule Action/.
The other action is called .Set 9eb <la$/ and it will be called rom menu items in the user interace.
4art + e2plains how to coni$ure the user interace to work with the custom actions. The irst edition o
this tutorial ocused on the Alresco 12plorer web client. This edition ocuses on the Alresco Share
web client. The Alresco 12plorer sections have been moved to the Appendi2 i you need them.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 7 o %0
ecmarchitect.com
Setup
Aeore $ettin$ too ar down the road! here are a couple o notes about my setup"
'ac ES G Lion )0.,.+
'ySHL 7.).80 B'acportsC
Tomcat 8.0.3+
*ava ).8.0I+&
Alresco %.0.c Community! 9A;-only distribution
Ether operatin$ systems! databases! application servers! and Alresco versions will work with the
e2amples in 4art )! but in 4art + - use some Share e2tension points that are new in Alresco %! so older
versions may not work with the Share coni$uration e2amples.
The code that accompanies this article is split into two 1clipse proJects0one or repository tier
coni$uration and customi>ation and the other or Share tier coni$uration and customi>ation. 1ach has
its own build script which copies the artiacts into the appropriate places within the e2ploded Alresco
and Share 9A;s. -n real lie! you3ll want to packa$e your customi>ations as A'4s or both the
repository and Share tiers.
The code is inclusive o the code rom the .Custom Content Types! +
nd
1dition/ tutorial with the
e2ception o the 9eb Services and C'-S e2amples. This e2ample uses the SomeCo content model
established in that tutorial. - you don3t understand how to e2tend Alresco3s content model with your
own or how to coni$ure custom models in the Share and 12plorer user interaces! read that tutorial
irst.
Part 1: Implementing an Action
Actions are very commonly used when implementin$ Alresco. This part o the tutorial e2plains what
actions are! sets up a couple o e2amples! then shows how actions are implemented in *ava.
What is an Action?
The term! .action/ is overloaded Duite heavily across the Alresco platorm Band application
development! in $eneralC. <or the purposes o this document! an action is a discrete! reusable unit o
work that can be perormed a$ainst an obJect in the repository! and can optionally be coni$ured at run-
time by the user. Some o the out-o-the-bo2 actions include thin$s like" Check-out! Check-in! Add
Aspect! ;emove Aspect! 'ove! Send 1mail! and Speciali>e Type.
Sometimes! the term .rule action/ is used to describe this type o action. That3s because actions are
reDuently used when coni$urin$ a rule on a older. <or e2ample! suppose that there is a reDuirement to
always create a 4KL version o L-<s checked in to a speciic older. This is easily done by creatin$ a
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 8 o %0
ecmarchitect.com
rule that watches or new or updated L-<s and then runs the .Transorm and Copy -ma$e/ action when
it inds an obJect that meets the criteria.
The screenshots below show the out-o-the-bo2 actions available when coni$urin$ a rule in Alresco.
@rawin$ ) is Alresco 12plorer and @rawin$ + is Alresco Share.
Aut actions aren3t limited to runnin$ as part o a rule. Actions can be called rom menu items in the user
interace Bboth 12plorer and ShareC. These are oten called .U- actions/ to distin$uish the actual menu
item! the U- action! rom the thin$ that actually does the work! the .rule action/ or simply! the .action/.
These screenshots show the .browse/ U- actions and the .details/ U- actions in Alresco 12plorer"
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e , o %0
Drawing 1: Actions in Explorer rule config
Drawing 2: Actions in Share rule config
ecmarchitect.com
Similarly! Alresco Share has U- actions available in the document library3s document list as well as the
document details pa$e"
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e = o %0
Drawing 3: Browse UI actions in Explorer
Drawing 4: Details UI
actions in Explorer
ecmarchitect.com
So actions can be invoked rom a rule and can be tri$$ered rom a menu item. Actions can also be
called rom code which means they can be invoked rom server-side *avaScript! worklows! web
scripts! or any other piece o code that can $et to the Action Service.
Aecause the same action can be invoked rom all o these places! actions are a powerul way to write
content operations once and then levera$e them in many places.
Example 1: Move Replaced
Usin$ actions and worklow to$ether can be an eective way to customi>e the web client or the needs
o the business. Consider SomeCo! the ictitious company introduced in the content types tutorial.
Suppose SomeCo wants to use Alresco to mana$e the policies and procedures or their entire
or$ani>ation. They need to be able to track when a new policy or procedure is published that
supersedes an older policy document.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e & o %0
Drawing 5: Browse UI
actions in Share
Drawing : Details UI
actions in Share
ecmarchitect.com
SomeCo uses three olders to keep track o the state o their policies" @rat! Approved! and Archived.
SomeCo uses Alresco3s Simple 9orklows to move policies rom older to older. 9hen someone
moves a policy into the Approved older! i that policy replaces an older policy! the older policy needs
to be automatically moved to the Archived older. Alresco has a .'ove/ action! but doesn3t have a
.'ove ;eplaced/ action. A new .'ove ;eplaced/ action can easily be created to accomplish this.
Example : Set !eb "lag
;ecall rom the irst tutorial that SomeCo publishes a subset o the documents in their repository to a
company portal. SomeCo uses a la$ on the obJect to keep track o which documents should be shown
on the portal. -n the irst tutorial! that la$ was set either by editin$ the ield in the user interace or by
runnin$ code. Kow it is time to make it a bit more user-riendly by providin$ menu items in the user
interace that can enable and disable the la$.
The rest o this document e2plains how to implement both o these actions includin$ the coni$uration
necessary to make them available rom the user interace.
Implementing the Move Replaced Action
Actions run a$ainst speciic nodes. -n this e2ample! the action needs to ind the documents that the
.actioned upon node/ replaces so they can be moved. -n order to do this! the action needs to know
where to move the old documents to and it needs to know how to ind the old documents. The irst part!
where to move the old documents! will be a parameter that $ets passed to the action. The second part
will levera$e a .replaces/ relationship.
A MreplacesM relationship is a pretty common reDuirement. -n act! Alresco already has a MreplaceableM
aspect in the out-o-the-bo2 content model. The .replaceable/ aspect deines an association called
.cm"replaces/. So! the out-o-the-bo2 content model already accommodates documents that replace
other documents. All that is needed is some coni$uration to e2pose this relationship to the user
interace.
The business lo$ic will reside in an action e2ecuter class. This will allow SomeCo end-users to call the
action rom a rule coni$ured on any older! without urther involvement rom the development team.
-mplementin$ the action3s business lo$ic involves two steps"
). 9ritin$ the action e2ecuter class
+. Coni$urin$ the action in Sprin$
Ence that3s done! the action can be called rom code usin$ the Action Service! or it can be wired in to
the user interace Bincludin$ rule coni$urationC! which is covered in 4art +.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )0 o %0
ecmarchitect.com
Step 1: !rite t#e action executer class
At its most basic! an action consists o an Action 12ecuter class and its associated Sprin$ bean
coni$uration. -mplementin$ an action involves e2tendin$ Action12ecuterAbstractAase and then
implementin$ the e2ecute-mpl method. Aeore startin$! thou$h! think about similar code that mi$ht
already e2ist within Alresco that mi$ht be a $ood startin$ point or the new action. Alresco is open
source--it would be a shame to i$nore that valuable resource. 4lus! ollowin$ the same patterns to
implement this customi>ation will make it easier or someone to support and makes it easier to share
our code with others or even to contribute the code back to the Alresco community proJect.
The new action is doin$ a move! so the e2istin$ 'ove action is a $ood place to start. -n act! the only
dierence between the 'ove action and the custom 'ove ;eplaced action is that the node bein$
moved isn3t the current node--it3s the node on the tar$et end o a MreplacesM association.
Alresco3s e2ecuter class or the 'ove action is called
or$.alresco.repo.action.e2ecuter.'oveAction12ecuter. - you have the Alresco source you can ind it
in the repository proJect. -3ll copy it into my own repository proJect and call it
'ove;eplacedAction12ecuter. The e2ecute-mpl method is where the move lo$ic is handled. -t looks
like this"
public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef)
{
NodeRef destinationParent =
(NodeRef)ruleAction.etParameter!alue(PARA"#$%&'INA'I(N#)(*$%R)+
tr,
{
file)older&ervice.move(actionedUponNodeRef, destinationParent, null)+
-
catc. ()ileNot)ound%xception e)
{
// $o not.in
-
-
!isting 1: Alfresco"s out#of#the#$ox action executer for %o&e
The code simply $rabs the parameter value or the destination older and then calls the
<ile<olderService to do the move. This is a $ood start or 'ove ;eplaced. All - need to do is modiy
the e2ecute-mpl method to ind the nodes related to the current node by a MreplacesM association! and
then or each result! set up and perorm a move.
public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef) {
// et t.e replaces associations for t.is node
*ist0AssociationRef1 assocRefs =
node&ervice.et'aretAssocs(actionedUponNodeRef, ((2NamePattern)
2Name.create2Name(Namespace&ervice.3(N'%N'#"($%*#4#5#URI, 6replaces6)) )+
// if t.ere are none, return
if (assocRefs.is%mpt,()) {
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )) o %0
ecmarchitect.com
// no 7or8 to do, return
return+
- else {
NodeRef destinationParent =
(NodeRef)ruleAction.etParameter!alue(PARA"#$%&'INA'I(N#)(*$%R)+
for (AssociationRef assocNode 9 assocRefs) {
// create a noderef for t.e replaces association
NodeRef taretNodeRef = assocNode.et'aretRef()+
// if t.e node exists
if (t.is.node&ervice.exists(taretNodeRef) == true) {
tr, {
file)older&ervice.move(taretNodeRef, destinationParent,
null)+
- catc. ()ileNot)ound%xception e) {
// $o not.in
-
-
- // next assocNode
- // end if is%mpt,
-
!isting 2: 'he custo( action executer for %o&e )eplace*
The only other chan$e needed is to chan$e the value o the constant KA'1 rom MmoveM to Mmove-
replacedM. BThrou$hout this document -3ll only include relevant pieces o these classes0check the
source that accompanies this article or code that actually compilesC.
Step : Configure t#e action in Spring
-n the content types tutorial! you learned that Sprin$ bean coni$urations $o in iles that end with
.conte2t.2ml/. Those iles reside in the .e2tension/ directory to keep them separate rom the rest o the
Alresco web application. <or this e2ample! - created a ile called .someco-action-conte2t.2ml/ and
placed it in #coni$#alresco#e2tension. -t contains the ollowin$"
0:xml version=;4.5; encodin=;U')<=;:1
0>$(3'?P% beans PU@*I3 ;<//&PRINA//$'$ @%AN//%N;
;.ttp9//777.sprinframe7or8.or/dtd/sprin<beans.dtd;1
0beans1
0bean id=6move<replaced6
class=6com.someco.action.executer."oveReplacedAction%xecuter6 parent=6action<
executer61
0propert, name=6file)older&ervice61
0ref bean=6)ile)older&ervice6 /1
0/propert,1
0propert, name=6node&ervice61
0ref bean=6Node&ervice6 /1
0/propert,1
0/bean1
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )+ o %0
ecmarchitect.com
0/beans1
!isting 3: Spring configuration for %o&e )eplace*
That3s all there is to it. Fou could compile the 'ove;eplacedAction12ecuter class! *A; it up! and
deploy it to Alresco3s 91A--K<#lib. The Sprin$ conte2t ile $oes in 91A-
-K<#classes#alresco#e2tension. -n act! the Ant build ile that accompanies this code does Just that.
Ence in place! the action can be invoked rom code. That3s obviously not $oin$ to be useul or end
users! thou$h. Aeore wirin$ the action into the user interace! let3s look at another Action 12ecuter
e2ample.
Implementing the Set Web Flag action
This action will be used to set the la$ on content which should be shown in the SomeCo portal. ;ecall
rom the content types tutorial that the property is a boolean named .sc"isActive/ which is deined as
part o an aspect named .sc"webable/. Also in that aspect is a date property named .sc"published/ that
keeps track o when the content was last published to the portal.
The Set 9eb <la$ action! then! needs to set the .sc"isActive/ la$. The value to set it to Btrue or alseC
can be passed in as a parameter to the action. 9hen the la$ is set to true! the action should set the
.sc"published/ property with the current date.
This action could be called rom a rule! but SomeCo intends to coni$ure a U- action in the user
interace to allow end-users the ability to enable or disable a piece o content or display on the portal
with a sin$le click.
*ust like in the 'ove ;eplaced e2ample! the steps are"
). 9rite the action e2ecuter class
+. Coni$ure the action in Sprin$
Then! the action will be ready to use.
Step 1: !rite t#e Set!eb"lag action executer class
Like the 'ove;eplacedAction! this action e2tends Action12ecuterAbstractAase. The action takes a
parameter that speciies the value or the .sc"isActive/ la$. Actions declare parameters by overridin$
the add4arameter@einitions method"
B(verride
protected void addParameter$efinitions(*ist0Parameter$efinition1 param*ist) {
param*ist.add(
ne7 Parameter$efinitionImpl(
PARA"#A3'I!%,
$ata',pe$efinition.@((*%AN,
false,
etParam$ispla,*abel(PARA"#A3'I!%)))+
-
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )3 o %0
ecmarchitect.com
!isting 4: Declaring a para(eter for an action
The constructor or the 4arameter@einition-mpl takes the name o the parameter! the parameter3s data
type! whether or not the parameter is mandatory! and a label. - the custom action had additional
parameters this method would have one paramList.add call or each parameter.
The ne2t step is to create the action3s lo$ic in the e2ecute-mpl method"
B(verride
protected void executeImpl(Action action, NodeRef actionedUponNodeRef) {
@oolean active)la = (@oolean)action.etParameter!alue(PARA"#A3'I!%)+
if (active)la == null) active)la = true+ // default
// set t.e sc9isActive propert, to true
"ap02Name, &erialiCable1 properties =
node&ervice.etProperties(actionedUponNodeRef)+
properties.put(
2Name.create2Name(&ome3o"odel.NA"%&PA3%#&("%3(#3(N'%N'#"($%*,
&ome3o"odel.PR(P#I&#A3'I!%), active)la)+
if (active)la) {
// set t.e sc9publis.ed propert, to no7
properties.put(
2Name.create2Name(&ome3o"odel.NA"%&PA3%#&("%3(#3(N'%N'#"($%*,
&ome3o"odel.PR(P#PU@*I&D%$), ne7 $ate())+
-
// if t.e aspect .as alread, been added, set t.e properties
if (node&ervice..asAspect(actionedUponNodeRef,
2Name.create2Name(
&ome3o"odel.NA"%&PA3%#&("%3(#3(N'%N'#"($%*,
&ome3o"odel.A&P%3'#&3#E%@A@*%))) {
node&ervice.setProperties(actionedUponNodeRef, properties)+
- else {
// ot.er7ise, add t.e aspect and set t.e properties
node&ervice.addAspect(actionedUponNodeRef,
2name.create2Name(
&ome3o"odel.NA"%&PA3%#&("%3(#3(N'%N'#"($%*,
&ome3o"odel.A&P%3'#&3#E%@A@*%), properties)+
-
-
!isting 5: Action executer for Set +e$ ,lag
The lo$ic should be pretty easy to ollow. The code $rabs the value o the active parameter. Then! it
sets up a map to hold properties. - the active la$ is bein$ set to true! the date property is added to the
map. The last part o the method Just checks to see whether the aspect needs to be added or not. - so!
the aspect can be added and the properties set in a sin$le call.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )% o %0
ecmarchitect.com
Step : Configure t#e action in Spring
The Sprin$ coni$uration or this action $oes in the same conte2t ile as the pervious action"
0bean id=6set<7eb<fla6 class=6com.someco.action.executer.&etEeb)la6
parent=6action<executer61
0propert, name=6node&ervice61
0ref bean=6Node&ervice6 /1
0/propert,1
0/bean1
!isting : Spring configuration for Set +e$ ,lag
This action is now ready to be wired in to the user interace. That3s covered in 4art +.
Java versus Server-side JavaScript
A Duick side-note beore movin$ on to the ront-end" The action e2ecuter e2amples shown in 4art )
were both implemented in *ava. 5owever! action e2ecuters can also be implemented usin$ server-side
*avaScript. The steps are the same" write the lo$ic! then coni$ure it throu$h Sprin$. This is an
attractive option or teams lackin$ in *ava skills. The tradeo is that the *avaScript A4- does not have
)00N o the eature set o the Alresco *ava A4-. Fou may also see a perormance dierence with the
*avaScript A4-! which essentially wraps the lower-level *ava A4-.
Part : Configuring t#e Action$s "ront%End in S#are
-n 4art ) o this document you learned how to create an Action 12ecuter class. The result was an action
that could be called rom code. Aut both actions need to be invoked by end-users. -n the case o the
'ove ;eplaced action! an end-user will coni$ure a rule that will invoke the action. 9hen the end-user
coni$ures the action! they need to speciy the directory to send the replaced documents to. That means
the user interace needs to know how to let the end user pick a tar$et older.
The Set 9eb <la$ action $ives end-users the ability to set the active la$ and the publish date with a
sin$le click o a menu item. So the user interace needs to know where to show that menu item and
how to invoke the Set9eb<la$ action in the repository.
The speciic steps to coni$ure the user interace or these two actions depend on the web client bein$
used. Alresco 12plorer used to be the only choice. Alresco Share is usually the preerred web client
these days. Alresco % added some e2tensibility eatures that make it much easier to coni$ure actions
in Share than it used to be. So -3ll use Share and i you need to see how to do the e2act same thin$ in
12plorer! check the Appendi2.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )7 o %0
ecmarchitect.com
Coniguring the Replaceable Aspect in Share
Alresco3s out-o-the-bo2 content model already deines an association called .cm"replaces/ as part o
the .cm"replaceable/ aspect. Aut neither the aspect nor the association are coni$ured to be displayed in
the Share user interace. That3s easy to i2.
;ecall rom the content types tutorial that the Share user interace coni$uration resides in a ile called
.share-coni$-custom.2ml/. The .cm"replaceable/ aspect can be added to the list o aspects a user can
see! like this"
0visible1
0aspect name=6sc97ebable6 /1
0aspect name=6sc9productRelated6 /1
0aspect name=6cm9replaceable6 /1
0/visible1
!isting -: A**ing the replacea$le aspect to the list of &isi$le aspects
Ke2t! the .cm"replaces/ association needs to show up when editin$ properties. -n this e2ample!
SomeCo will use instances o .cm"content/ or policies! but this would work the same way i a speciic
content type! like .sc"hr4olicy/! were used instead. So -3ve copied the orm coni$uration or
.cm"content/ rom the out-o-the-bo2 orm coni$uration into .share-coni$-custom.2ml/. *ust like in
the content types tutorial! the association is coni$ured by addin$ children to the .ield visibility/ and
.appearance/ elements! like this"
0><< cm9eorap.ic aspect <<1
0s.o7 id=6cm9latitude6 /1
0s.o7 id=6cm9lonitude6 /1

<!-- cm:replaceable -->
<show id="cm:replaces" />
0/field<visibilit,1
!isting .: /onfiguring the c(:replaces association
and this"
0field id=6cm9sentdate6 read<onl,=6true6 /1
0field id=6cm9subFectline6 read<onl,=6true6 /1
<field id="cm:replaces" label-id="assoc.cm_replaces"/>
0/appearance1
!isting 0: /onfiguring the c(:replaces association
The last step in e2posin$ the .cm"replaceable/ aspect and .cm"replaces/ association is locali>in$ the
labels. The web-e2tension#messa$es#sc'odel.properties ile already e2ists! so add the ollowin$"
Gcm9replaceable
aspect.cm#replaceable=Replaceable
assoc.cm#replaces=Replaces
!isting 11: !ocali2ing the replacea$le aspect
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )8 o %0
ecmarchitect.com
The ne2t step is to coni$ure the 'ove ;eplaced ;ule Action in Share.
Coniguring the Move Replaced Rule Action in Share
Share is pretty smart. - you deploy the 'ove ;eplaced action as-is it will automatically $et added to
the list o actions users can select when coni$urin$ a rule. So or simple actions! you won3t have to do
anythin$ urther. Aut in this e2ample! the action takes an ar$ument. Ay deault! Share will try to render
a plain te2t ield or the ar$ument which mi$ht work in some cases. Aut this action takes a node
reerence as an ar$ument and makin$ an end-user provide a node reerence or the tar$et older would
be a very bad thin$. -nstead! Share needs to render a older picker dialo$ or the tar$et older ar$ument.
Luckily! Alresco has already developed such a dialo$0Share Just has to be told to use it.
-n Alresco %! a lot o work has been done to make customi>in$ and e2tendin$ the user interace easier.
Unortunately! at the moment! $ettin$ a older picker to show up or this action takes a bit more work
than it ou$ht to. 'y $uess is that this will $et resolved in the uture. Until then! here is what is
involved"
). Everride the rule coni$ action web script to point to a custom client-side component and to set
the order the action appears in the action list.
+. Everride the rule details and rule edit web script to include a .script/ reerence in the .head/
section o the pa$e that points to the client-side *avaScript where the custom client-side
component lives.
3. 9rite the custom client-side component.
-t looks like a pain! but once you i$ure it out it isn3t too bad. And it is a lot easier than it used to be i
that makes you eel any better. Let3s $o throu$h the steps.
Step 1: Specif& t#e custom client%side component and set t#e action order
-n Alresco %! a lot o the action coni$uration has been pulled into share-orm-coni$-custom.2ml. Aut
rule coni$ still lives in the rule coni$ web script. This isn3t a bi$ deal0it is easy to override one or
more iles that make up a web script. -n this case! copy the rule-coni$-action.$et.coni$.2ml ile rom
OTE'CATI5E'1#webapps#share#91A--K<#classes#alresco#site-
webscripts#or$#alresco#components#rules#coni$ into your own proJect. <or e2ample! in the code that
accompanies this article! - copied the ile into coni$#alresco#web-e2tension#site-
webscripts#or$#alresco#components#rules#coni$.
The irst chan$e is to speciy a custom client-side *avaScript component"
0rule<confi t,pe=6action61
<component>SomeCo.RleConfi!"ctionCstom</component>
0confi<definitions 7ebscript=6/api/actiondefinitions61
!isting 11: /onfiguring Share to use a custo( client#si*e co(ponent for rule config
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e ), o %0
ecmarchitect.com
This will be a new client-side *avaScript component that will $et created shortly.
Ke2t! the action $ets arran$ed in the list o actions. -n this case! it makes sense to see it in the list ri$ht
ater .'ove/"
0menu1
0roup1
0item id=6select6/1
0/roup1
0roup1
0action name=6script6/1
0/roup1
0roup1
0action name=6cop,6/1
0action name=6move6/1
<action name="mo#e-replaced"/>
0/roup1
!isting 12: 3lacing the %o&e )eplace* action in the rule action list
<inally! the action $ets bound with a client-side *avaScript unction"
0action name=6cop,613op,0/action1
0action name=6move61"ove0/action1
<action name="mo#e-replaced">$o#eReplaced</action>
0action name=6simple<7or8flo761&impleEor8flo70/action1
!isting 13: Specif4ing which client#si*e han*ler to use for %o&e )eplace*
Step : Add a reference to t#e custom client%side 'avaScript file to t#e
#ead
The client-side *avaScript ile where the custom client-side component resides needs to be pulled in to
the .PheadQ/ section o the pa$e so the browser knows about it. 9eb scripts that end with .head.tl/
are used or this purpose. <or rules! there are two web scripts that will need to reer to the custom
client-side *avaScript" .rule details/ and .rule edit/. So the rule-details.$et.head.tl and rule-
edit.$et.head.tl iles are copied rom OTE'CATI5E'1#webapps#share#91A-
-K<#classes#alresco#site-webscripts#or$#alresco#components#rules. The modiications to both are
identical and are as ollows"
0Blin8 rel=6st,les.eet6 t,pe=6text/css6 .ref=6H
{pae.url.context-/res/components/rules/rule<details.css6 /1
0Bscript t,pe=6text/Favascript6 src=6H{pae.url.context-/res/components/rules/rule<
details.Fs610/Bscript1
<!--Cstom %a#ascript file inclde for detail mode -->
<&script t'pe="te(t/%a#ascript" src=")
*pa!e.rl.conte(t+/someco/components/rles/confi!/rle-confi!-action-
cstom.%s"></&script>
!isting 14: A**ing the client#si*e 5a&aScript reference to hea*
Ekay! at this point! the rule orm will be lookin$ or a custom client-side *avaScript component called
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )= o %0
ecmarchitect.com
SomeCo.;uleConi$ActionCustom! the action will show up in the ri$ht place! and the pa$e3s .PheadQ/
element will include a reerence to the custom client-side *avaScript ile where the component will
reside. -t3s time to implement the client-side *avaScript.
Step (: Implement t#e custom client%side 'avaScript component
The <ree'arker iles have been modiied to include a reerence to a ile called rule-coni$-action-
custom.Js. Ay convention! - include client-side *avaScript in my 1clipse proJect under
.src#web#someco/. Alresco has their rule-related client-side *avaScript under
.components#rules#coni$/ so - used the same older structure.
The irst thin$ the rule-coni$-action-custom.Js ile does is declare a SomeCo namespace. -t is
important that you namespace everythin$ in Alresco to avoid collisions with Alresco3s code or other
add-ons you mi$ht install.
if (t,peof &ome3o == 6undefined6 II >&ome3o)
{
var &ome3o = {-+
-
!isting 15: Declaring a So(e/o na(espace in client#si*e 5a&aScript
Ke2t! comes the constructor or the component B-3ve let out some borin$ stu! check the source or the
ull listin$C"
&ome3o.Rule3onfiAction3ustom = function(.tmlId)
{
&ome3o.Rule3onfiAction3ustom.superclass.constructor.call(t.is, .tmlId)+
// Re<reister 7it. our o7n name
t.is.name = 6&ome3o.Rule3onfiAction3ustom6+
Alfresco.util.3omponent"anaer.rereister(t.is)+
// Instance variables
t.is.customisations = ?AD((.lan.mere(t.is.customisations,
&ome3o.Rule3onfiAction3ustom.superclass.customisations)+
t.is.renderers = ?AD((.lan.mere(t.is.renderers,
&ome3o.Rule3onfiAction3ustom.superclass.renderers)+

return t.is+
-+
!isting 1: Snippet of client#si*e 5a&aScript showing the )ule/onfigAction/usto( constructor
- this is your irst oray into the world o obJect-oriented client-side *avaScript! rela2. 9hat! you
thou$ht Just because .*ava/ and .*avaScript/ have a word in common that obJect inheritance would
work the same way: 5ow literal o you6 Aasically! what3s $oin$ on here is that the constructor is
callin$ its superclass constructor! then it is re$isterin$ itsel with the Alresco component mana$er. The
FU- mer$e calls provide a way to avoid re-typin$ a bunch o code that e2ists in the parent class.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e )& o %0
ecmarchitect.com
The inal bit is where the e2tend actually happens! and the 'ove;eplaced handler is deined"
?AD((.extend(&ome3o.Rule3onfiAction3ustom, Alfresco.Rule3onfiAction,
{
/JJ
J 3U&'("I&A'I(N&
J/
customisations9
{
"oveReplaced9
{
text9 function(confi$ef, rule3onfi, confi%l)
{
// $ispla, as pat.
t.is.#etParam$ef(confi$ef, 6destination<folder6).#t,pe =
6pat.6+
return confi$ef+
-,
edit9 function(confi$ef, rule3onfi, confi%l)
{
// Dide all parameters since 7e are usin a cusotm ui but set
default values
t.is.#.ideParameters(confi$ef.parameter$efinitions)+
// "a8e parameter renderer create a 6$estination6 button t.at
displa,s an destination folder bro7ser
confi$ef.parameter$efinitions.pus.({
t,pe9 6arca9destination<dialo<button6,
displa,*abel9 t.is.ms(6label.to6),
#button*abel9 t.is.ms(6button.select<folder6),
#destinationParam9 6destination<folder6
-)+
return confi$ef+
-
-,
-,
-)+
!isting 1-: Defining the %o&e)eplace* client#si*e han*ler
This part is a copy o the out-o-the-bo2 handler or 'ove with the obJect renamed to 'ove;eplaced.
The 'ove;eplaced obJect has two methods" te2t and edit. Te2t is what is displayed or the component
in read mode. 1dit is or edit mode. The edit method is what is responsible or $eneratin$ the button
that invokes the older picker. -n this case! edit levera$es an e2istin$ renderer called .arca"destination-
dialo$-button/ that is deined in the superclass. - you needed to produce markup or a parameter or
which Alresco doesn3t already have a renderer! you would add the appropriate code to the renderers
obJect.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e +0 o %0
ecmarchitect.com
9ith this inal step in place! end-users can coni$ure a rule that invokes the 'ove ;eplaced action. The
rule editor will use the custom handler or the action so that a older picker dialo$ is used to select the
tar$et older.
Fou can see this happenin$ in the screenshot below. Fou can see the dialo$ that $ets launched when the
Select button is clicked as well as the little older icon and older path that are rendered once a selection
is made.
Coniguring the Set Web Flag !I Action in Share
Kow it is time to shit ocus rom rule actions to U- actions. SomeCo wants end-users to be able to
click an item in the menu that either enables or disables the web la$. Alresco % has a ramework that
allows you to easily add new U- actions to the menu. Fou can coni$ure"
U- actions that call a web pa$e Be2ternal or within ShareC!
U- actions that invoke rule actions on the repository tier that take no parameters!
U- actions that invoke rule actions on the repository tier that launch a dialo$ to $ather
parameters beore passin$ those parameters to an action on the repository tier!
U- actions that call arbitrary client-side *avaScript action handlers.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e +) o %0
Drawing -: /onfiguring the %o&e )eplace* action in Share
ecmarchitect.com
;ecall that the Set 9eb <la$ action takes one parameter0the value o the active la$. - could use the
action ramework out-o-the-bo2 to invoke a dialo$ that lets the user set the action la$ to true or alse
and then call the set web la$ action. Aut that doesn3t meet the sin$le-click reDuirement! and a orm is
overkill to $rab one boolean value.
- you look in the list above! you3ll see there isn3t an option to hardcode arbitrary parameters in the
action coni$ when the action is called. So we3re orced to either call a custom client-side *avaScript
action handler or add new actions to the repository tier that don3t take parameters. There3s no .ri$ht/
answer here0it3s Just a matter o where you want to write the code. At some point! Alresco will
probably enhance the ramework to meet this use case. Until then! or this e2ample! -3m $oin$ to $o the
.no parameter/ route! which means -3ll have to add two new actions on the repository tier that don3t
reDuire parameters to be passed in.
So! the steps to ollow or this e2ample are"
). Create two new repository tier actions that take no parameters
+. Update share-coni$-custom.2ml with the action coni$uration
3. Create icons and locali>e the strin$s
Step 1: Create t)o ne) repositor& tier actions
Fou created action e2ecuter classes in 4art ) o this tutorial so this is nothin$ new. There needs to be
one action or enablin$ the active la$ and one or disablin$ it and neither should take a parameter. Ay
sub-classin$ the e2istin$ Set9eb<la$ action! code can be kept to a minimum. 5ere3s the
1nable9eb<la$ action e2ecuter in its entirety"
public class %nableEeb)la extends &etEeb)la {
B(verride
protected void executeImpl(Action action, NodeRef actionedUponNodeRef) {
action.setParameter!alue(&etEeb)la.PARA"#A3'I!%, true)+
super.executeImpl(action, actionedUponNodeRef)+
-
-
!isting 1.: Su$#classing Set+e$,lag to pro&i*e a new action that *oesn"t re6uire para(eters
The @isable9eb<la$ action looks Just like this but sets the active la$ to alse. - won3t repeat it here.
The Sprin$ coni$uration or the action is similarly short"
0bean id=6enable<7eb<fla6 class=6com.someco.action.executer.%nableEeb)la6
parent=6set<7eb<fla61
0propert, name=6publicAction61
0value1false0/value1
0/propert,1
0/bean1
!isting 10: Spring configuration for Ena$le +e$ ,lag
A$ain! -3m leavin$ out the disable-web-la$ bean but it looks Just like this one with a dierent class.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e ++ o %0
ecmarchitect.com
Settin$ the .publicAction/ property to alse hides these actions rom the action dropdowns. There3s no
real reason to do that! in this case0it3s Just an e2ample.
Step : *pdate s#are%config%custom+xml )it# t#e action configuration
The ne2t step is to coni$ure the Share user interace to show the U- actions in the document library
and document details menus. 9hile we3re at it! -3m $oin$ to also drop in a U- action that calls a web
pa$e Just or kicks.
The action coni$ has moved to share-coni$-custom.2ml in Alresco %. Action coni$uration consists
o two parts. The .actions/ element contains a list o action deinitions. The .actionLroups/ element
contains a list o action $roups. Action $roups are thin$s like the list o actions shown in the document
library document list or the document details pa$e.
Actions and action $roups live in the .@ocLibActions/ coni$ within share-coni$-custom.2ml. 5ere
are the action deinitions or the web site action and web enable"
0><< Actions <<1
0confi evaluator=6strin<compare6 condition=6$oc*ibActions61
0actions1
0action id=6someco<7eb<site6 t,pe=6lin86 label=6actions.someco.7eb<
site6 icon=6someco<7ebsite61
0param name=6.ref61.ttp9//ecmarc.itect.com0/param1
0param name=6taret61#blan80/param1
0/action1
0action id=6someco<7eb<enable6 t,pe=6Favascript6
label=6actions.someco.7eb<enable6 icon=6someco<create<7ebsite61
0param name=6function61onAction&impleRepoAction0/param1
0permissions1
0permission allo7=6true61Erite0/permission1
0/permissions1
0param name=6action61enable<7eb<fla0/param1
0param name=6success"essae61messae.7eb<fla.enabled0/param1
0param name=6failure"essae61messae.7eb<fla.failure0/param1
0/action1
!isting 21: UI action *eclaration for +e$ Site an* +e$ Ena$le
The .someco-web-site/ action is really simple. -t is a .link/ type o an action! which means it is
invokin$ a U;L that is provided in a parameter. The labels and icons will $et set up in the ne2t step.
The .someco-web-enable/ action is a little more involved. -t is a .Javascript/ action! which means it is
callin$ a client-side *avaScript handler. 9hat3s cool is that Alresco has already provided a client-side
handler called .onSimple;epoAction/. -t Just needs to know the name o the repository tier action to
invoke Bthe ones created in Step )C and messa$es to display on success and ailure.
-3ve let out .someco-web-disable/ because it is so similar.
This action uses the built-in onActionSimple;epoAction! but what i you needed to $ather parameters
rom the end-user beore callin$ the action: <or that you can use onAction<orm@ialo$. The item-d
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e +3 o %0
ecmarchitect.com
speciies a orm -@ correspondin$ to a orm deined in share-orm-coni$-custom.2ml. Take a look at
the document-transorm action as an e2ample.
The last part o the coni$ is the action deinitions. This slots the actions into the appropriate $roups"
0actionAroups1
0actionAroup id=6document<bro7se61
0action index=6K556 id=6someco<7eb<site6 /1
0action index=6K456 id=6someco<7eb<enable6 /1
0action index=6KL56 id=6someco<7eb<disable6 /1
0/actionAroup1
0actionAroup id=6document<details61
0action index=6K556 id=6someco<7eb<site6 /1
0action index=6K456 id=6someco<7eb<enable6 /1
0action index=6KL56 id=6someco<7eb<disable6 /1
0/actionAroup1
0/actionAroups1
0/confi1
!isting 21: UI action groups exten*e* to inclu*e custo( actions
There are a couple o thin$s to note about the action coni$uration. <irst! you don3t have to copy in the
out-o-the-bo2 actions and action $roups. They will $et mer$ed in. Second! the order o the action
items in the list can be controlled by settin$ the inde2 attribute. The hi$her the inde2! the lower in the
list the menu items appear.
Step (: Create icons and locali,e t#e strings
The last step is to provide some icons or the actions and locali>e the action labels. -n step + the action
element had an .icon/ attribute. Alresco will look in a path or an icon that starts with that name and
ends with .-)8.pn$/. 1ntirely lackin$ in $raphics skills! - $rabbed a couple o out-o-the-bo2 icons that
looked somewhat applicable and copied them in to my proJect under
.src#web#components#documentlibrary#actions/. Aecause this is Alresco3s older structure! - made sure
to name the icons startin$ with .someco/ so they would not be conused with others.
The locali>ed strin$s can $o in the e2istin$ sc'odel.properties ile. 5ere they are"
Gactions
actions.someco.7eb<site=&ome3o
actions.someco.7eb<enable=&3 %nable Eeb
actions.someco.7eb<disable=&3 $isable Eeb
messae.7eb<fla.enabled=&uccessfull, enabled t.e &ome3o active fla
messae.7eb<fla.disabled=&uccessfull, disabled t.e &ome3o active fla
messae.7eb<fla.failure=%rror settin t.e &ome3o active fla
!isting 22: !ocali2e* strings for the new actions
9ith icons and locali>ed strin$s in place! you could deploy and run and everythin$ should work. B-
you are ollowin$ alon$! don3t or$et to deploy both the repository tier proJect and the share tier proJect
because you made chan$es in bothC.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e +% o %0
ecmarchitect.com
Aut! what you3ll notice is that both the 1nable and @isable U- actions show up at the same time! which
is lame. The enable should only show up when the active la$ is not set to true. The disable should only
show up when the active la$ is set to true. That3s easy to i2 with an evaluator and that3s covered in the
ne2t section.
Finishing "ouches# Evaluators $ Indicators
- you are writin$ a U- action that should show up all o the time! you don3t need to do anythin$ else.
Aut hidin$ a U- action based on certain conditions is a pretty common reDuirement. -n this e2ample!
the U- action needs to hide based on a metadata value. Alresco has several .evaluators/ that can be
levera$ed out-o-the-bo2 to do this. Fou can hide U- actions based on thin$s like"
The presence o an aspect
The type o a node
'imetype
The type o site the document library is sittin$ in
The name o the site
1valuators can also be chained to$ether i multiple conditions need to apply. The out-o-the-bo2
evaluators live in slin$shot-document-library-conte2t.2ml so reer to that ile or the ull list o
evaluators and an e2ample o how chainin$ works. Fou can also write completely new evaluators usin$
*ava deployed to the Share tier.
<or this e2ample! the out-o-the-bo2 .value/ evaluator will do Duite nicely. The steps! then! will be as
ollows"
). @eclare a new evaluator in Sprin$ coni$ that e2tends the .value/ evaluator
+. Update the action coni$ in share-coni$-custom.2ml to point to the evaluator
Alresco % has also made it easy to coni$ure .indicators/! which are little icons in the document
library column. This isn3t entirely relevant to the subJect at hand! but because they work Just like
evaluators and because it makes it easy to see rom the document library which content has the active
la$ set! -3m $oin$ to add a third step"
3. Update the share-coni$-custom.2ml ile to show a document library indicator
Ater these steps are complete! the U- actions will show or hide themselves appropriately and end-users
will be able to see documents with the active la$ set to true rom the document list.
Step 1: -eclare a ne) evaluator in Spring config
Enly one evaluator is needed or this e2ample. The evaluator Just needs to know the value o the active
la$0the U- actions can show or hide themselves based on that. 1valuators live in Sprin$ coni$ and
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e +7 o %0
ecmarchitect.com
Sprin$ coni$ resides in iles endin$ with .conte2t.2ml/. This proJect already has .custom-slin$shot-
application-conte2t.2ml/ so - added the evaluator to that ile"
0bean id=6someco.evaluator.doclib.action.isActive6
parent=6evaluator.doclib.action.value61
0propert, name=6accessor6 value=6node.properties.sc9isActive6 /1
0propert, name=6comparator61
0bean class=6or.alfresco.7eb.evaluator.&trin%Muals3omparator61
0propert, name=6value6 value=6true6 /1
0/bean1
0/propert,1
0/bean1
!isting 23: Declaring a new e&aluator that chec7s the &alue of sc:isActi&e
This bean e2tends the out-o-the-bo2 .value/ evaluator and provides properties speciic to our needs. -n
this case! the .accessor/ is the name o the property the evaluator needs to inspect. The comparator
does a strin$ comparison a$ainst the value o .true/. Kote the use o .someco/ in the bean -@. This is
another place where you want to make sure you are usin$ your own namespace.
All evaluators work similarly. - you wanted to check or a speciic aspect! or e2ample! you would
e2tend the aspect evaluator and then speciy the aspect you are lookin$ or in one o the properties.
Step : *pdate t#e action config in s#are%config%custom+xml
9ith an evaluator declared the ne2t step is to tell the action coni$uration which evaluator to use to
decide whether or not to show the U- action. So! back over in share-coni$-custom.2ml! -3ve made the
ollowin$ modiications! hi$hli$hted in bold"
0action id=6someco<7eb<enable6 t,pe=6Favascript6
label=6actions.someco.7eb<enable6 icon=6someco<create<7ebsite61
0param name=6function61onAction&impleRepoAction0/param1
0permissions1
0permission allo7=6true61Erite0/permission1
0/permissions1
0param name=6action61enable<7eb<fla0/param1
0param name=6success"essae61messae.7eb<fla.enabled0/param1
0param name=6failure"essae61messae.7eb<fla.failure0/param1
<e#alator
ne!ate="tre">someco.e#alator.doclib.action.is"cti#e</e#alator>
0/action1
0action id=6someco<7eb<disable6 t,pe=6Favascript6
label=6actions.someco.7eb<disable6 icon=6someco<delete<7ebsite61
0param name=6function61onAction&impleRepoAction0/param1
0permissions1
0permission allo7=6true61Erite0/permission1
0/permissions1
0param name=6action61disable<7eb<fla0/param1
0param name=6success"essae61messae.7eb<fla.disabled0/param1
0param name=6failure"essae61messae.7eb<fla.failure0/param1
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e +8 o %0
ecmarchitect.com
<e#alator>someco.e#alator.doclib.action.is"cti#e</e#alator>
0/action1
!isting 24: Specif4ing the e&aluator in the action configuration
Aoth actions use the same evaluator. <or the someco-web-enable action! the evaluator is ne$ated. So i
the evaluator returns true Bi.e.! the sc"isActive property is set to trueC the web enable action will be
hidden. - the evaluator returns alse! the action will show itsel.
Step (: *pdate t#e s#are%config%custom+xml file to s#o) a document
librar& indicator
The last step is really not needed at all i all you are doin$ is addin$ an action to the menu. Aut because
it is easy to do and levera$es the same evaluator written in the previous step! - didn3t think you3d mind.
The $oal here is to show a little icon in the document library only i the .sc"isActive/ property is set to
true. - you are already thinkin$! .5ey! that sounds like an evaluator6/ you3ve $ot it.
-ndicators are part o the .@ocumentLibrary/ coni$ in share-coni$-custom.2ml. All it needs is a
pointer to an evaluator. -n this case! the one created earlier can be reused"
0/t,pes1

0><< 3ustom Indicators <<1
0indicators1
0indicator id=6someco<7ebsite6 index=64561
0evaluator1someco.evaluator.doclib.action.isActive0/evaluator1
0/indicator1
0/indicators1
0/confi1
!isting 25: A**ing an in*icator to the *ocu(ent li$rar4 configuration
Alresco will use the indicator3s id attribute appended with .-)8.pn$/ or the icon. - copied the same
icon used or the .enable/ action into .src#web#components#documentlibrary#indicators/ or this
purpose.
-eplo& . Test
- you3ve been ollowin$ alon$ and you3ve waited to deploy until now! it3s time to try it out. The code
that accompanies this article includes an Ant build ile in each o the two proJects. And each proJect
includes a build.properties ile. The repository proJect3s build.properties ile needs to know the location
o the e2panded Alresco S@R and the location o the e2panded Alresco webapp root. The Share
proJect3s build.properties ile needs to know the location o the e2panded Share webapp root and the
location o the FU- compressor *A;! which is used as part o the build process. Ence those are set! you
should be able to run .ant deploy/ or each o the two proJects! start Tomcat! and test.
- everythin$ is workin$ correctly! you should see the SomeCo web site link and either the SC 9eb
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e +, o %0
ecmarchitect.com
1nable or the SC 9eb @isable menu items rom both the browse menu and the details pa$e as shown
below.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e += o %0
ecmarchitect.com
Clickin$ the .SomeCo/ menu item will open a browser window to the U;L speciied in the
coni$uration. Clickin$ the .SC @isable 9eb/ should invoke the action on the repository tier and then
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e +& o %0
Drawing .: In*icators show which content has
the acti&e flag set in Share
Drawing 0: /usto( UI actions
in the *ocu(ent list
Drawing 11: /usto( UI
actions in the *ocu(ent
*etails page
ecmarchitect.com
reresh the metadata and the action list.
Conclusion
This article has shown how actions can be used to implement reusable operations that can be run
a$ainst content in the repository. Those actions can be called rom code usin$ the Action Service and
they can be invoked rom the user interace by coni$urin$ rules or by settin$ up U- actions and placin$
those alon$side other menu items in places like the document list and the details pa$e. 5opeully it has
sparked some ideas about how you could use custom actions in your ne2t Alresco implementation.
Where to ind more inormation
All source code used in this e2ample is available here.
The Alresco S@R comes with a Custom Action e2ample.
Eicial documentation or both 1nterprise and Community is available at docs.alresco.com.
Share 12tras has many e2amples o deeper Share customi>ation as well as documentation o
Alresco3s client-side *avaScript components.
'ike 5atield and @avid @raper are two e2amples o Alresco en$ineer blo$s that are
e2tremely useul i you are customi>in$ Share.
<or deployment help! see 4acka$in$ and @eployin$ 12tensions in the Alresco wiki.
<or $eneral development help! see the @eveloper Luide.
<or help customi>in$ the data dictionary! see the @ata @ictionary wiki pa$e.
- you are ready to cover new $round! try another ecmarchitect.com tutorial in the Alresco
@eveloper Series.
About the Author
*e 4otts is the Chie Community Eicer or Alresco Sotware. *e has been a
reco$ni>ed and award-winnin$ leader in the Alresco community or many years.
5e has over )= years o content mana$ement and collaboration e2perience! most o
that havin$ come rom senior leadership positions in consultin$ or$ani>ations.
*e has made many contributions to the Alresco community since he started
workin$ with Alresco in +007. 12amples ran$e rom code! to tutorials and
inormative blo$ posts! to code camps! meetups! and conerence sessions. -n +00=!
*e wrote the Alresco @eveloper Luide! the irst developer-ocused book on
Alresco. 5e has also been active in the Apache Chemistry proJect where he leads
the development o cmislib! the 4ython A4- or C'-S.
;ead more at *eSs blo$! ecmarchitect.com.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 30 o %0
ecmarchitect.com
Appendix
Kot everyone is able to use Alresco Share as their user interace. The sections within this Appendi2
show you how to do the same thin$ 4art + covers! but uses Alresco 12plorer instead o Alresco Share.
Coniguring the Replaceable Aspect in E%plorer
Alresco3s out-o-the-bo2 content model contains an aspect called .cm"replaceable/ but it is not
e2posed in the U-. 1nd-users need to be able to declare which documents a new document should
replace! so the aspect will need to be added to the web-client-coni$-custom.2ml ile created in the
content types tutorial.
The .aspects/ element should now look like this"
0aspects1
0aspect name=6sc97ebable6/1
0aspect name=6sc9productRelated6/1
0aspect name=6cm9replaceable6/1
0/aspects1
!isting 2: A**ing the replacea$le aspect to the Explorer UI config
And a new .coni$/ element tells the user interace to show the .cm"replaces/ relationship"
0confi evaluator=6aspect<name6 condition=6cm9replaceable61
0propert,<s.eet1
0s.o7<association name=6cm9replaces6 displa,<label<id=6replaces6 /1
0/propert,<s.eet1
0/confi1
!isting 2-: /onfiguring the replacea$le aspect for the Explorer UI
9ith this coni$uration in place! end-users can edit a document3s metadata to maintain the .replaces/
relationship.
Coniguring the Move Replaced Rule Action in E%plorer
The back-end lo$ic or the 'ove ;eplaced Action was implemented in 4art ). - users are $oin$ to
speciy parameters or an action when coni$urin$ it as part o a rule or when invokin$ it via .;un
Action/! a user interace has to be provided. This is done by"
). Create an action handler class
+. Create a correspondin$ *S4 pa$e
3. Locali>e the strin$s.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 3) o %0
ecmarchitect.com
Step 1: Create an action #andler class
Alresco3s bean handler class or the 'ove action is called
or$.alresco.web.bean.actions.handlers.'ove5andler and it resides in the Alresco source in the 9eb
Client proJect. The bean handler class handles the MviewM or the action coni$uration. Aecause both the
M'oveM action and our M'ove ;eplacedM action both have a destination older and no other
coni$urable properties! only minor modiications are needed to make it work or the new action.
<irst! the custom action will have its own *S4 or the presentation so the $et*S44athBC method needs to
chan$e rom this"
public &trin etN&PPat.() {
return etN&PPat.("oveAction%xecuter.NA"%)+
-
!isting 2.: 'he out#of#the#$ox get5S33ath (etho* in %o&e8an*ler9:a&a
to this"
public final static &trin 3U&'("#A3'I(N#N&P = 6/someco/Fsp/actions/6 O
"oveReplacedAction%xecuter.NA"% O 6.Fsp6+
public &trin etN&PPat.() {
return 3U&'("#A3'I(N#N&P+
-
!isting 20: 'he new get5S33ath (etho* in %o&e)eplace*8an*ler9:a&a
All -3m doin$ here is tellin$ the bean where to ind our customi>ed *S4.
Ke2t! i you3ve ever coni$ured an action beore you know that the user interace includes a short
summary o what the action is $oin$ to do. The $enerateSummaryBC method is responsible or that
messa$e. The actual te2t will be in a resource bundle! so - chan$ed the property name rom
MactionImoveM to MactionImoveIreplacedM.
Step : Create a corresponding 'SP page
The *S4 pa$e that handles the move coni$uration or 'ove ;eplaced is identical to the out-o-the-bo2
move. Aut the title needs to be dierent! so it reDuires its own pa$e. And! because the pa$e is in a
dierent older structure than the Alresco *S4! the e2istin$ *S4 includes will need to be updated
because they use relative links.
Copy M#source#web#Jsp#actions#move.JspM rom the Alresco 9eb Client proJect into the custom
repository proJect. - use Msrc#web#TnamespaceU#JspM or all customi>ed Alresco *S4s by convention! so
the ull path to the *S4 in the custom proJect is! Msrc#web#someco#Jsp#actions#move-replaced.JspM. The
customi>ed *S4s will be deployed to a dierent directory structure so any e2istin$ relative links that
need to point to out-o-the-bo2 *S4s need to point to .#Jsp#parts#V/. -n this case there are three includes
that - updated as ollows"
0PB include file=6/Fsp/parts/titlebar.Fsp6 P1
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 3+ o %0
ecmarchitect.com
0PB include file=6/Fsp/parts/s.elf.Fsp6 P1
0PB include file=6/Fsp/parts/breadcrumb.Fsp6 P1
!isting 31: %o*ifie* inclu*e state(ents in (o&e#replace*9:sp
To point to the custom title property in the resource bundle! - chan$ed the title-d attribute o the r"pa$e
ta$ rom MtitleIactionImoveM to MtitleIactionImoveIreplacedM.
That3s it or the *ava and *S4 code. Kow it is time to locali>e the action.
Step (: /ocali,e t#e Move Replaced Action
The someco-action-conte2t.2ml ile needs to be updated to point to a resource bundle. - added the
ollowin$ to that ile"
0bean id=6someco.actionResource@undles6 parent=6actionResource@undles61
0propert, name=6resource@undles61
0list1
0value1alfresco.extension.messaes.somecoactions0/value1
0/list1
0/propert,1
0/bean1
!isting 31: Spring configuration nee*e* to specif4 the action resource $un*le
Ke2t! - need to create a resource bundle so - created a ile in alresco#e2tension#messa$es called
somecoactions.properties. Kote that this ile name and path matches the resource bundle declaration
rom the previous step.
GG
GG &ome3o Actions I4=N file
GG
G "ove Replaced action
move<replaced.title="ove replaced document to space
move<replaced.description='.is 7ill move t.e taret node of a replaces association
to a specified space.
!isting 32: !ocali2e* strings for the %o&e )eplace* action
The summary te2t and the *S4 title $et pulled rom alresco#e2tension#webclient.properties. The
.cm"replaces/ aspect also needs to be locali>ed. So! - added the ollowin$ entries to the ile"
Gcm9replaceable
replaces=Replaces
G"ove Replaced Action
action#move#replaced="ove replaced to ;;{5-;;
title#action#move#replaced="ove Replaced Action
!isting 33: !ocali2e* strings for the replacea$le aspect an* %o&e )eplace* in we$client9properties
The last step is to hook in to the Alresco action wi>ard U- so that when someone coni$ures a rule or
simple worklow! the new action is listed as a valid choice. - edited the alresco#e2tension#web-client-
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 33 o %0
ecmarchitect.com
coni$-custom.2ml ile and added the ollowin$"
0><< action .andlers <<1
0confi evaluator=6strin<compare6 condition=6Action EiCards61
0><< add custom action .andler for 6"ove Replaced6 action <<1
0action<.andlers1
0.andler name=6move<replaced6
class=6com.someco.action..andler."oveReplacedDandler6 /1
0/action<.andlers1
0/confi1
!isting 34: Action wi2ar* configuration to *eclare the custo( action han*ler
The code that accompanies this document includes a sample Ant build.2ml ile that can be used to
deploy the iles to the ri$ht spot within the Alresco 9A;. -n real lie! you3ll want to packa$e your
e2tensions as an A'4 and then use the 'odule 'ana$ement Tool B''TC to mer$e the A'4 with the
Alresco 9A;. <or local development and testin$! the Ant3s deploy! which essentially does a copy into
the e2ploded webapp! will be ine.
To set up a test! you3ll need to add the replaceable aspect to a piece o test content. Ater the aspect has
been applied! you should see a MreplacesM section in the document3s properties. - not! double-check the
web-client-coni$-custom.2ml ile. 1dit the properties and select a document to replace. This
establishes the MreplacesM association.
Kow add a rule to the space in which M4ublishedM documents reside. The rule should run the new
M'ove ;eplacedM action.
Coni$ure the action to move documents to the MArchivedM space.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 3% o %0
ecmarchitect.com
To test the lo$ic! paste the document with the MreplacesM association into the M4ublishedM space. The
document it is replacin$ should $et automatically moved to the MArchivedM older.
Coniguring the Set Web Flag !I Action in E%plorer
The Set 9eb <la$ action isn3t meant to be called rom a rule so it does not have a 5andler class or a
*S4. -t will be called rom a menu item in the 12plorer user interace. These menu items are oten
called .U- actions/.
Assumin$ the back-end action already e2ists! the steps to inte$rate it into the 12plorer user interace
are"
). Create a *S<-mana$ed bean
+. Update web-client-coni$-custom.2ml
3. Locali>e the action
Step 1: Create a 'S"%managed 0ean
The 9ebSettin$sAean class $ets called when the U- action is clicked. 5ere is a snippet rom the bean3s
setActive method"
final NodeRef ref = ne7 NodeRef(Repositor,.et&toreRef(), id)+
Retr,in'ransactionDelper txnDelper =
Repositor,.etRetr,in'ransactionDelper(fc)+
Retr,in'ransaction3allbac80(bFect1 callbac8 = ne7
Retr,in'ransaction3allbac80(bFect1() {
public (bFect execute() t.ro7s '.ro7able {
ActionImpl action = ne7 ActionImpl(ref, &etEeb)la.NA"%, null)+
action.setParameter!alue(&etEeb)la.PARA"#A3'I!%, active)la)+
&etEeb)la action%xecuter = (&etEeb)la)
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 37 o %0
ecmarchitect.com
)aces3ontextUtils.etEebApplication3ontext(fc).et@ean(&etEeb)la.NA"%)+
action%xecuter.execute(action, ref)+

&trin ms = Application.et"essae(fc, "&A#&U33%&&#E%@#&%'#A3'I!%)+
)aces"essae faces"s = ne7 )aces"essae()aces"essae.&%!%RI'?#IN)(,
ms, ms)+
&trin formId = Utils.etParent)orm(fc,
event.et3omponent()).et3lientId(fc)+
)aces3ontext.et3urrentInstance().add"essae(formId O ;9; O
PAN%*#I$#&PA3%#PR(P&, faces"s)+
return null+
-
-+
txnDelper.doIn'ransaction(callbac8)+
t.is.bro7se@ean.et$ocument().reset()+
!isting 35: /usto( +e$SettingsBean9:a&a
This snippet shows a transaction bein$ set up beore instantiatin$ and e2ecutin$ the Set9eb<la$ action
e2ecuter class. The rest o the code deals with providin$ the user some eedback ater the action runs.
Ence the class is complete it has to be wired in to *avaServer <aces. This is done by creatin$ a ile
called aces-coni$-conte2t.2ml in 91A--K< with the ollowin$ content"
0:xml version=;4.5; encodin=;U')<=;:1
0>$(3'?P% faces<confi PU@*I3 6<//&un "icros,stems, Inc.//$'$ Nava&erver )aces
3onfi 4.4//%N6
6.ttp9//Fava.sun.com/dtd/7eb<facesconfi#4#4.dtd61
0faces<confi1
0manaed<bean1
0description1
'.e bean t.at manaes &3 Eeb settins.
0/description1
0manaed<bean<name1Eeb&ettins@ean0/manaed<bean<name1
0manaed<bean<class1com.someco.7eb.bean.Eeb&ettins@ean0/manaed<bean<
class1
0manaed<bean<scope1session0/manaed<bean<scope1
0manaed<propert,1
0propert,<name1bro7se@ean0/propert,<name1
0value1G{@ro7se@ean-0/value1
0/manaed<propert,1
0/manaed<bean1
0/faces<confi1
!isting 3: ,aces configuration for the +e$ Settings Bean
Kow that *S< knows about the new bean it can be wired into the 12plorer user interace.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 38 o %0
ecmarchitect.com
*pdate )eb%client%config%custom+xml )it# t#e ne) *I action
There are several menus within the Alresco 12plorer user interace. These are called .action $roups/.
Actions B-3m talkin$ about .U- actions/ nowC can be deined once and then added to as many action
$roups as needed. A U- action mi$ht call an arbitrary U;L! an action Blike Set 9eb <la$C! or a 9i>ard
or @ialo$. This tutorial doesn3t cover wi>ards and dialo$s! but it does provide e2amples o the irst two.
- added the ollowin$ to web-client-coni$-custom.2ml"
0><< UI Actions <<1
0confi1
0actions1
0action<roup id=6document#bro7se61
0action idref=67eb#site6 /1
0/action<roup1
0><< Actions "enu for a document in t.e @ro7se screen <<1
0action<roup id=6document#bro7se#menu61
0action idref=67eb#site6 /1
0/action<roup1
0><< Actions "enu for $ocument $etails screen <<1
0action<roup id=6doc#details#actions61
0action idref=67eb#enable6 /1
0action idref=67eb#disable6 /1
0action idref=67eb#site6 /1
0/action<roup1
!isting 3-: Action groups an* action references for Explorer
This part o the coni$uration adds a .9eb Site/ menu item to the browse menu! the .more/ menu! and
the document details screen. -t also adds the .9eb 1nable/ and .9eb @isable/ to the document details
screen.
The ne2t part o the coni$uration deines the U- actions. The irst one is a simple action that invokes a
U;L.
0><< *in8 to &ome3o;s 7eb site <<1
0action id=67eb#site61
0label1&ome3o0/label1
0.ref1.ttp9//ecmarc.itect.com0/.ref1
0imae1/someco/imaes/icons/7ebsite.if0/imae1
0taret1ne70/taret1
0/action1
!isting 3.: Action *eclaration for the +e$ Site UI action in Explorer
The ne2t one enables the .sc"isActive/ la$.
0><< set sc9isActive to true <<1
0action id=67eb#enable61
0permissions1
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 3, o %0
ecmarchitect.com
0><< eac. permission can be an Allo7 or $en, c.ec8 <<1
0permission allo7=6true61Erite0/permission1
0/permissions1
0evaluator1com.someco.action.evaluator.Eeb%nable%valuator0/evaluato
r1
0label<id1enableEeb0/label<id1
0imae1/someco/imaes/icons/create#7ebsite.if0/imae1
0action<listener1G{Eeb&ettins@ean.setActive-0/action<listener1
0params1
0param name=6id61G{action3ontext.id-0/param1
0param name=6active61true0/param1
0/params1
0/action1
!isting 30: Action *eclaration for Ena$le +e$ in Explorer
The .permissions/ element points to an out-o-the-bo2 permission called .9rite/. -3m assumin$ anyone
with write access to the node is also allowed to publish the content to the web. -t mi$ht make sense to
instead create a custom role! like .4ortal4ublisher/ and use that. 5onestly! - had a little bit o trouble
$ettin$ that to work so - decided to keep it simple or now and use .9rite/ and will ollow up later
with how to modiy the e2ample to use a custom role.
The .evaluator/ element is a *ava class discussed in the ne2t section. - you want to deploy and test
your action beore writin$ that class! Just comment out the evaluator. The .action-listener/ reers to the
*S<-mana$ed bean created in the previous step. The .params/ element passes ar$uments into the
9ebSettin$sAean.
The inal piece o coni$ sets up the menu item to disable the .sc"isActive/ la$. -t3s almost identical to
the .enable/ case e2cept that it passes a dierent value or the active la$.
0><< set sc9isActive to false <<1
0action id=67eb#disable61
0permissions1
0><< eac. permission can be an Allo7 or $en, c.ec8 <<1
0permission allo7=6true61PortalPublis.er0/permission1
0/permissions1
0evaluator1com.someco.action.evaluator.Eeb$isable%valuator0/evaluat
or1
0label<id1disableEeb0/label<id1
0imae1/someco/imaes/icons/delete#7ebsite.if0/imae1
0action<listener1G{Eeb&ettins@ean.setActive-0/action<listener1
0params1
0param name=6id61G{action3ontext.id-0/param1
0param name=6active61false0/param1
0/params1
0/action1
0/actions1
0/confi1
!isting 41: Action *eclaration for +e$ Disa$le in Explorer
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 3= o %0
ecmarchitect.com
/ocali,ing t#e Set !eb "lag action
- locali>ed the action by addin$ the ollowin$ to somecoactions.properties"
G &et 7eb fla action
set<7eb<fla.title=&ets t.e &3 Eeb )la
set<7eb<fla.description='.is 7ill add t.e sc97ebable aspect and set t.e isActive
fla.
!isting 41: !ocali2ing the Set +e$ ,lag action
- you deploy now you should see menu items in the ri$ht places. And i you click them they should
work. Fou3ll notice when lookin$ at the document details pa$e! however! that the .SC 9eb 1nable/ and
.SC 9eb @isable/ menu items both show up. To reduce conusion and clutter! the enable item should
only show when the la$ hasn3t been set or is set to alse and the disable item should only show when
the la$ has been set to true. 5idin$ and showin$ menu items is the Job o an .evaluator/ and that3s the
topic o the ne2t section.
Coniguring the Evaluator to Sho&'(ide the Set Web Flag !I Action in
E%plorer
The inal step in coni$urin$ the Set 9eb <la$ action within the Alresco 12plorer user interace is to
write an evaluator that hides#shows the menu items appropriately based on the value o the
.sc"isActive/ la$.
The evaluators have already been speciied in the web-client-coni$-custom.2ml. The only thin$ let to
do is to implement the evaluator as a *ava class. The 9eb1nable1valuator class implements the
Action1valuator interace. The ma$ic happens within the evaluate method and is as ollows"
public boolean evaluate(Node node) {
)aces3ontext context = )aces3ontext.et3urrentInstance()+
// c.ec8 t.e aspect, t.en c.ec8 t.e active propert,
NodeRef ref = ne7 NodeRef(Repositor,.et&toreRef(), node.etId())+
// if t.e aspect .asn;t ,et been added, it can be enabled
if (>node..asAspect(
2Name.create2Name(&ome3o"odel.NA"%&PA3%#&("%3(#3(N'%N'#"($%*,
&ome3o"odel.A&P%3'#&3#E%@A@*%))) {
return true+
-
// c.ec8 t.e active propert,
Node&ervice node&vc =
Repositor,.et&erviceReistr,(context).etNode&ervice()+
boolean active = (@oolean)node&vc.etPropert,(ref,
2Name.create2Name(&ome3o"odel.NA"%&PA3%#&("%3(#3(N'%N'#"($%*,
&ome3o"odel.PR(P#I&#A3'I!%))+
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e 3& o %0
ecmarchitect.com

return >active+
-
!isting 42: 'he +e$ Ena$le E&aluator
This code checks or the presence o the .sc"webable/ aspect. -t actually doesn3t matter i the aspect is
there or not0i it isn3t! the Set 9eb <la$ action will add it. Then! the evaluator checks the value o the
active la$ and simply returns the opposite o its value B- the la$ is alse! return true to show the
enable menu item. - the la$ is true! return alse to hide the enable menu itemC.
The evaluator or disable is so similar! it doesn3t make sense to repeat it here.
En deployin$ the repository proJect usin$ .ant deploy/ and then restartin$ Tomcat! you should be able
to enable and disable the web la$ usin$ the menu items on the document details pa$e. The menu items
should only show up or users in the appropriate role! and they should hide themselves based on the
value o the active la$.
Developing Custom Actions, 2
nd
Edition
Tis !or" is licensed under te Creative Commons Attri#ution$Sare
Ali"e %&0 'nported (icense
4a$e %0 o %0

You might also like