This section describes helper methods and other aspects useful for developing the web services.
The Java Sample Codes covered in this book, and those available for download from Oracle Software Delivery Cloud, demonstrate various usage characteristics of Agile 933 Web Services.
Apart from outlining the basic cases for each Web Service, they also elaborate upon more specific cases that involve usage of options or mandatory message elements.
Download these Sample Codes in 'src' directory. They are categorized into different packages based on the type of Web Service, which are AdminMetaData, Attachment, Business, Collaboration, PC, Search and Table.
Batch files for building and running samples independent of a java IDE are also provided.
A batch file build.bat located in the main directory JavaWeb Servicesamples is also provided. This batch file uses ant tasks to generate stubs for Agile Web Services and compiles the java sample files after generation of these stubs.
Along with build.bat, you will find a file custom.properties file that specifies the basic configuration properties, such as the Agile server URL, username, password of your user and also the URL of DFM. Unless this property file is edited to reflect the values appropriate for your Agile environment, you will not be able to generate stubs or run the samples.
After ensuring appropriate modification of 'custom.properties', run the batch file 'build.bat'. Running the same through a command prompt helps in identifying error statements (if any) that are echoed onto the console. If the message 'BUILD SUCCESSFUL' displays on the console then the build process was completed without any errors. However, if the message 'BUILD FAILED' is observed on the console, your 'custom.properties' configuration may be incorrect and you must verify the same.
The stubs and the compiled samples are added to the folder build/built/*.jar as two jar files 'ws_samples.jar' and 'ws_stubs.jar' which are used later while running the sample.
After building the stubs and compiling the sample files, any sample file can be readily executed using the batch file run.bat and specifying the fully qualified class name as an argument.
Browse the source directory 'JavaWeb Servicesamples/src' to find the package structure of the sample that you are looking for.
For example, to the run the sample 'CreateObjectAPIName' that creates an object using API names, the following command must be executed through command prompt:
run business.create.CreateObjectAPIName
Similarly, to run a sample from another sample package, say AddRowsSiteSpecific of the table Web Service, use the command:
run table.addrows.AddRowsSiteSpecific
If no argument is passed to run.bat, then all the available samples will be executed sequentially.
Note: While running samples using this ant task, the Agile server URL, username and password properties are retrieved from the same 'custom.properties' file that was used for building stubs. |
To run the sample files from a Java IDE, such as JDeveloper or Eclipse, create a new project or workspace in your IDE (as applicable to your IDE) and in your project properties modify / add project source paths to include the 'JavaWeb Servicesamples/src' directory where the sample source code is located.
You also need to update your project library or classpath information to include all the necessary classes of Axis and other Agile jar files which are used iduring sample development.
Ensure to add the jar files under the folders 'JavaWeb Servicesamples/build/axis' and 'JavaWeb Servicesamples/build/lib' to your library / classpath.
Any sample file can now be executed by browsing through the package structure, and running the desired sample.
The static variables relating to Agile server url, username and password in each java sample must be modified, if you choose to run the sample through an IDE.
Each java sample file contains header documentation at the class level explaining the functionality or usage scenario that the sample demonstrates. A set of static variables relating to server url, username, password and variables specific to that sample, like partNumber or folderName or nextStatus, are declared here.
If the sample is executed using the ant task (through run.bat), then the server configuration related static variables are overridden by the method checkArguments(String[] args(), which obtains arguments from the ant task and reinitializes server URL username, password and DFM URL variables.
If a sample is executed through a Java IDE, the server configuration variables must be modified manually to reflect the server settings of your Agile server.
With the exception of adminMetaData services, all samples provided here use the method prepareData() to prepare all the data prerequisites necessary to create a scenario using which, a particular Web Service may be demonstrated meaningfully.
For example, if the sample demonstrates usage of the operation loadTable to load a table from a particular version of an Agile object, prepareData() does the following:
Creates a part object
Adds a change, modifies the part
Provides a new version number
Releases the change.
After you prepare the data, the operation loadTable is used with the option 'version' to demonstrate the retrieval of a table from a particular version of an Agile object.
If you intend to use your own data or scenario to execute a Web Service sample, comment out the 'prepareData();' statement in the main method of that sample. You then edit the static variables at the top of the code and specify your own data.
All the operations performed in data preparation are also achieved using Agile 933 Web Services. To gain a broader understanding of how Web Services are used in conjunction to orchestrate a larger task, examine the file DataPrepare.java in the package src/run/DataPrepare.java
The sample files are documented with comments at each stage and evince several usage characteristics of these Web Services while illustrating how basic requests are formed and how the responses obtained are used.
This sample method demonstrates addition of a file attachment to the Attachment Tab of an Agile object using SOAP.
Example: Adding a file attachment to the Attachment tab of an Agile object using SOAP
Basic Steps
Create the request object AddFileAttachmentRequestType for the addFileAttachment operation.
Create an array of requests of type AgileAddFileAttachmentRequestType. Batch operations may be performed by populating as many request objects as required to add several files to different objects with one single operation.
For each batched request, specify the unique object to whose attachment tab the files are to be added. Supply class identifier and object number information for the same.
The exact specification of the attachment to be added is defined as an object of type AgileAddFileAttachmentRequestType. This object includes information about the name of the file and its description and content.
While using SOAP attachments, create a datahandler to specify the file source and add the content as a soap attachment to the soap request. Finally set the contentId onto AgileAddFileAttachmentRequestType.
The request objects are set and the Agile Stub makes the addFileAttachment Web Service call. The status code obtained from the response object is printed to verify the success of the addFileAttachment operation.
If the Web Service call is successful, then state the same.
If the status code is not 'SUCCESS', then populate the list of exceptions returned by the Web Service.
Sample Code
SOAP
try { setupServerLogin(); AddFileAttachmentRequestType addFileAttachmentRequestType = new AddFileAttachmentRequestType(); AgileAddFileAttachmentRequest agileAddFileAttachmentRequest[] = new AgileAddFileAttachmentRequest[1]; agileAddFileAttachmentRequest[0] = new AgileAddFileAttachmentRequest(); agileAddFileAttachmentRequest[0].setClassIdentifier("Part"); agileAddFileAttachmentRequest[0].setObjectNumber(partNumber); System.out.println("Adding a SOAP attachment to the part '" + partNumber + "'..."); AgileAddFileAttachmentRequestType attachments[] = new AgileAddFileAttachmentRequestType[1]; attachments[0] = new AgileAddFileAttachmentRequestType(); attachments[0].setName("Filename.txt"); attachments[0].setDescription("Description for file "); String filename = "sample123456.txt"; BufferedWriter out = new BufferedWriter(new FileWriter(filename)); out.write("Test file"); out.close(); DataHandler dh = new DataHandler(new FileDataSource(filename)); AttachmentPart ap = new AttachmentPart(dh); agileStub.addAttachment(ap); attachments[0].setContentId(ap.getContentId()); agileAddFileAttachmentRequest[0].setAttachments(attachments); agileAddFileAttachmentRequest[0].setSingleFolder(false); addFileAttachmentRequestType.setRequests(agileAddFileAttachmentRequest); AddFileAttachmentResponseType addFileAttachmentResponseType = agileStub.addFileAttachment(addFileAttachmentRequestType); System.out.println("\nSTATUS CODE: " + addFileAttachmentResponseType.getStatusCode()); if (!addFileAttachmentResponseType.getStatusCode().toString().equals(ResponseStatusCode.SUCCESS.getValue())) { AgileExceptionListType[] agileExceptionListType = addFileAttachmentResponseType.getExceptions(); if (agileExceptionListType != null) for (int i = 0; i < agileExceptionListType.length; i++) { AgileExceptionType exceptions[] = agileExceptionListType[i].getException(); for (int j = 0; j < exceptions.length; j++) System.out.println("Exception Id:" + exceptions[j].getExceptionId() + "\nMessage: " + exceptions[j].getMessage()); } AgileWarningListType agileWarningListType[] = addFileAttachmentResponseType.getWarnings(); if (agileWarningListType != null) for (int i = 0; i < agileWarningListType.length; i++) { AgileWarningType warnings[] = agileWarningListType[i].getWarning(); for (int j = 0; j < warnings.length; j++) System.out.println("Warning Id: " + warnings[j].getWarningId() + "\nMessage: " + warnings[j].getMessage()); } } else { AgileAddFileAttachmentResponse responses[] = addFileAttachmentResponseType.getResponses(); if (responses != null) for (int i = 0; i < responses.length; i++) { System.out.println("The specified SOAP attachment was successfully added to the Attachment tab"); System.out.println("of the object: " + responses[i].getObjectNumber()); } } }
The getRowID and getFileId are custom helper methods. These are not Agile Web Services operations.
Service
This topic describes how you obtain the rowId for a row on an Agile table
Usage
Several table and attachment operations require the rowId as input for executing a Web Service. Load the table that contains the required row using the loadTable operation. It is then iterated through the results until the row is found.
To find a particular row in a table, use a keyword to search and identify the row. In this example, the filename is used as the key to identify a row.
Search all the rows available in the attachment table and compare all message elements with tag names 'filename' with the filename specified by the client, looking for a match. Once a match is found, the rowId information is derived from the row and returned.
Compare all 'filename' message elements, searching for a match with the filename specified by the user. If a match is found, return either the fileId or rowId based on the requirement.
Note: getValueFromSelection is a method written in this sample that handles all message elements of type AgileListEntryType. Since 'filename' is a message element of AgileListEntryType, the values are elicited by this method. |
Usage
Handle all AgileListEntryType message elements, cycle through the selection element, obtain the actual selection value and the selection Id and add it to a HashMap. Here the selection value denotes the filename while the selection Id denotes the fileId.
In Filefolders, the message element for filename is not an AgileListEntryType. The value may be obtained directly.
To get RowID:
Create the request object LoadTableRequestType for the loadTable operation.
For each request, specify the table to which the row belongs.
Tables in Agile Web Services are defined as RequestTableType objects. A specific table may be identified by specifying the class identifier and table identifier attributes.
The request objects are set and the Agile Stub makes the loadTable Web Service call. The status code obtained from the response object is printed to verify the success of the loadTable operation.
If the status code indicates 'SUCCESS', use the table results to find the required row. Once the row is found, its rowId is returned. If the status code indicates that the Web Service call was not successful, populate a list of exceptions.
Search for the required row by using the filename to look for a match and return the rowId.
Sample Code
getRowId
public static int getRowId(String filename, String classIdentifier, String objectNumber, String tableId){ try{ setupServerLogin_LoadTable(); LoadTableRequestType loadTableRequestType = new LoadTableRequestType(); RequestTableType table[] = new RequestTableType[1]; table[0] = new RequestTableType(); table[0].setClassIdentifier(classIdentifier); table[0].setObjectNumber(objectNumber); table[0].setTableIdentifier( tableId ); loadTableRequestType.setTableRequest(table); LoadTableResponseType loadTableResponseType = agileStub_Table.loadTable(loadTableRequestType); System.out.println("Obtaining row Id / fileId information....."); System.out.println("STATUS CODE: " + loadTableResponseType.getStatusCode() ); if( loadTableResponseType.getStatusCode().toString().equals( ResponseStatusCode.SUCCESS.getValue() ) ){ AgileTableType[] tables = loadTableResponseType.getTableContents(); return findRowId(tables, filename); } else{ System.out.println("<Failed to load table information>"); AgileExceptionListType[] agileExceptionListType = loadTableResponseType.getExceptions(); if(agileExceptionListType!=null) for(int i=0; i<agileExceptionListType.length; i++){ AgileExceptionType exceptions[] = agileExceptionListType[i].getException(); for(int j=0; j<exceptions.length; j++) System.out.println(exceptions[j].getMessage() ); } AgileWarningListType agileWarningListType[] = loadTableResponseType.getWarnings(); if(agileWarningListType!=null) for( int i=0; i<agileWarningListType.length; i++){ AgileWarningType warnings[] = agileWarningListType[i].getWarning(); for(int j=0; j<warnings.length; j++) System.out.println("Warning Id: " + warnings[j].getWarningId() + "\nMessage: " + warnings[j].getMessage() ); } } } catch (Exception ex) { ex.printStackTrace(); } return -1; } public static int findRowId(AgileTableType[] tables, String filename){ if(tables!=null) for(int i=0; i<tables.length; i++){ AgileRowType[] rows = tables[i].getRow(); if(rows!=null) for(int j=0; j<rows.length; j++){ MessageElement[] messages = rows[j].get_any(); for(int m=0; m<messages.length; m++){ if( messages[m].getName().toString().equalsIgnoreCase("filename") ){ HashMap fileValues[] = getValuesFromSelection(messages[m]); for(HashMap fileValue:fileValues) if( fileValue.get("filename").equals(filename) ){ System.out.println("Row Id successfully retrieved."); return rows[j].getRowId(); } } } } } return 0; } public static HashMap[] getValuesFromSelection(MessageElement element){ HashMap fileValues[] = null; if(element.getType().getLocalPart().equals("AgileListEntryType")){ AgileListEntryType list = (AgileListEntryType) element.getObjectValue(); SelectionType selection[] = list.getSelection(); fileValues = new HashMap [selection.length]; for(int i=0; i<selection.length; i++){ fileValues[i] = new HashMap(); fileValues[i].put("filename", selection[i].getValue() ); fileValues[i].put("fileid", selection[i].getId() ); } } else{ fileValues = new HashMap [1]; fileValues[0] = new HashMap(); fileValues[0].put("filename", element.getFirstChild().getNodeValue() ); fileValues[0].put("fileId", null ); } return fileValues; }
Service
This topic describes how you obtain the FileId for a Row on an Agile Table.
Usage
Several attachment operations require the fileId as input for executing. For example, if a particular attachment row has several files associated with it, the fileId is necessary to differentiate between each file available on that row.
Here, you first use the loadTable Web Service to load the table that contains the required row, iterate through the results until the row is found. To find a particular row in a table, use a keyword and identify the row
In this example, the filename is used as the key to identify a row. Once the filename message element is obtained as an AgileListEntry Type element, the 'id' value of the SelectionType element may be returned. This 'id' tag corresponds to the fileId of that file attachment.
Search all the rows available in the attachment table and compare all message elements with tag names 'filename' with the filename specified by the client, looking for a match. Once you find a match, fileId information is derived from the filename selection elements, whose 'id' corresponds to the fileId.
Compare all 'filename' message elements, searching for a match with the filename specified by the user. If you find a match, return fileId.
Note: If both rowId and fileId values are necessary, then a similar approach may be used to obtain both the rowId and fileId for a particular file attachment from an attachment row. |
Note: getValueFromSelection is a method written in this sample that handles all message elements of type AgileListEntryType. Since 'filename' is a message element of AgileListEntryType, the values are elicited by this method. |
Usage
Handle all AgileListEntryType message elements, cycle through the selection element, obtain the actual selection value and the selection ID and add it to a HashMap. Here the selection value denotes the filename while the selection ID denotes the fileId.
With File folders the message element for filename is not an AgileListEntryType. The value may be obtained directly.
To get a File ID:
Create the request object LoadTableRequestType for the loadTable operation.
For each request, specify the table to which the row belongs. Tables in Agile Web Services are defined as RequestTableType objects. A specific table may be identified by specifying the class identifier and table identifier attributes.
The request objects are set and the Agile Stub makes the loadTable Web Service call. The status code obtained from the response object is printed to verify the success of the loadTable operation.
If the status code indicates 'SUCCESS', search and retrieve the fileId.
Search for the necessary fileId by using the filename to look for a match and return either of the two, according to the requirement specified in the input parameter 'methodType'.
If the status code indicates that the Web Service call was not successful, populate a list of exceptions.
Sample Code
getFileId
public static int getFileId(String filename, String clazz, String objectNumber, String tableId){ try{ setupServerLogin_LoadTable(); LoadTableRequestType loadTableRequestType = new LoadTableRequestType(); RequestTableType table[] = new RequestTableType[1]; table[0] = new RequestTableType(); table[0].setClassIdentifier(clazz); table[0].setObjectNumber(objectNumber); table[0].setTableIdentifier( tableId ); loadTableRequestType.setTableRequest(table); LoadTableResponseType loadTableResponseType = agileStub_Table.loadTable(loadTableRequestType); System.out.println("Obtaining row Id / fileId information....."); System.out.println("STATUS CODE: " + loadTableResponseType.getStatusCode() ); if( loadTableResponseType.getStatusCode().toString().equals( ResponseStatusCode.SUCCESS.getValue() ) ){ AgileTableType[] tables = loadTableResponseType.getTableContents(); return findFileId(tables, filename); } else{ System.out.println("<Failed to load table information>"); AgileExceptionListType[] agileExceptionListType = loadTableResponseType.getExceptions(); if(agileExceptionListType!=null) for(int i=0; i<agileExceptionListType.length; i++){ AgileExceptionType exceptions[] = agileExceptionListType[i].getException(); for(int j=0; j<exceptions.length; j++) System.out.println(exceptions[j].getMessage() ); } AgileWarningListType agileWarningListType[] = loadTableResponseType.getWarnings(); if(agileWarningListType!=null) for( int i=0; i<agileWarningListType.length; i++){ AgileWarningType warnings[] = agileWarningListType[i].getWarning(); for(int j=0; j<warnings.length; j++) System.out.println("Warning Id: " + warnings[j].getWarningId() + "\nMessage: " + warnings[j].getMessage() ); } } } catch (Exception ex) { ex.printStackTrace(); } return -1; } public static int findFileId(AgileTableType[] tables, String filename){ if(tables!=null) for(int i=0; i<tables.length; i++){ AgileRowType[] rows = tables[i].getRow(); if(rows!=null) for(int j=0; j<rows.length; j++){ MessageElement[] messages = rows[j].get_any(); for(int m=0; m<messages.length; m++){ if( messages[m].getName().toString().equalsIgnoreCase("filename") ){ HashMap fileValues[] = getValuesFromSelection(messages[m]); for(HashMap fileValue:fileValues) if( fileValue.get("filename").equals(filename) ){ System.out.println("File Id successfully retrieved."); return (Integer) fileValue.get("fileid"); } } } } } return 0; } public static HashMap[] getValuesFromSelection(MessageElement element){ HashMap fileValues[] = null; if(element.getType().getLocalPart().equals("AgileListEntryType")){ AgileListEntryType list = (AgileListEntryType) element.getObjectValue(); SelectionType selection[] = list.getSelection(); fileValues = new HashMap [selection.length]; for(int i=0; i<selection.length; i++){ fileValues[i] = new HashMap(); fileValues[i].put("filename", selection[i].getValue() ); fileValues[i].put("fileid", selection[i].getId() ); } } else{ fileValues = new HashMap [1]; fileValues[0] = new HashMap(); fileValues[0].put("filename", element.getFirstChild().getNodeValue() ); fileValues[0].put("fileId", null ); } return fileValues; }
Issue #7639814: API names are not available for a huge set of lists.
Resolution: GetLists Admin service is supported only for Admin Lists which can be found in JavaClient>Admin>Lists. Some class specific lists are not exposed in Admin Lists.
To get values for these Lists, use GetAttributes Admin service, which will return AttributeType. This, in turn, has availableValues as AdminListType. This list values can be used for updateObject or createObject.
Issue #8253064: Group sign-off option cannot be set from Web Services.
Resolution: Group sign-off is not supported in the current release.
Issue #9308516: undoRedline operation error message does not convey the wrong "option name" given.
Resolution: If you do not use option "redline_change", or if it is wrongly entered as "redline_chg", the correct revision of the item will not be loaded. Only the latest released revision will be loaded. In that revision of the item BOM table, the given row id is invalid and hence the invalid rowId exception is thrown. The behavior seems acceptable.