Module:External Data Integration/Developers Guide/How To Implement A Output Process
Contents |
Introduction
The External Data Integration provides two different Output Processes, WSRest and Debug. In this document is described the required steps to develop a new Output Process. The WSRest is used as example during the document. This Output type sends the response of the EDL Request to the configured REST Web Service.
Output Process definition
The Output processes are defined in the Output Type window. The Search Key is used to identify the Java Class implementing the Output Type. There are also several flags to enable configuration fields that can be used by any output process. This flags are used on display logics on related fields of EDL Configuration window. In the WSRest example are enabled the flags Requires Path, Requires User, Requires Password and Requires Web Service Method. This fields are needed to set up in the configuration window to determine the web service to send the EDL Process response. The Debug output process does not have any flag enabled as it is not needed to configure any parameter to print the response in the logs.
Output Process implementation
The Custom Output Process is developed by implementing the org.openbravo.externaldata.integration.process.OutputDataProcessor abstract class. This class has 2 methods to implement: obtainWriter() and closeWriter(). There are also 2 methods that can be overridden to implement extra logic closeResources() and storeSendingData().
The class is identified with the corresponding Output Process by a Qualifier where its name is the Search Key set in the Output Type definition.
@Dependent @Qualifier("WSRest") public class OutputWSRestProcessor extends OutputDataProcessor {
The obtainWriter method receives the configuration instance of the output process as parameter and has to return a Writer
. In this writer is written the response of the EDL Request execution. In the WSRest example is the configuration is read to retrieve the needed information to open a connection with the Web Service. with the connection open the outputStream is loaded to return its writer. In case of error a OBException should be thrown.
@Override protected Writer obtainWriter(OBEDLConfigOutput output) { Writer result = null; try { URL url = new URL(output.getPath()); connection = (HttpURLConnection) url.openConnection(); // SKIPPED CODE connection.connect(); outputStream = connection.getOutputStream(); result = new BufferedWriter(new OutputStreamWriter(outputStream)); } catch (IOException e) { String errorMessage = OBMessageUtils.messageBD(ERROR_OBTAINING_WRITER); log.error(errorMessage + " " + output.getPath()); throw new OBException(errorMessage + " " + output.getPath(), e); } return result; }
The closeWriter has to close the required resources to be able to read a possible response in a outputExtraActions implementation of ItemProcessor. In the WSRest example the writer and the outputResponse are closed. It also provides a getWSInputStream() public method so outputExtraActions method implementations could read the response of the WebService.
/** * Returns the InputStream containing the response of the WebService call. */ public InputStream getWSInputStream() throws IOException { if (connection.getResponseCode() != 200) { return connection.getErrorStream(); } return connection.getInputStream(); } /** * Closes the writer and the outputStream of the WebService call opened in hte obtainWriter * method. * * @see OutputDataProcessor#closeWriter(Writer) */ @Override protected void closeWriter(Writer writer) { try { writer.close(); outputStream.close(); } catch (IOException e) { String errorMessage = OBMessageUtils.messageBD(ERROR_CLOSING_RESOURCES); log.error(errorMessage); throw new OBException(errorMessage, e); } }
An example of a ItemProcessor implementation that overrides the outputExtraActions method considering the WSRest output. In this example it reads the received response as a JSONObject and checks if there is a error parameter to throw a OBException.
@Override public void outputExtraActions(OutputDataProcessor outputDataProcessor, OBEDLConfigOutput output) { if (outputDataProcessor instanceof OutputWSRestProcessor) { try { InputStream response = ((OutputWSRestProcessor) outputDataProcessor).getWSInputStream(); String responseStr = IOUtils.toString(response); JSONObject wsResponse; try { wsResponse = new JSONObject(responseStr); } catch (JSONException e) { // Response is not a JSON throw new OBException(responseStr); } if (wsResponse.getString(WS_RESPONSE_STATUS_PROP).equals(WS_ERROR_RESPONSE)) { JSONObject errorMessage = wsResponse.getJSONObject(WS_ERROR); throw new OBException(errorMessage.getString(WS_RESPONSE_CODE_PROP) + " " + errorMessage.getString(WS_RESPONSE_MESSAGE_PROP)); } } catch (IOException e) { throw new OBException("Error reading response from InputStream", e); } catch (JSONException e) { throw new OBException("Error parsing response", e); } } }
Optional Implementations
The OutputDataProcessor class provides 2 methods that can be overridden to execute additional logic closeResources() and storeSendingData().
The closeResources() is used to close all the resources that might be still open. In the WSRest example the connection is not closed in the closeWriter method to be able to read the response. This method is overridden to close it and throw an exception if the response code is not 200.
@Override protected void closeResources() { try { if (connection.getResponseCode() != 200) { throw new OBException(connection.getResponseMessage()); } } catch (IOException e) { log.error("Error closing resources", e); throw new OBException(OBMessageUtils.messageBD(ERROR_CLOSING_RESOURCES), e); } finally { connection.disconnect(); } }
The storeSendingMethod() is a method that returns a boolean to store or not the response on the EDL Request. It is possible to store on each EDL Request the output content that has been send as response. Changing the return of this method to true this functionality is enabled. Note that this is used when the execution of the EDL request finishes successfully. In case it is desired to store output information when the EDL request fails, then the writeErrorResponse method of the ItemProcessor must be implemented.
@Override protected boolean storeSendingData() { return true; }
Output Process configuration
The Output Processes are configured for each client on the EDL Configuration window. This is mandatory when a EDL Process that has the has Output flag checked. Each EDL Process might have several output processes configured that are executed based on the defined Sequence Number. Depending on the Output Type selected different configuration fields are shown. See the Requires flags on the Output Type definition.