Spring-Webflow Using a HTML link to signal an event - spring-webflow

I am playing around with Spring-Webflow (2.3), ZK (5.0.7.1) and ZK Spring (3.0).
Actually I'm trying to signal an event with a HTML link as described at Spring-Webflow.
<a href="${flowExecutionUrl}&_eventId=go2ProjectRoomView" >2 Project</a>
Part of my flow definition file looks like:
<view-state id="mainView">
<transition on="go2ProjectRoomView" to="projectRoomView" bind="false"/>
</view-state>
<view-state id="projectRoomView">
<transition on="go2MainView" to="mainView" bind="false"/>
</view-state>
If I deploy my web project and navigate to the main view following error appears:
The reference to entity "_eventId" must end with the ';' delimiter
Same error happens if I replace _eventId=go2ProjectRoomView by _eventId_go2ProjectRoomView.
Link to full stack trace.

The error you are receiving is actually an HTML/XML parsing error. Ampersand (&) is used to reference special characters/entities (see here). Change your link to:
<a href="${flowExecutionUrl}&_eventId=go2ProjectRoomView" >2 Project</a>
and you should be ok.

Related

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

Override Alfresco pickerresults.lib.ftl

I've found a bug in pickerresults.lib.ftl that i have already reported
Briefly: if the user does not have the permission on a file parent, the line
<#if row.item.parent??>"parentName": "${row.item.parent.name!""}",
will fail, failing the entire script (and the user can't see any file)
So, waiting for the bug being resolved i need to patch this. I'd like to override the macro "pickerResultsJSON" defined in the file removong the line or putting a string value in place of "${row.item.parent.name!""}" that cause the exception
I have no idea of how to redefine the macro and where to place the file inside my amp. Can someone help me?
UPDATE
I'm using the Alfresck SDK 2.0 and my project structure is:
I've tryed to put a file "custom-pickerresults.lib.ftl" with the following content (as suggested by sev) but it does not seem to be the right position. Or should i "register" it in some way?
<#macro pickerResultsJSON results>
<#-- new code here -->
</#macro>
<#global pickerResultsJSON = pickerResultsJSON />
Since macros are just variables, you might be able to do something like this:
<#macro pickerResultsJSON>
<#-- new code here -->
</#macro>
<#global pickerResultsJSON = pickerResultsJSON />
As to where you would put that... you could put it in any file that is included globally on your project. It might require a little trial and error since I'm not sure what your project structure is.
Many thanks to sev, he pointed me the right way.
I realized that pickerresults.lib.ftl is used by the webservice pickerchildren.get.desc.xml and pickerchildren.post.desc.xmlso, the solution is to copy the web service definition and files along with the library in
/alfresco-myamp-repo/src/main/amp/config/alfresco/extension/templates/webscripts/com/my/repository/forms/
(repository/forms/ just becouse the original files are inside config/alfresco/templates/webscripts/org/alfresco/repository/forms/ but any other folder under /alfresco-myamp-repo/src/main/amp/config/alfresco/extension shuld do)
and change the library like this:
...
"type": "${row.item.typeShort}",
"parentType": "${row.item.parentTypeShort!""}",
<#-- from here -->
<#attempt>
<#if row.item.parent??>"parentName": "${row.item.parent.name!""}",</#if>
<#recover>
"parentName": "<unknown>",
</#attempt>
<#-- to here -->
"isContainer": ${row.item.isContainer?string},
<#if row.container??>"container": "${row.container!""}",</#if>
...
This way even if the user has not the permissions to read the parent's name the template can complete without errors (i don't know if the value "unknown" in place of the parent name can cause any troubles, but i did not notice nothing right now)

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.

Spring webflow: how to keep track of persisted entity ids?

