Workflow: Setting default value for bpm:assignee - alfresco

When I start my workflow, I want the option to assign it to somebody. If nobody is chosen, I want to default to assign it to the initiator.
Is this possible to do without creating a new model that extends bpm:assignee? If not, how would that extension be accomplished?
I believe this answer from Jeff Potts is relevant: https://stackoverflow.com/a/9418066/4542428
Note: I am using Community edition 4.2
EDIT: Stefan's answer got me the vast majority of the way to the answer, but it seems that I am somehow referencing the value of the association incorrectly. Context: I've never used associations, and this is likely just my failure to understand their difference from types and aspects.
From my model:
<type name="deliveryTicketWorkflow:start">
<parent>bpm:startTask</parent>
<properties>
</properties>
<associations />
<overrides />
<mandatory-aspects>
<aspect>deliveryTicketWorkflow:pmAspect</aspect>
<aspect>deliveryTicketWorkflow:requestDetailsAspect</aspect>
</mandatory-aspects>
</type>
<aspect name="deliveryTicketWorkflow:pmAspect">
<associations>
<association name="deliveryTicketWorkflow:assignedPM">
<source>
<mandatory>false</mandatory>
<many>false</many>
</source>
<target>
<class>cm:person</class>
<mandatory>false</mandatory>
<many>true</many>
</target>
</association>
</associations>
</aspect>
Which is used by my config as:
<config condition="activiti$deliveryTicketWorkflow" evaluator="string-compare">
<forms>
<form>
<field-visibility>
...
<show id="deliveryTicketWorkflow:assignedPM" />
...
</field-visibility>
<appearance>
...
<field id="deliveryTicketWorkflow:assignedPM" label-id="Project Manager" />
...
</appearance>
</form>
</forms>
</config>
My config for deliveryTicketworkflow:start is identical. This successfully displays the person selector, without making it mandatory, exactly 100% as Stefan said it would.
In my bpmn workflow definition, I then have these snippets in an execution listener for the start event:
if(!execution.getVariable("deliveryTicketWorkflow_assignedPM")){
execution.setVariable("deliveryTicketWorkflow_assignedPM", initiator);
}
...
deliveryTicket.properties["dtdlm:projectManager"] = execution.getVariable("deliveryTicketWorkflow_assignedPM").properties.firstName + " " + execution.getVariable("deliveryTicketWorkflow_assignedPM").properties.lastName;
When the workflow is run and I select somebody as the PM, that final line (where the first and last name of the PM is grabbed) returns a value of undefined for "deliveryTicketWorkflow_assignedPM". When it is left blank, everything works swimmingly but the General Info section of the Workflow description still lists the Project Manager as (None).

You could indeed customize the people picker, as jeff describes, but it requires quite some coding effort.
Alternatively you could use a workflow executionlistener for event start, and use it to set the bpm_assignee variable to the initiator in case it was empty on the form:
Add listener to you bpmn20:
<activiti:executionListener event="start" class="com.mycomp.Executionlistener"></activiti:executionListener>
In your first usertask, define the assignee to the association property in your workflow start form.
<userTask id="firsttask" name="firsttask" activiti:assignee="${mymodel.myassoc.properties.userName}" >
Also add this association to your start task content model.
Code in com.mycomp.Executionlistener will look like this:
public void notify(DelegateExecution execution) throws Exception {
if (execution.getVariable("mymodel_myassoc") == null ){
ActivitiScriptNode userScriptNode= (ActivitiScriptNode) execution.getVariable("initiator");
execution.setVariable("mymodel_myassoc",userScriptNode);
}
}

Related

How to override some of ajax based picker logic?

Alfresco Community v5.2 (other versions too) includes some of preconfigured workflows that available on the page /share/page/start-workflow
I'm interested in "Review and Approve (one or more reviewers) - Assign a review task to multiple reviewers".
Actually, to be more precise - in the logic of assigning.
For example, I want to make some customization - Customization of the user task screen
I want to display members in the table, not in the list. For this I need to understand how they appear in the list.
In the file share-config-custom.xml I can find the path to the templates.
For example, for the bpm:workflowDueDate it will be:
...
<field id="bpm:workflowDueDate" set="info" label-id="workflow.field.due">
<control template="/org/alfresco/components/form/controls/info.ftl" />
</field>
...
But for bpm:assignees the template is not specified:
...
<field id="bpm:assignee" label-id="workflow.field.reviewer" set="assignee" />
...
I assume, that there are some back-end beans, that perform most of the logic.
How can I override some of ajax based picker logic?
If a form control is not provided in the share form config, Alfresco Share falls back to some defaults depending on the type of the field.
bpm:assignee is an association to a person node, so I would expect it to point by default to association.ftl !
What I suggest is to copy that file into a new one let's say src/main/amp/alfresco/site-webscripts/${project.groupId}/form/controls/custom-association.ftl
and then in your share-config-custom.xml copy over the form config for the task with one small update :
...
<field id="bpm:assignee" label-id="workflow.field.reviewer" set="assignee" >
<control template="/${project.groupId}/form/controls/custom-association.ftl" />
</field>
...
and then you can safely fiddle with custom-association.ftl because it is almost never a good idea to override alfresco defaults !
UPDATE : The value of that control is a list of nodeRefs referring to the nodes of the selected users. It is the ObjectFinder Java script object who is managing things behind the scene, calling a special endpoint to fetch all sort of data to be shown, then manipulates the DOM accordingly ! You might want to look at object-finder.js and picker.inc.ftl

