Calling Web Services using Process Server

Process Server has had a mashup control since version 9.1.3, called TriggerPanel. It could be used to trigger a process flow without returning data from the flow itself.
In Lawson Smart Office 10.0.0 the TiggerPanel supports a synchronous call which means that it is possible to run a flow and bring in data from the process back to the Mashup.

In order for the mashup to be able to automatically generate a UI and to be able to create an object model that can be used for easy binding the XML has to be according to a specific schema.

The XML schema describes a Header section and any number of Detail sections. The service has to at least return an xml document with only the root. The root element name is ProcessResponseHeaderDetails. Returning no Xml at all will result in an error dialog informing that no data was returned from the service.

But what if the schema does not fit with what you want to achieve and it is hard to form your xml from third parties into that schema? Then there is always the option of setting IsOutputEnabled to false, as well as IsAutoLayoutEnabled to false and finally IsValidationEnabled to false. In that scenario you will have access to the XmlDocument returned in the OutputXml property and you have to manually create the UI and bind values from the XML using XPath. In order to succeed with this you will need to have a tool where you can try your XPath expressions. Writing XPaths isn’t easy. But using the Trigger panel with the automatically generated UI is easy.

Different ways to use the TriggerPanel with synchronous calls
1. Automatically generated UIs and Xml that follows the schema
2. Manually build UIs and Xml that follows the schema
3. Consuming any Xml using manual build UIs and XPath bindings

Mashup Designer UI

Four new parameters are visible in the UI. They represent the following properties (same order as in the screenshot):

IsAsynchronous
Default is true so you need to set it to false to make a synchronous call.

IsAutoLayoutEnabled
Default is true. You need to set it to false if you want to create your own UI within the TriggerPanel for the output.

IsConversionEnabled
Specify if data received from a synchronous call should be converted to .Net classes. Conversion requires the meta-data within the XML response. Conversion is important when formatting dates and numbers and if the TriggerPanel feeds data that are not strings into other mashup controls or when connecting the data to controls that require specific types such as charts. Default value is true.

IsValidationEnabled
If the XML returned should be validated against the schema. If the XML is not valid according to the schema a dialog will inform the user of this. However if the XML is partly valid anything that is parable will still be parsed to objects and generated UI for. Default is false.

Automatic UI generation
The default layout is to have the response displayed below the trigger form. It is optional to have the form and button; a flow can just as well be triggered via a mashup event.

Automatic UI generation is needed when the response XML can change in its structure between calls.
If you want the Response UI to be generated beside the input form you have to manually edit the Xaml within the TriggerPanel.
Locate the and move it as you see fit. Note that the name of the grid is PART_OutputXXXX were XXXX is the name of the TriggerPanel. If you change the name of the panel you need to change the name of the grid as well. If no grid is found the content of the TriggerPanel will show the UI and if you had an input form that form will be removed.

If you add two columns to the grid you can add the input panel in one column and have the output next to the input form.

Image of a trigger panel with a button (see picture below). In a real scenario the button should not be visible and the flow should instead be triggered by the TriggerFlow event.

After the call has been completed the response is generated below any input form, in this case the button.
The dynamic UI has its advantage since it adapts to the XML but layout and sizing or lists are automatic. If you need to control the UI then you can work with a custom UI and use bindings against the data returned.

Creating a custom UI

To be able to create a custom UI you need to manually edit the Xaml. First you need to set IsAutoLayoutEnabled to false. Then you need to build your Xaml using bindings against the objects model that represents the structure of the schema.

Example bindings when controls are placed within the TriggerPanel:

<!--Get the title property from the header block-->
Text=”{Binding Output.Header.Title}”

<!-- Gets the first Value in the HeaderDetails section. Use the index (0 in the example) to bind to data.-->
Text=”{Binding Output.Header[0]}”

<!-- Gets the value for the Name NameString. Use the name of the field to bind to data. Similar with the Columns but those must have meta data to describe them.-->
Text=”{Binding Output.Header[NameString]}”

<!-- Binds to a list of records. Used as ItemsSource for a list or datagrid or gridview. Details[i] for the first detail section in the Xml.-->
ItemsSource=”{Binding Output.Details[0].Records}”

