Vous êtes sur la page 1sur 13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

Small steps with big feet


BraindumpsofanactiviticoredeveloperaboutActiviti,workflowsystemsandtheworldaroundus.

About

CreatinganewformpropertyinActiviti
OnMarch13,2013byJoram BarrezWith21Com m ents Activiti,bpm ,bpm n,java

Activitihasmanywaystointegratewithyourenvironmentandtechnologies.Formsistypicallyanarea
wheretherearemanydifferentsolutionsneeded.Activitioffersoutoftheboxtwooptions:usingaformkey
(thatishowforexampleAlfrescoformsarecorrelatedwithprocesstasks)orusingformproperties.The
detailsofformsandformpropertiesaredescribedintheuserguide,butbasicallyitboilsdownto
DefiningformpropertiesintheBPMN2.0xml
UsingtheFormServiceatruntimetofetchandsubmitformsandformproperties
Forexample,thisishowtheformpropertiescanbedefinedonausertask:
1
2
3
4
5
6
7

<userTask id="provideNewSalesLead" name="Provide new sales lead" activit


?i
:assignee
<extensionElements>
<activiti:formProperty id="customerName" name="Customer name" type="string"
<activiti:formProperty id="potentialProfit" name="Potential profit" type
<activiti:formProperty id="details" name="Details" type="string"/>
</extensionElements>
</userTask>

Tofetchthisinformationatruntime,youhavetousesomethinglike:
1
2

TaskFormData taskFormData = formService.getTaskFormData(myTaskId);


List<FormProperty> formProperties = taskFormData.getFormProperties();

WhenusingActivitiExplorer,allofthesupportedformpropertieshavespecificrenderesthatknowhowto
renderthatformpropertytype.Eg.adateformpropertywillbevisualizedusingadatepicker,anumber
propertymustbecheckedonvalidity,etc.
ThexmlexampleofabovelooksasfollowsinExplorer:

http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

1/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

Customformproperties
AquestionweoftenhearontheActivitiForumishowtoaddnewformpropertytypesandrenderthemin
Explorer.Andactuallydoingthatisveryeasy.
Letsstartwithasimpleexample:wewanttoaddaformpropertytypethatallowstheusertoselecta
month.Visually,wewanttouseadropdownmenuforthatontheUIsideofthings.
CreateanewclassthatsubclassesAbstractFormTypeandimplementthetwoabstractmethods:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