TestNG groups depending on the same group. Which one should get executed first?

I have two test groups which are dependent on another group.
<dependencies>
<group name="search" depends-on="login" />
<group name="addnew" depends-on="login" />
</dependencies>
Which one out of the two groups (search, addnew) should ideally get executed first? For me, the group addnew is getting executed first all the time, which I don't want to happen. I want search to get executed and then addnew to get executed, once login is done. Also, I have set "preserve-order" for the test as true. Any suggestions?
If you want search to get executed first, then add new is also dependent on search group in that case. You can specify a list of groups in the depends-on list. Try with depends-on="login search" or you can let search depend on login and make add new depend on search to guarantee execution order.
Quote from documentation: "By default, TestNG will run your tests in the order they are found in the XML file. If you want the classes and methods listed in this file to be run in an unpredictible order, set the preserve-order attribute to false:"
<test name="Regression1" preserve-order="false">
<class name="test.Test1">
<methods>
<include name="m1" />
<include name="m2" />
</methods>
</class>
<class name="test.Test2" />

Alfresco FormService Fundamental WRONG

Alfresco Forms Service does not work properly.
Looks like a fundamental Form functionality does not pass form configs (control-param name="nameHere") to webscripts.
I reproduce it step-by-step.
Create the Freemarker template and register it according to the documentation under /share project. The component renders and shows successfully. Everything works well.
Create a form according to the documentation on wiki Forms page.
Register it in <TOMCAT_INST/shared/classes/alfresco/web-
extension/myclok-form-config.xml> directory and pass it for load in such manner:
<bean id="sampleShareConfig" class="org.springframework.extensions.config.ConfigBootstrap" init-method="register">
<property name="configService" ref="web.config" />
<property name="configs">
<list>
<value>classpath:alfresco/web-extension/myclok-form-config.xml</value>
</list>
</property>
</bean>
<!-- ... share/WEB-INF/classes/org/springframework/extensions/surf/bootstrap/forms-bootstrap-context.xml -->
Form inst:
<config>
<forms>
<form id="myclok">
<view-form template="/org/alfresco/components/myclok/myclok.get.html.ftl" />
<edit-form template="/org/alfresco/components/myclok/myclok.get.html.ftl" />
<create-form template="/org/alfresco/components/myclok/myclok.get.html.ftl" />
<field-visibility>
<show id="currentPath" />
</field-visibility>
<appearance>
<field id="currentPath">
<control name="currentPath" template="/org/alfresco/components/myclok/myclok.get.html.ftl">
<control-param name="currentPath">sampleData1</control-param>
</control>
</field>
<control name="currentPath" template="/org/alfresco/components/myclok/myclok.get.html.ftl">
<control-param name="currentPath">sampleData2</control-param>
</control>
</appearance>
</form>
</forms>
</config>
In official documentation is written:
If the form element exists within a config element without an
evaluator and condition the form is always found, this is useful if
you want a certain field to appear on EVERY form in your application.
So, I specified it in myclok-form-config.xml file, but this approach does not give any result. Thus when the component with such reference to param is loaded by the following URL <http://localhost:8080/share/page/site/wcmqs/myclok> the Alfresco fails with the Exception:
Exception: freemarker.core.InvalidReferenceException - Expression field is undefined on line 6, column 6 in org/alfresco/components/myclok/myclok.get.html.ftl.
freemarker.core.TemplateObject.assertNonNull(TemplateObject.java:125)
freemarker.core.TemplateObject.invalidTypeException(TemplateObject.java:135)
freemarker.core.Dot._getAsTemplateModel(Dot.java:78)
In other words it's impossible to receive the value of the parameter of currentPath that is defined in FormConfigs.
So, the minimal functionality of FormsService / ConfigService does not work.
<#if field.control.params.currentPath??>
<#assign path=field.control.params.currentPath>
<#else>
<#assign path="someOtherDataValue">
</#if>
Does anyone know how to resolve it Or can demonstrate a working sample?
PS: All above described configurations of the form of FormService and the webscript component are attached.
The .AMP file for quick installation is required just to invoke the following command:
java -jar alfresco-mmt.jar install myclokStubFormComponent.amp ../tomcat/webapps/share.war
AMP file.
Config file.
I think you have mis-understood the difference betweent a form template and a field template. You are specifying the same file /org/alfresco/components/myclok/myclok.get.html.ftl to control the layout of the form as well as to render your fields.
When you use a field template to render the form you are getting an error that says the field object has not been populated. This is quite correct as the framework has not yet started to render the individual fields. You are rendering the form.
I'd suggest you try some more basic examples such as those that come with the Forms Development Kit (FDK) before you start implementing your own more complex forms, and especially before you begin to claim that the framework does not work as documented.