<!-- Bind to a value in a record, in this case the first column “[i]” or the name of the Column.-->
DisplayMemberPath=”[0]” or “[NameString]”

There is also the option of collapsing content once the response is received if it contains no data. Use the NotNullToVisibilityConverter in Mango.UI.Utils.

<Grid.Resources>
<utils:NotNullToVisibilityConverter x:Key="visibilityConverter" />
</Grid.Resources>

<!-- And later in the xaml set visibility-->
Visibility="{Binding Path=Output.Details[1], Converter={StaticResource visibilityConverter}}"

If you in some scenarios have a second detail section this would collapse the control containing that info – leaving more space for other content.
DataGrid binding example:

<DataGrid Grid.Row="2" Width="300" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="3" Grid.RowSpan="3" AutoGenerateColumns="False" ItemsSource="{Binding Path=Output.Detail.Records}" CanUserAddRows="False" CanUserDeleteRows="False" Style="{DynamicResource styleDataGrid}" >
<DataGrid.Columns>
   <DataGridTextColumn Binding="{Binding [0], Mode=OneWay}" Header="Name"
    IsReadOnly="True" />
   <DataGridTextColumn Binding="{Binding [1], Mode=OneWay}" Header="Hire Date"
    IsReadOnly="True" />
   <DataGridTextColumn Binding="{Binding [2], Mode=OneWay}" Header="Age"
    IsReadOnly="True" />
</DataGrid.Columns>
</DataGrid>

Consuming any Xml
The Xml returned from ProcessFlow is always available for asynchronous calls in the OutputXml property. The data model is available in the Output property. If your Xml does not fit with the schema that LSO used you can chose to consume the pure Xml and create a custom UI. What you need to do is to set the following properties:

– IsAsynchronous=false. Or it will not be a synchronous call

– IsConvertionEnabled=false. No support for this since you will be using the xml response directly.

– IsAutoLayoutEnabled=false. No automatic layout supported.

– IsOutputEnabled=false. Output is the property for the object model. By setting this property to false you avoid getting error messages in the log as the TriggerPanel will try and read the Xml to the object model.

You create your Xaml and read up on XPath expressions.

Passing values to events

Variables values that are input to a transaction are available as field names using the indexer directly e.g. [MyFirstVariable]. If you need to send one of the response values from the TriggerPanel to another panel you need to map the TriggerSuccess Event and in the event bind in the values from the panel similar to this:

<mashup:Event TargetName="M3List" TargetEventName="TriggerFlow" SourceName="mikeSync">
  <mashup:Parameter TargetKey="CUNO" Value="{Binding ElementName=”mikeSync”, Path=Output.Header[0]}" />
</mashup:Event>