public class MonthFormType extends AbstractFormType {

public static final String TYPE_NAME = "month";

public String getName() {


return TYPE_NAME;
}

public Object convertFormValueToModelValue(String propertyValue) {


Integer month = Integer.valueOf(propertyValue);
return month;
}

public String convertModelValueToFormValue(Object modelValue) {


if (modelValue == null) {
return null;
}
return modelValue.toString();
}

Tounderstandthiscode,youjusthavetokeepinmindthatfortheFormService,everyhingisastring.This
isdonesoitisveryeasytoincludeinyourownUItechnology.TheFormTypeclassitself,liketheone
abovewilldotheactualconversiontorealobjects.
TheconvertFormValueToModelValuemethodimplementstheconversionfromtheformtotheinternalobject.
Hereitsverysimple,weassumethevaluestoredintheformisanintegerwhichisthenumberofthe
month.Theothermethod,convertModelValueToFormValueistheotherwayaround.Sincewejustusethe
monthindexasmodelvaluehere,thatsalsoprettyeasy.
Theformtypemustnowbepluggedintotheprocessengineconfig:
1 <bean id="processEngineConfiguration" ... >
2 ...
3 <property name="customFormTypes">
4 <list>
http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

2/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

4
5
6
7
8
9

<list>
...
<bean class="org.activiti.explorer.form.MonthFormType"/>
</list>
</property>
</bean>

FortherendererinActivitiExplorer,weneedtowritethedropdownofmonths.Wealsoknowfrom
theMonthFormTypeabovethatwemustsendaninteger(asastring)backandforthindicatingtheindexof
themonth:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

public class MonthFormPropertyRenderer extends AbstractFormPropertyRend


?e
rer {

private static final long serialVersionUID = 1L;

public MonthFormPropertyRenderer() {
super(MonthFormType.class);
}

public Field getPropertyField(FormProperty formProperty) {


ComboBox comboBox = new MonthCombobox(getPropertyLabel(formProperty));
comboBox.setRequired(formProperty.isRequired());
comboBox.setRequiredError(getMessage(Messages.FORM_FIELD_REQUIRED, getPropertyL
comboBox.setEnabled(formProperty.isWritable());

// Fill combobox
I18nManager i18nManager = ExplorerApp.get().getI18nManager();
for (int i=0; i<12; i++) {
comboBox.addItem(i);
comboBox.setItemCaption(i, i18nManager.getMessage(Messages.MONTH_PREFIX + i))
}

return comboBox;
}

Inthecodeitiseasytoseehowthatisdone:wesimplesetthecaptiontothemonthnameandstorethe
indexasvalue.Inourmessages.propertiesfile,wedoneedtohaveentrieslikemonth.0=Januarytomake
thiswork.
TherenderermustnowbepluggedintotheFormPropertyRenderManagerbean.Youcanfindthisbeanin
theactivitiuicontext.xmlfile:
1
2
3
4
5
6
7
8
9

<bean id="formPropertyRendererManager" class="org.activiti.explorer.ui.f


?o
rm.FormProp
...
<property name="propertyRenderers">
<list>
...
<bean class="org.activiti.explorer.ui.form.MonthFormPropertyRenderer"
</list>
</property>
</bean>

Thecustomformtypeandrendererarenowknowntothesystem.IfyouuseitinyourBPMN2.0processes
likethis
1

<activiti:formProperty id="month" name="Month"type="month" required="tr


?u
e"

http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

3/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

Itwillberenderednicelytothis:

Andthatsallthereistoit!

Anotherexample
Thepreviousexamplewasofcourseprettyeasy.Letmeshowyouhowyoucancreateamorecomplex
formtype.Inthefollowingexample,wewanttheusertoselectaprocessdefinitionfromadropdown.
TheFormTypeimplementationisabitmoreinvolvednow.Again,thevaluethatisbeingsentbackandforth
isastring.Soforthiscase,weusetheprocessdefinitionidandconvertittoaProcessDefinitionobject
whenneeded:

1 public class ProcessDefinitionFormType extends AbstractFormType {


?
2
3 public static final String TYPE_NAME = "processDefinition";
4
5 public String getName() {
6 return TYPE_NAME;
7 }
8
9 public Object convertFormValueToModelValue(String propertyValue) {
10 if(propertyValue != null) {
11 ProcessDefinition processDefinition = ProcessEngines.getDefaultProcessEngine(
12 .getRepositoryService()
13 .createProcessDefinitionQuery()
14 .processDefinitionId(propertyValue)
15 .singleResult();
16
17 if(processDefinition == null) {
18 throw new ActivitiObjectNotFoundException("Process definition with id "
19 }
20
21 return processDefinition;
22 }
23
24 return null;
25 }
26
27 public String convertModelValueToFormValue(Object modelValue) {
28 if (modelValue == null) {
29 return null;
30 }
31
32 if (!(modelValue instanceof ProcessDefinition)) {
33 throw new ActivitiIllegalArgumentException("This form type only support proce
34 }
http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/
4/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

34
35
36
37

}
return ((ProcessDefinition) modelValue).getId();
}
}

Wemustnowmaketheuserselectaprocessdefinitionfromthedropdown,andsendtheprocessdefinition
backandforth.Keepinmindthattherendereronlykeepstheprocessdefinitionidsasvalues,notthe
processdefinitionobjects.TheobjectisonlyretrievedbytheProcessDefinitionFormTypeclass
abovewhentheuseractuallysubmitstheform.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

public class ProcessDefinitionFormPropertyRenderer extends AbstractForm


?P
ropertyRend

private static final long serialVersionUID = 1L;

public ProcessDefinitionFormPropertyRenderer() {
super(ProcessDefinitionFormType.class);
}

public Field getPropertyField(FormProperty formProperty) {


ComboBox comboBox = new ComboBox(getPropertyLabel(formProperty));
comboBox.setRequired(formProperty.isRequired());
comboBox.setRequiredError(getMessage(Messages.FORM_FIELD_REQUIRED, getPropertyL
comboBox.setEnabled(formProperty.isWritable());

List<ProcessDefinition> processDefinitions = ProcessEngines.getDefaultProcessEn


.getRepositoryService()
.createProcessDefinitionQuery()
.orderByProcessDefinitionName().asc()
.orderByProcessDefinitionVersion().asc()
.list();

for (ProcessDefinition processDefinition : processDefinitions) {


comboBox.addItem(processDefinition.getId());
String name = processDefinition.getName() + " (v" + processDefinition.getVers
comboBox.setItemCaption(processDefinition.getId(), name);
}

return comboBox;
}
}

Andofcoursebothmustbeconfiguredintheconfigurationfilesasdescribedinthepreviousexample.The
resultlooksasfollows:

http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

5/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

Thatsallthereistoittocreatecustomformproperties.HappyCoding!

21Comments
Rubn
April8,2013

Thanks,
IthinkIllusethisfeaturemorethanonce.
Regards.

Mathias
June30,2013

Thisworksforme.Butisthereanypossibilitytouseformvalues(likeusedforenums)inmy
formrenderer?
Regards,Mathias

JoramBarrez
July1,2013

@Mathias:sure,whynot?Youcanqueryanythingwhatyouwanttohaveitdisplayed.

Mathias
July1,2013

@Joram:IdontknowifIunderstandyoucorrectly.AsfarasIcansee,queriesalwaysrefer
toinstancesofprocessdefinitions,taskdefinitionsorsomethinglikethat.InmycaseIwant
tohaveanewdatatypewhichcanbeusedinpotentiallyeveryprocessortask.
Basicallytheideawastoimplementanewdatatyperstringwhichshouldbeastring
validatedagainstaregex.Theregexshouldbeprovidedwithaformpropertyholdingthe
regex.
MyapproachwastoimplementsomethinganalogoustoEnumFormTypebutthemechanism
howthevaluesmapisfilledbytheBpmnParser/DefaultFormHandler/israthercomplexand
deepinthecode.

JoramBarrez
July2,2013

@Mathias:ok,isortofunderstandnow.

http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

6/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

TheEnumFormTypeisntthathard:extendstheAbstractFormTypeandplugitintoyour
processengineconfiguration.
However,thetrickybitwillbetohavedependenciesbetweentheformfields(ieyourregex
fieldandtheactualfield),asIdontknowifthecurrentcodeiscapableofdoingsomething
likethat.

Sunil
August23,2013

HiJoram,
Usingthiswecandevelopanykindofformelement.Canyoupleasesharehowcanwe
designaradiobutton.andusetheminform.

Tan
September30,2013

MyEclipsecomplainsaboutAbstractFormPropertyRenderer.Ithenhadtogoogleandfound
theanswerthattheAbstractFormPropertyRendererisfromactivitiexplorer.jarwhichisnot
storedinMavenrepo.NowIstillhavetheerrorField(inpublicFieldgetProeprtyField)and
thenComboBoxandMonthCombobox.Thesesclassesaredefinedanywhereelse?Ijusttry
toruntheexampletoseehowthewholethingworks.
Thanks,
Tan

Tan
September30,2013

Ifoundit.IfyouhaveMaven,thisisthejaryouwillneed:
com.vaadin
vaadin
6.8.12

Shiang
October22,2013

Thanksforthisgreattutorial,Imnewtoactivitianditisgreattounderstandit
However,wheredoIputthecode?isitinthebpmnxmlfile?Or?
Thanksagain

Joram
October22,2013

TheformpropertyxmlgoesintotheBPMN2.0file.
http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

7/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

ThejavacodegoesofcourseasajarontheclasspathordirectlyinthesourceofExplorer

Marc
December16,2013

Thanks,itswellexplainedandworkedrightaway.
NowIhaveasuggestionifImay.Boththedateandenumpropertieshaveextraparameters
(datePatternandvalues).Ifwecouldhaveaccesstotheseparameterswithcustom
properties,itwouldbegreat!
(thatorsomegenericparameters)

JoramBarrez
December19,2013

@Marc:thatispossible
forexample:
@Override
publicFieldgetPropertyField(FormPropertyformProperty){
//Writablestring
PopupDateFielddateField=newPopupDateField(getPropertyLabel(formProperty))
StringdatePattern=(String)formProperty.getType().getInformation(datePattern)
dateField.setDateFormat(datePattern)

Marc
December20,2013

ThanksfortheprecisionJoram.
ButIstillhavetroublegettingtheinformation.
FirstofallIshouldhavementionedthatIusetheRESTAPItoretrievetheform.
ButevenusingthenormalAPI,Ihaveaproblem.WhenIimporttheXMLfile,datePatternis
readbyFormPropertyParser.parseChildElement.ButwhenIdeploythefile,itlookslikethe
fileisparsedagainbutthistimedatePatternhasdisappeared(xtr.getAttributeValuereturns
nullwhereastheotherattributesarecorrectlyread).SodatePatternisnullinthe
BpmnModel.
Iguessduringdeploymentitsthenottheoriginalfilethatisreadbutaversionthatis
generatedforthepurpose?

JoramBarrez
January8,2014
http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

8/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

Sorryforthedelayinresponding(christmanholidays).
Icheckedourtestsuite,andwedotestthis:

whichistestedinthisway:
property=startFormData.getFormProperties().get(1)
assertEquals(start,property.getId())
assertNull(property.getValue())
assertTrue(property.isReadable())
assertTrue(property.isWritable())
assertFalse(property.isRequired())
assertEquals(date,property.getType().getName())
assertEquals(ddMMMyyyy,property.getType().getInformation(datePattern))
DoImisunderstandyourissue?

TomC
January28,2014

Joram,IamhavingasimilarissueinthatIamtryingtocreatearadiobutton
formtype(modeledaftertheEnumFormType).Icancreatethetypenoproblem.
publicclassRadioFormTypeextendsAbstractFormType{
protectedMapvalues
publicRadioFormType(Mapvalues){
this.values=values
}
publicStringgetName(){
returnradio
}
@Override
publicObjectgetInformation(Stringkey){
if(key.equals(values)){
returnvalues
}
returnnull
}
@Override
publicObjectconvertFormValueToModelValue(StringpropertyValue){
validateValue(propertyValue)
returnpropertyValue
}

http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

9/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

@Override
publicStringconvertModelValueToFormValue(ObjectmodelValue){
if(modelValue!=null){
if(!(modelValueinstanceofString)){
thrownewActivitiIllegalArgumentException(ModelvalueshouldbeaString)
}
validateValue((String)modelValue)
}
return(String)modelValue
}
protectedvoidvalidateValue(Stringvalue){
if(value!=null){
if(values!=null&&!values.containsKey(value)){
thrownewActivitiIllegalArgumentException(Invalidvalueforradioformproperty:+value)
}
}
}
}
Ihavethenewpropertyloadingatstartup.Alsoworking
ListcustomFormTypes=newArrayList()
customFormTypes.add(newFileFormType())
customFormTypes.add(newTextAreaFormType())
customFormTypes.add(newRadioFormType())
((ProcessEngineConfigurationImpl)
processEngineConfiguration).setCustomFormTypes(customFormTypes)
Icancreatemyprocessinthedesigner,setthetypetoradiothenIsetthevaluesasI
wouldforanenumtype.Itsavesoutfinetothexml.
WehaveourownGUIandwhenItryandgetthevalues
Mapvalues=(Map)formProperty.getType().getInformation(values)
Igetanullpointererror.FromwhatIcanseebytracingthruthecodeonlytheenumtypehas
thevaluesloaded.IhaveothercustomtypeswhereIgetthevaluesdynamicallyfroma
databaseandthatworksbutIreallyneedtoaccessthevaluesstoredintheprocess
definition.
Anythoughts?
Thanks

Marc
March18,2014
http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

10/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

@Joram,IrealisewhatIpresentedwasconfusing.
Myproblemisthefollowing:
IwanttodefineanewFormTypeanduseitlikethisintheprocessXML:
ThenIwanttoretrievethefloorsparameter.Imopenashowtopassit.Itcouldbeina
activiti:valuetag,inadatePatternparameteroranythingelse,aslongasIcangetit.
SoIcreateanewclass:
publicclassBuildingTypeextendsAbstractFormType{

publicvoidsetFloors(Stringfloors){

}
Itisrecognised(Iaddedtheentryintheconfigurationfile).
NowIwanttoretrievethefloorcountwhentheprocessarrivestothespecifictask
TaskFormDataformData=processEngine.getFormService().getTaskFormData(task.getId())
FormPropertyproperty=formData.getFormProperties().get(0)
FormTypebuildingType=property.getType
AlasIhavenoinformationinbuildingType.
Anypointer?
Thanks,
Marc

Marc
March18,2014

TheXMLpartofmypreviouspostisnotdisplayed.
Hereitis:
<activiti:formPropertyid=buildingname=Buildingtype=buildingTypefloors=10
required=true>

JoramBarrez
April1,2014

http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

11/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

Ifyouaddnewelementtotheschema(whichispossible),youwillalsoneedtoextendthe
BpmnXmlConvertersimafraid,otherwisetheywontbepickedup.
Anotherhackywaycouldbetomisusethevalueelementegtostorejson,thatcontainsboth
thebuildingTypeandthe10value.

AddingcustomformtypeinActiviti5.17|FYTROSPORTS
April30,2015

[]InparticulariwanttocreateacomboBoxthatfillsupwithdatafromadatabase(PostgreSQL),andim
followingthispost:http://www.jorambarrez.be/blog/2013/03/13/creatinganewformpropertyinactiviti/[]
Akshay
January29,2016

Hey,Ifollowedthesametutorial.
InsteadofusingcomboBoxIrenderedTableinmyapplication.
andgivenitnameasmapinsteadofmonthasdemonstratedabove.
butwhilerunningthisitsaysunknowntypemapmap.
Ithinkiammissingsomethingpleasecanyouhelp??
thanks,

JoramBarrez
February5,2016

@Akshayhaveyouregistereditwiththeengine?Thaterrorseemstopointinthat
direction.ordoyoumeanitsshowingthatintheUI?

LeaveaReply
Youremailaddresswillnotbepublished.

Name
Email
Website
PostComment

CopyrightSmallstepsw ithbigfeet
Pow eredByWordPressThemeBySiteOrigin
http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

12/13

10/10/2016

Creating a new form property in Activiti | Small steps with big feet

http://www.jorambarrez.be/blog/2013/03/13/creating-a-new-form-property-in-activiti/

13/13

Vous aimerez peut-être aussi