Group testNG tests without annotations

I'm responsible for allowing unit tests for one of ETL components.I want to acomplish this using testNG with generic java test class and number of test definitions in testng.xmlpassing various parameters to the class.Oracle and ETL guys should be able to add new tests without changing the java code, so we need to use xml suite file instead of annotations.
Question
Is there a way to group tests in testng.xml?(similarly to how it is done with annotations)
I mean something like
<group name="first_group">
<test>
<class ...>
<parameter ...>
</test>
</group>
<group name="second_group">
<test>
<class ...>
<parameter ...>
</test>
</group>
I've checked the testng.dtd as figured out that similar syntax is not allowed.But is therea workaround to allow grouping?
Thanks in advance
You can specify groups within testng.xml and then run testng using -groups
<test name="Regression1">
<groups>
<run>
<exclude name="brokenTests" />
<include name="checkinTests" />
</run>
</groups>
....
No, this is not possible at the moment.
As a rule of thumb, I don't like adding information in XML that points into Java code, because refactorings might silently break your entire build.
For example, if you rename a method or a class name, your tests might start mysteriously breaking until you remember you need to update your XML as well.
Feel free to bring this up on the testng-users mailing-list and we can see if there's interest for such a feature.
--
Cedric

NHibernate StaleObjectStateException when using version optimistic locking for an object with a one-to-many relationship

I am using NHibernate and ASP.Net using a session per request as suggested in the best practices article by Billy McCafferty (sorry, I cannot include the link). I have used this successfully with version optimistic locking, saving updated objects in the HTTP Session object and reattaching to the NHibernate session using the SaveOrUpdate method.
However, my latest page requires the update of a collection of child objects. I used the method suggested in the parent child example of the NHibernate manual (Chapter 17). This works when loaded and saved in a single request. However, when loaded in one request, saved in the HTTP Session, and reattached in a subsequent request using SaveOrUpdate, I get a StaleObjectException when flushing the NHibernate session. This happens even if no changes are made to the child object collection.
Changes that are made to the parent object's properties are saved to the database, so it would appear that NHibernate is trying to update the object twice. I suspect that this is something to do with the cascade options in the mapping, but these are required in order to get the parent/child relationship working correctly.
Here are my mapping files:
Parent Class Mapping
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="NHS.WebTeam.PharmacyFirst.Medication, PharmacyFirst" table="Medication" lazy="false" optimistic-lock="version" where="Deleted=0">
<id name="ID" column="Medication_ID" unsaved-value="0">
<generator class="identity" />
</id>
<version column="version" name="Version"/>
<property name="Deleted" column="Deleted" />
<property name="Name" column="Name" />
<bag name="Prices" access="field.camelcase-underscore" lazy="false" inverse="true" cascade="all">
<key column="Medication_ID"/>
<one-to-many class="NHS.WebTeam.PharmacyFirst.MedicationPrice, PharmacyFirst" />
</bag>
</class>
</hibernate-mapping>
Child Class Mapping
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="NHS.WebTeam.PharmacyFirst.MedicationPrice, PharmacyFirst" table="Medication_Price" lazy="false" optimistic-lock="version" where="Deleted=0">
<id name="ID" column="Medication_ID" unsaved-value="0">
<generator class="identity" />
</id>
<many-to-one name="Medication" column="medication_id" not-null="true" cascade="none"/>
<property name="DateFrom" column="Date_From" />
<property name="Price" column="Price" />
</class>
</hibernate-mapping>
Please can somebody help.
For anyone else finding this, it appears the issue has been fixed in nhibernate 2.1, so you should just update.

Resources