6 thoughts on “Calling Web Services using Process Server

  1. Alain

    Hi Karin
    I am trying to use the Automatic UI generation but I cannot find the XML pre defined schema. I kind of make my way through with the errors from LSO log but this is quite laborious.
    Where is this xml schema url? Ideally I would like to use the IPA XML node. Or maybe you can share the xml from your example?
    Many Thanks
    Alain

    Reply
    1. karinpb Post author

      Hi Alain,
      It’s been a while since I build the control and the mashup. Let me check with the Process Server team as the schema should be in their designer. What version of Smart Office and Process Server are you using?

      Reply
  2. Alain

    Hi Karin
    thank you for coming back, it is a cold trail indeed but this is exactly what I need right now. I want users to be able to check their tasks filters from within M3 as they cannot do so with the process server page. Not to mention it opens many possibilities further on.
    LSO version is 10.0.5.4.19. IPA version is CU5 10.1.1.5.
    Many thanks
    Alain

    Reply
    1. karinpb Post author

      Hi,
      I did find a schema which I think applies to this. I also found an example of what an XML looks like that would work. I have not heard back from the IPA Product Owner but I think I found it. But I’m not sure what it is called in the IPA / LPA Studio where you model the flows.

      I did check with the global demo team and they might have an example that I can share – it shows the status on active IPA Workflows. It does not use the generated UI but I hope that I can share that example on the blog.

      As for the schema for automatic UI here is what I found:

      <?xml version="1.0" encoding="utf-8"?>
      <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="ProcessResponseHeaderDetails">
          <xs:complexType>
            <xs:sequence>
              <xs:element minOccurs="0" name="Header">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element minOccurs="0" name="Title" type="xs:string" />
                    <xs:element name="HeaderDetails" minOccurs="0" maxOccurs="unbounded">
                      <xs:complexType>
                        <xs:sequence minOccurs="0" maxOccurs="unbounded">
                          <xs:element name="Name" minOccurs="1" maxOccurs="1" type="xs:string" />
                          <xs:element name="Value" minOccurs="1" maxOccurs="1" type="xs:string" />
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element minOccurs="0" maxOccurs="unbounded" name="Detail">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element minOccurs="0" name="Title" type="xs:string" />
                    <xs:element minOccurs="0" maxOccurs="1" name="MetaColumns">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element minOccurs="1" maxOccurs="unbounded" name="MetaColumn">
                            <xs:complexType>
                              <xs:sequence>
                                <xs:element name="Name" minOccurs="1" maxOccurs="1" type="xs:string" />
                              </xs:sequence>
                              <xs:attribute default="string" name="type">
                                <xs:simpleType>
                                  <xs:restriction base="xs:string">
                                    <xs:enumeration value="string" />
                                    <xs:enumeration value="date" />
                                    <xs:enumeration value="integer" />
                                    <xs:enumeration value="double" />
                                  </xs:restriction>
                                </xs:simpleType>
                              </xs:attribute>
                              <xs:attribute name="dateFormat" type="xs:string"  use="optional" default="ddMMyyyy"/>
                              <xs:attribute name="numberDecimalSeparator" type="xs:string" use="optional" default="."/>
                            </xs:complexType>
                          </xs:element>
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>
                    <xs:element minOccurs="0" maxOccurs="1" name="Records">
                       <xs:complexType>
                          <xs:sequence>
                             <xs:element name="Record" minOccurs="1" maxOccurs="unbounded">
                                <xs:complexType>
                                   <xs:sequence minOccurs="0" maxOccurs="unbounded">
                                      <xs:element name="Column" minOccurs="1" maxOccurs="unbounded" type="xs:string" />
                                   </xs:sequence>
                                </xs:complexType>
                             </xs:element>
                          </xs:sequence>
                       </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                  <xs:attribute default="list" name="type">
                    <xs:simpleType>
                      <xs:restriction base="xs:string">
                        <xs:enumeration value="list" />
                        <xs:enumeration value="detail" />
                      </xs:restriction>
                    </xs:simpleType>
                  </xs:attribute>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
      

      A simple xml example:

      <ProcessResponseHeaderDetails>
      <Header>
      <title>Employee Information</title>
      <HeaderDetails>
      <name>Name</name>
      <value>Joe Smith</value>
      <name>DOB</name>
      <value>11/11/80</value>
      </HeaderDetails>
      </Header>
      <Detail>
      <title>Dependents</title>
      <MetaColumns>
      <MetaColumn>
      <name>Name</name>
      </MetaColumn>
      <MetaColumn>
      <name>Relationship</name>
      </MetaColumn>
      </MetaColumns>
      <Records>
      <Record>
      <Columns>
      <Column>Jane Smith</Column>
      <Column>Daughter</Column>
      </Columns>
      </Record>
      <Record>
      <Columns>
      <Column>Joe Smith Jr</Column>
      </Columns>
      <Columns>
      <Column>Son</Column>
      </Columns>
      </Record>
      </Records>
      </Detail>
      <Detail>
      <title>Direct Reports</title>
      <MetaColumns>
      <MetaColumn>
      <name>Name</name>
      </MetaColumn>
      <MetaColumn>
      <name>Title</name>
      </MetaColumn>
      </MetaColumns>
      <Records>
      <Record>
      <Columns>
      <Column>John Doe</Column>
      <Column>Engineer</Column>
      </Columns>
      </Record>
      <Record>
      <Columns>
      <Column>Jane Doe</Column>
      <Column>Sr Engineer</Column>
      </Columns>
      </Record>
      </Records>
      </Detail>
      </ProcessResponseHeaderDetails>

      Reply
  3. Alain

    Hi Karin
    my apologies but I don’t see the schema or the xml in the comment, have they been interpreted by wordpress or my IE?
    Thank you
    Alain

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s