Alfresco FormService Fundamental WRONG - alfresco

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.

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

Workflow: Setting default value for bpm:assignee

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);
}
}

maximo anywhere adding new view not working

I am trying to add a new view in our application. For time being adding this view as the first page in the app. Created necessary OSLC resources in maximo and also verified that I am able to view the data by hitting the URL (ip,userid,pw removed intentionally).
http://{ipaddress}:7001/maximo/oslc/os/ABS_VERI_POINTS?_lid={maximoadminuser}&_lpwd={maximoadminpw}&oslc.select=*
I have also added the view and the resources in app.xml file but when I am logging in to the application it gives me the following message
"WorkList Record Could Not be Downloaded. If Problem persists, Contact your administrator"
After than it landed up into the view with No data. Upon inspecting the UI in browser I noticed I am getting the following error
Procedure invocation error. Runtime: Failed to parse JSON string
Error 404--Not Found
....
....
Resource Data in app.xml is as follows
<resource describedBy="http://jazz.net/ns/ism/asset/smarter_physical_infrastructure#ABS_VERI_POINTS" id="resabsVP" name="resabsVP" providedBy="/oslc/sp/SmarterPhysicalInfrastructure">
<attributes id="absVPAttrs">
<attribute describedByProperty="spi:parent" id="vpparent" name="parent"/>
<attribute describedByProperty="spi:location" id="vplocation" name="location"/>
<attribute describedByProperty="spi:assetnum" id="vpassetnum" name="assetnum"/>
<!-- attribute describedByProperty="spi:abs_verification_pointsid" id="vpabsvpid" name="absvppointsid" -->
<attribute describedByProperty="spi:taskid" id="vptaskid" name="taskid"/>
<attribute describedByProperty="spi:description" id="vpdescription" name="description"/>
<attribute describedByProperty="spi:wonum" id="vpwonum" name="wonum"/>
</attributes>
<queryBases id="absvpqry">
<queryBase id="absvpqry1" name="getabsvp" queryUri="oslc/os/ABS_VERI_POINTS" />
</queryBases>
</resource>
View in app.xml as follows
<view id="absVPview" label="ABS Verification Points">
<requiredResources id="absVPAttrs11">
<requiredResource name="resabsVP" id="resabsVP11">
<requiredAttribute id="vpdescription1" name="description"/>
<requiredAttribute id="vpwonum1" name="wonum"/>
<requiredAttribute id="vpparent1" name="parent"/>
</requiredResource>
</requiredResources>
<list id="VP.abs_veri_points_list" resource="resabsVP" >
<listItemTemplate id="VP.abs_veri_points_list_listItemTemplate" layout="InspectionListItem">
<listtext id="VP.abs_veri_points_list_vpid" resourceAttribute="description" layoutInsertAt="item1"/>
<listtext id="VP.abs_veri_points_list_wonum" resourceAttribute="wonum" layoutInsertAt="item2"/>
<listtext id="VP.abs_veri_points_list_parenttext" resourceAttribute="parent" layoutInsertAt="item3"/>
</listItemTemplate>
</list>
</view>
Can you please give any clue whats going wrong here
Can you open a PMR on this with our support? This may be a bug where we're not correctly handling underscores in our OSLC request url to retrieve data. Also, check the URL that is failing in your javascript console, just to make sure that it's really this resource throwing the 404 exception. You might check the network tab of the debugger to see that.
#MDutta,
If the issue is in the object/attribute using underscore ("_"), you can fix this by updating the xsd validation file located at ..\Anywhere\lib\codegen\artifac-processor-7.5.2.jar.
Unzip this file and open the app.xsd located: ..\resource\xsd\app.xsd. Modify the validation
From:
<xs:simpleType name="string">
<xs:restriction base="xs:string">
<xs:pattern value="[a-zA-Z][a-zA-Z0-9]+"/>
</xs:restriction>
</xs:simpleType>
To:
~dk

How to move a content type definition created TTW to the file system

I was modeling a content type definition using the web interface on the Dexterity Types control panel configlet in order to include the resulting code in my project:
I ended up with a file like this one, that includes a RichText field:
<model
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
xmlns:security="http://namespaces.plone.org/supermodel/security"
xmlns:marshal="http://namespaces.plone.org/supermodel/marshal"
xmlns:form="http://namespaces.plone.org/supermodel/form"
xmlns:indexer="http://namespaces.plone.org/supermodel/indexer"
xmlns="http://namespaces.plone.org/supermodel/schema">
<schema>
...
<field name="biography" type="plone.app.textfield.RichText">
<description>A detailed description of a person's life.</description>
<required>False</required>
<title>Biography</title>
</field>
...
</schema>
</model>
I copied that file to a directory inside my project that I called models.
I exported also the type information and I edited the file to look like this:
<?xml version="1.0"?>
<object name="mytype" meta_type="Dexterity FTI">
...
<property name="schema">my.project.content.IMyType</property>
<property name="klass">my.project.content.MyType</property>
...
</object>
Then I added the following code inside my content.py module:
from plone.dexterity.content import Item
from plone.supermodel import model
class IMyType(model.Schema):
"""My Type."""
model.load('models/mytype.xml')
class MyType(Item):
"""My Type."""
Finally, I added some basic tests but they are failing with the following error (full traceback here):
ConfigurationExecutionError: <class 'plone.supermodel.parser.SupermodelParseError'>: Field type plone.app.textfield.RichText specified for field biography is not supported
What I am doing wrong here? Did I forget something?

Add computed metadata to catalog for dexterity object (plone 4)

I want to create a catalog metadata with a computed string. So following Aspeli's book and the developer manual I proceeded to create an indexer:
# indexer.py
#grok.adapter(Entry, name='bind_representation')
#indexer(Entry)
def bindIndexer(context):
print str(IBindRepresentable(context))
return str(IBindRepresentable(context))
and register the index with genericSetup:
<!-- profiles/default/catalog.xml -->
<?xml version="1.0"?>
<object name="portal_catalog" meta_type="Plone Catalog Tool">
<index name="bind_representation" meta_type="ZCTextIndex">
<!-- I tried with meta_type="FieldIndex" too -->
<indexed_attr value="bind_representation"/>
<!-- copied from other text metadata -->
<extra name="index_type" value="Okapi BM25 Rank"/>
<extra name="lexicon_id" value="plaintext_lexicon"/>
</index>
</object>
The problems are: (1) only the index is registered, not the metadata, and (2) After reindex all the zodb, bind_representation still doesn't find any entry to index, even when they are.
The examples cited only deal with pre-existent indexes, so I'm not sure about the content of catalog.xml. bindIndexer seems not to be called at all, since its print statement is never executed. I copied bindIndexer to entry.py too, to get sure it wasn't being ignored, but still nothing.
What am I missing?
Thanks.
1- In order to add a new metadata, you have to use this syntax:
<?xml version="1.0"?>
<object name="portal_catalog" meta_type="Plone Catalog Tool">
...
<column value="bind_representation"/>
</object>
2a- you are adapting your content class, you should adapt your content interface (IEntry most likely).
2b- you are using a ZCTextIndex: that index won't show you all entries anyway (even following the previous point) because it's based on a lexicon. You should probably use this instead (unless you have specific bounds):
<index name="bind_representation" meta_type="FieldIndex">
<indexed_attr value="bind_representation"/>
</index>
More info:
http://bluebream.zope.org/doc/1.0/manual/componentarchitecture.html#adapters
http://maurits.vanrees.org/weblog/archive/2009/12/catalog

Resources