In real-life projects, dealing with varying or dynamic inbound inputs is common. In this article, we’ll walk you through the step-by-step process of managing dynamic inputs within WebMethods boundaries.
In general, mapping using a flow service becomes challenging when dealing with dynamic inputs. However, you can still perform manipulations on dynamic inputs using a Java service.
Let’s consider you have a source from which you are getting the XML and fields for the XML are subject to change, in this article we will take a close look at the XML and will write a Java service to produce two output string-list containing field name and field value but in a real-life project, you can change the logic to effectively handle the incoming data.
Code Area:-
- Create a package with the name ‘HG_DynamicInput’ and follow the below package structure.
- Create a Java service with the name ‘handleDynamicInput’ under the services folder.
- In the input section of the Java service create a document list with the name ‘EmployeeList’ and don’t define any field under the EmployeeList document, we will handle it in run time.
- In the output section of the java service create two string lists with the name ‘fieldName’ and ‘fieldValue’.
- Right-click on the Java service ->Generate code -> Select the ‘For implementing this service’ option and click finish.
- Once you follow the above procedure, it will copy the input & output parameters code to the clipboard and it should look like below.
// pipeline IDataCursor pipelineCursor = pipeline.getCursor(); // EmpoyeeList IData[] EmployeeList= IDataUtil.getIDataArray( pipelineCursor, "EmployeeList" ); if ( EmployeeList!= null) { for ( int i = 0; i < EmployeeList.length; i++ ) { } } pipelineCursor.destroy(); // pipeline IDataCursor pipelineCursor_1 = pipeline.getCursor(); String[] fieldName = new String[1]; fieldName[0] = "fieldName"; IDataUtil.put( pipelineCursor_1, "fieldName", fieldName ); String[] fieldValue = new String[1]; fieldValue[0] = "fieldValue"; IDataUtil.put( pipelineCursor_1, "fieldValue", fieldValue ); pipelineCursor_1.destroy();
- Paste the copied code to the ‘handleDynamicInput’ method area, once you paste it your Java service will look like below.
package HG_DynamicInput.v1.services; import com.wm.data.*; import com.wm.util.Values; import com.wm.app.b2b.server.Service; import com.wm.app.b2b.server.ServiceException; public final class handleDynamicInput_SVC { /** * The primary method for the Java service * * @param pipeline * The IData pipeline * @throws ServiceException */ public static final void handleDynamicInput(IData pipeline) throws ServiceException { // pipeline IDataCursor pipelineCursor = pipeline.getCursor(); // EmpoyeeList IData[] EmployeeList= IDataUtil.getIDataArray( pipelineCursor, "EmployeeList" ); if ( EmployeeList!= null) { for ( int i = 0; i < EmployeeList.length; i++ ) { } } pipelineCursor.destroy(); // pipeline IDataCursor pipelineCursor_1 = pipeline.getCursor(); String[] fieldName = new String[1]; fieldName[0] = "fieldName"; IDataUtil.put( pipelineCursor_1, "fieldName", fieldName ); String[] fieldValue = new String[1]; fieldValue[0] = "fieldValue"; IDataUtil.put( pipelineCursor_1, "fieldValue", fieldValue ); pipelineCursor_1.destroy(); } // --- <<IS-BEGIN-SHARED-SOURCE-AREA>> --- // --- <<IS-END-SHARED-SOURCE-AREA>> --- final static handleDynamicInput_SVC _instance = new handleDynamicInput_SVC(); static handleDynamicInput_SVC _newInstance() { return new handleDynamicInput_SVC(); } static handleDynamicInput_SVC _cast(Object o) { return (handleDynamicInput_SVC)o; } }
- Insert the following code within the for loop to obtain a cursor object, enabling navigation and manipulation of the data within that element.
IDataCursor listCursor = EmployeeList[i].getCursor();
- To extract each field name and its corresponding value within the ‘EmployeeList,’ we should implement a while loop inside the for loop. This while loop will allow you to move the cursor to the next element iteratively, processing each EmployeeList element as long as they exists.
while (listCursor.next()){ }
- Till now we have not declared a string list to hold our fieldName and fieldValue, declare the string list in the beginning, and remove the declaration from the pipeline output section. once your code is updated it should look like below.
package HG_DynamicInput.v1.services; import com.wm.data.*; import com.wm.util.Values; import com.wm.app.b2b.server.Service; import com.wm.app.b2b.server.ServiceException; import java.util.ArrayList; import java.util.List; public final class handleDynamicInput_SVC { /** * The primary method for the Java service * * @param pipeline * The IData pipeline * @throws ServiceException */ public static final void handleDynamicInput(IData pipeline) throws ServiceException { List<String> fieldName = new ArrayList<>(); List<String> fieldValue = new ArrayList<>(); // pipeline IDataCursor pipelineCursor = pipeline.getCursor(); // EmpoyeeList IData[] EmployeeList = IDataUtil.getIDataArray( pipelineCursor, "EmployeeList" ); if ( EmployeeList != null) { for ( int i = 0; i < EmployeeList.length; i++ ) { IDataCursor listCursor = EmployeeList[i].getCursor(); while (listCursor.next()){ } } } pipelineCursor.destroy(); // pipeline IDataCursor pipelineCursor_1 = pipeline.getCursor(); IDataUtil.put( pipelineCursor_1, "fieldName", fieldName ); IDataUtil.put( pipelineCursor_1, "fieldValue", fieldValue ); pipelineCursor_1.destroy(); } // --- <<IS-BEGIN-SHARED-SOURCE-AREA>> --- // --- <<IS-END-SHARED-SOURCE-AREA>> --- final static handleDynamicInput_SVC _instance = new handleDynamicInput_SVC(); static handleDynamicInput_SVC _newInstance() { return new handleDynamicInput_SVC(); } static handleDynamicInput_SVC _cast(Object o) { return (handleDynamicInput_SVC)o; } }
- Inside the while loop add the below code which will get the fieldName and the fieldValue respectively and then we can add those values to our array.
String field_name = listCursor.getKey(); String field_Value=(String) listCursor.getValue();
- Update the code to include the addition of filedName and fieldvalue to their respective lists.
fieldName.add(field_name); fieldValue.add(field_Value);
- Now we have two lists that are currently holding the data but we need to convert it to the array so that it will be populated correctly out of our Java service.
- Update the code with the below to convert it to Array instead of List and populate it in output.
String[] fieldName_A = fieldName.toArray(new String[fieldName.size()]); String[] fieldValue_A = fieldValue.toArray(new String[fieldValue.size()]); pipelineCursor.destroy(); // pipeline IDataCursor pipelineCursor_1 = pipeline.getCursor(); IDataUtil.put( pipelineCursor_1, "fieldName", fieldName_A ); IDataUtil.put( pipelineCursor_1, "fieldValue", fieldValue_A ); pipelineCursor_1.destroy();
- If you have followed everything correctly till now, then your Java code should look like below.
package HG_DynamicInput.v1.services; import com.wm.data.*; import com.wm.util.Values; import com.wm.app.b2b.server.Service; import com.wm.app.b2b.server.ServiceException; import java.util.ArrayList; import java.util.List; public final class handleDynamicInput_SVC { /** * The primary method for the Java service * * @param pipeline * The IData pipeline * @throws ServiceException */ public static final void handleDynamicInput(IData pipeline) throws ServiceException { List<String> fieldName = new ArrayList<>(); List<String> fieldValue = new ArrayList<>(); // pipeline IDataCursor pipelineCursor = pipeline.getCursor(); // EmpoyeeList IData[] EmployeeList = IDataUtil.getIDataArray( pipelineCursor, "EmployeeList" ); if ( EmployeeList != null) { for ( int i = 0; i < EmployeeList.length; i++ ) { IDataCursor listCursor = EmployeeList[i].getCursor(); while (listCursor.next()){ String field_name = listCursor.getKey(); String field_Value=(String) listCursor.getValue(); fieldName.add(field_name); fieldValue.add(field_Value); } } } String[] fieldName_A = fieldName.toArray(new String[fieldName.size()]); String[] fieldValue_A = fieldValue.toArray(new String[fieldValue.size()]); pipelineCursor.destroy(); // pipeline IDataCursor pipelineCursor_1 = pipeline.getCursor(); IDataUtil.put( pipelineCursor_1, "fieldName", fieldName_A ); IDataUtil.put( pipelineCursor_1, "fieldValue", fieldValue_A ); pipelineCursor_1.destroy(); } // --- <<IS-BEGIN-SHARED-SOURCE-AREA>> --- // --- <<IS-END-SHARED-SOURCE-AREA>> --- final static handleDynamicInput_SVC _instance = new handleDynamicInput_SVC(); static handleDynamicInput_SVC _newInstance() { return new handleDynamicInput_SVC(); } static handleDynamicInput_SVC _cast(Object o) { return (handleDynamicInput_SVC)o; } }
- Now Let’s create a flow service where we will call our Java service to provide dynamic input.
- Create a flow service inside the services folder and give it a name.
- In the service input area create an input variable with the name ‘inputXML’.
- Invoke ‘pub.xml:xmlStringToXMLNode’ and follow the below mappings.
- Invoke ‘pub.xml:xmlNodeToDocument’ to convert the node to a document which we can pass to the Java service.
- Invoke our Java service that we created earlier and perform the below mapping.
- Now it’s time to test our service so run the flow service with the below XML as input.
<?xml version="1.0" encoding="ISO-8859-1"?> <Employee> <Name>John Doe</Name> <Id>1</Id> </Employee> <Employee> <Designation>Associate</Designation> <Salary>2K</Salary> </Employee>
- If you observe the above XML it has different fields in the Employee List, we should get these details in Stringlist containing field name and values respectively so let’s run it.
- Congratulations!!, we did it.
- The above coding is done to make you understand how we can traverse the inputs dynamically and get their value in run time, you can update the logic based on your requirement.Please click the below button to download the source code of this project.