Troubleshooting
Problem
In the generated JSF custom client for human tasks, when you want to view or edit messages that contain xsd:any, choice, or substitution group constructs, you cannot see these parts of the message nor modify them.
Cause
Due to a limitation in the Service Data Object API, it is not possible to identify substitution groups or choice elements. If the message contains an xs:any element, there is a wildcard slot about which the generated client cannot make any assumption. Instead you must add custom code to deal with such constructs.
Resolving The Problem
This technote describes the solution for substitution elements. The solution for xs:choice and xs:any is similar.
If there is an element AbstractAccount, which can be subsituted by an element AccountChild, the schema definition might look like this:
<xs:element name="AbstractAccount" type="ns1:AccountType"/>
<!-- xs:attribute name="attr" type="xs:string" use="optional"/--> <xs:element name="AccountChild"
</xs:extension> |
<h:outputText styleClass="ViewFieldLabel" value="#{bundle['MSG_SUBVIEW_ELEMENT_NOT_SUPPORTED']}"/><h:outputText styleClass="Indentend" value="elt is part of xsd:substitutionGroup"/> |
To add AccountChild elements instead of AbstractAccount elements, you can replace these lines with the following lines for the input message:
<h:outputText styleClass="ViewFieldLabel" value="elt:"/><h:outputText styleClass="ViewReadOnlyField" value="#{toDoMessageHandler.toDoInstance.inputValues['/input1/AbstractAccount/elt']}"/> |
<h:outputText styleClass="ViewFieldLabel" value="childElt:"/><h:outputText styleClass="ViewReadOnlyField" value="#{toDoMessageHandler.toDoInstance.inputValues['/input1/AbstractAccount/childElt']}"/> |
In the case of the output message, inputText elements need to be used.
<h:outputText styleClass="ViewFieldLabel" value="elt: "/><h:inputText id="output1field2_ID" styleClass="ViewEntryField" value="#{toDoMessageHandler.toDoInstance.outputValues['/output1/AbstractAccount/elt']}" required="false" /> |
<h:outputText styleClass="ViewFieldLabel" value="childElt: "/><h:inputText id="output1field3_ID" styleClass="ViewEntryField" value="#{toDoMessageHandler.toDoInstance.outputValues['/output1/AbstractAccount/childElt']}" required="false" /> |
Note: The properties of an AccountChild are accessed by refering to the head element AbstractAccount. Unfortunately, the output JSP will not work immediately because the implementation of the generated client cannot handle the used xPath. Therefore, you must alter the getOutputValues() method of the the com.ibm.wbit.tel.client.jsf.bean.ToDoInstance.
This example shows the original implementation:
public Object getOutputValues(Object dataType) throws PropertyNotFoundException, PropertyPopulationException {
} else { ret = outputValues.get(SINGLE_PRIMITIVE_TYPE); } } |
To alter the above implementation, follow these steps:
- As this method is invoked for all message types of the generated client, you must ensure that the custom code is only invoked for the right message type.
- Set the ALContext to the application that provides the schema definition and unset the context in a finally statement later again.
- Remove the xPaths that relate to the substitution group.
- Invoke the populateAll method with all the supported xPaths.
- Check if the substitution element already exists.
- If the substitution element does not exit, create a new element using the BOFactory service and set the substitution element on the DataObject.
- Set the properties of the substitution element
public Object getOutputValues(Object dataType) throws PropertyNotFoundException, PropertyPopulationException {
// System.out.println("URI: " + uriName); // // 0 )Only run the special logic for that right type // if ("operation1Response_._type".equals(typeName) && " http://SubstLibrary/ChildIntf".equals(uriName)) {
// 1) Set the searchpath for artifacts appropriately // Make sure that the application that contains the artifacts is set. In my case "SubstTest1App" // com.ibm.wsspi.al.ALContext.setContext("BPC_CLIENT","SubstTest1App"); // // 2) Remove the keys out of the map and store the values. //
String childElt = (String) outputValues.remove("/output1/AbstractAccount/childElt"); // 3) Populate all other values using the standard method // ret = DataObjectUtils.populateAll((DataObject) dataType, outputValues); // // 4) Check whether the substitution element already exists //
DataObject accountChild = (DataObject) output1.get("AccountChild");
// 5) Create the substitution element using the BOFactory //
http://www.example.org/artifacts/", "AccountChild"); // Set the value on the substitution element //
// // 6) set the properties of the substitution element //
throw exception; finally {
} } else { } } |
Was this topic helpful?
Document Information
Modified date:
15 June 2018
UID
swg21306783