I'm working on a webflow (SWF2). The entities are generated using Roo. One of the webflow views, multi-instance.jspx, may be called multiple times to allow for multiple, persisted instances of the same entity (MyClass).
I'd like to keep a list of those persisted entities so that I can reference them on a later point in the flow. So far, I've tried the following.
A simplified version of my flow.xml looks like this:
<on-start>
<evaluate expression="new java.util.ArrayList()" result="flowScope.myList" result-type="java.io.Serializable"/>
</on-start>
<view-state id="multi-instance" view="multi-instance" model="myClass">
<binder>
<binding property="field1"/>
<binding property="field2"/>
</binder>
<on-entry>
<evaluate expression="new com.test.MyClass()" result="flowScope.myClass" />
</on-entry>
<transition on="another_instance" to="multi-instance"/>
<transition on="success" to="confirm"/>
<transition on="cancel" to="abort"/>
<on-exit>
<evaluate expression="myClass.persist()"/>
<evaluate expression="flowScope.myList.add(myClass)"/>
</on-exit>
</view-state>
The confirm and abort view-states are defined in flow.xml as well. The confirm.jspx looks like this:
<div xmlns:spring="http://www.springframework.org/tags" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:form="http://www.springframework.org/tags/form" xmlns:util="urn:jsptagdir:/WEB-INF/tags/util" xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<jsp:output omit-xml-declaration="yes" />
<form:form>
<c:forEach items="${myList}" var="instance">
<li>${instance.getField1()} ${instance.getField2()}</li>
</c:forEach>
<div class="submit">
<input type="submit" id="success" name="_eventId_success" value="success"/>
<input type="submit" id="cancel" name="_eventId_cancel" value="cancel" />
</div>
</form:form>
</div>
So to the question:
Whenever I hit confirm.jspx, the web return says that there's an exception thrown at org.springframework.webflow.engine.impl.FlowExecutionImpl.wrap(FlowExecutionImpl.java:569).
EDIT: The Apache log is a little more enlightening. The following is a snippet of the top of the call stack:
SEVERE: Servlet.service() for servlet jsp threw exception org.apache.jasper.JasperException:
/WEB-INF/views/myflow/confirmation.jspx(6,7)
The function getField1 must be used with a prefix when a default namespace is not specified
at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:40)
I'm not sure if the ArrayList-approach is possible; I believe I've read somewhere that the flowScope.myClass instance, as it is defined in the multi-instance-state, is picked up by the GC or at least falls out of scope. I'm not sure. If anyone can shed some light on that particular topic, I'd be thrilled.
(And if you happen to know a better way to keep a list of these persisted entities, please feel free to let me know!) Thanks in advance! :)
Update:
I'm able to count the number of elements in my list like so:
<c:choose>
<c:when test="${myList != null}">myList exists, it contains <c:out value="${fn:length(myList)}" /> items!</c:when>
<c:otherwise>myList doesn't exist.</c:otherwise>
</c:choose>
It shows the same number of elements as I've inserted. However, when I do this:
<c:forEach items="${myList}" var="instance">
<c:if test="${instance != null}">
<li>${instance.field1} ${instance.field2}</li>
</c:if>
</c:forEach>
nothing is displayed. (I can confirm that there is a correct number of <li>-elements when the null-test is omitted. Note also that I'm trying to access the properties directly, as indicated here: jstl/jsp - iterating over a vector of beans) I don't know what to think, regarding the scope here, but it seems clear that I can't access my entities via an ArrayList.
First, with regards to your question(s) around variable scoping, I would suggest looking at section 4.4 of the SWF documentation, where it describes all of the different available scopes.
Flow scope variables live through the lifetime of the flow. So your myClass variable will not go away until the flow exits. However keep in mind that your <on-entry> expression is assigning a new instance every time that view state is entered.
Second, I think you are probably on the right track with your solution. I would note several things:
You are persisting and adding to your list in the <on-exit> element -- this means these two things will always happen when you leave the state, including when you are doing your cancel transition. This may not be what you want. Related:
Your <transition on="another_instance" to="multi-instance"/> is actually exiting the view-state and re-entering it, triggering the <on-exit> and <on-entry> logic. It is possible to remain in the same state, by simply doing <transition on="another_instance">. Doing this will execute any logic you have inside the transition, and then re-render the view without actually changing states.
You may want to consider using the <var> tag to initialize variables... what you are doing with <evaluate expression="new ..."/> works but using <var> may be cleaner. Also, it is not necessary to say result-type="java.io.Serializable". result-type should be used when you need to convert the return type to something elese.
Finally, the error you are getting looks like it is unrelated to webflow. JSTL/EL allow you to access bean properties but not methods, and you are trying to invoke a method. See this question for more info.

Spring webflow 1.0 - Downloading a file

I am using spring webflow 1.0. I am uploading a csv file, parsing it, and displying results before proceeding. The user has an option to download a csv file that contains the records that did not pass validation. When I click the link in a JSP to download this file, webflow invokes a form Action. The form action writes out a file via getting the output stream off the response:
HttpServletResponse response = ((ServletExternalContext) context.getExternalContext()).getResponse();
I do not want to leave the jsp I'm currently on. I just want to download the file. In other words, I do not want to transition to another state. I just want to serve the dynamically rendered file. Everything works (I don't leave the page, and I download the file), but I'm getting the following error in my console:
_pEncydKfggPHJo8=org.springframework.webflow.engine.NoMatchingTransitionException: No transition was matched on the event(s) signaled by the [1] action(s) that executed in this action state 'downloadErrorReportAction' of flow 'myFlow'; transitions must be defined to handle action result outcomes -- possible flow configuration error? Note: the eventIds signaled were: 'array<String>[[null]]', while the supported set of transitional criteria for this action state is 'array<TransitionCriteria>[[empty]]'
at org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:187)
at org.springframework.webflow.engine.State.enter(State.java:191)
at org.springframework.webflow.engine.Transition.execute(Transition.java:212)
at org.springframework.webflow.engine.TransitionableState.onEvent(TransitionableState.java:107)
at org.springframework.webflow.engine.Flow.onEvent(Flow.java:534)
Truncated. see log file for complete stacktrace
Here is the relevant portion of my webflow config.
<view-state id="showUploadResults" view="UploadResults3.0">
<render-actions>
<action bean="UploadResultsAction" method="transitionToWebflow"/>
<action bean="UploadResultsAction" method="setupData"/>
</render-actions>
<transition on="submit" to="proceed"/>
<transition on="downloadErrorReport" to="downloadErrorReportAction"/>
</view-state>
<action-state id="downloadErrorReportAction">
<action bean="UploadResultsAction" method="downloadErrorReport" name="downloadErrorReport"/>
</action-state>
I was able to do this by defining a view-state and specifying a render action.
<view-state id="downloadErrorReportAction">
<render-actions>
<action bean="uploadResultsAction" method="downloadErrorReport" name="downloadErrorReport"/>
</render-actions>
</view-state>
I also had to add the same transitions from the previous action, because once you click the download link, you transition to another state. So the final config looks like the following:
<view-state id="showUploadResults" view="UploadResults3.0">
<render-actions>
<action bean="UploadResultsAction" method="transitionToWebflow"/>
<action bean="UploadResultsAction" method="setupData"/>
</render-actions>
<transition on="submit" to="proceed"/>
<transition on="downloadErrorReport" to="downloadErrorReportAction"/>
</view-state>
<view-state id="downloadErrorReportAction">
<render-actions>
<action bean="uploadResultsAction" method="downloadErrorReport" name="downloadErrorReport"/>
</render-actions>
<transition on="submit" to="proceed"/>
</view-state>

Resources