Oracle Transport Agent

This chapter covers the following topics:

Oracle Transport Agent Overview

Oracle Transport Agent (OTA) is a lightweight messaging platform for transmitting documents over HTTP and Secure HTTP (HTTPS). OTA implements a messaging protocol on top of the HTTP Application protocol.

The OTA server is a Java-based servlet that uses the OTA messaging protocol to support the following requirements:

This section will describe how client authentication is implemented in the latest release of OTA. Oracle E-Business Suite users may choose to implement client authentication. It is not mandatory.

In this document, the Sender refers to the "Client" that sends a document or requests connection. The Receiver refers to the "Server" that receives the document or connection request.

The Oracle Transport Agent Protocol Stack

The OTA protocol stack is as follows:

OTA (Messaging Protocol)

HTTP (Application Protocol)

SSL (Encryption/Security Protocol - optional)

TCP/IP (Network Protocol)

The OTA protocol defines the conversation semantics used by two Web servers running the OTA Servlet. The two OTA Servlets "talk" to each other to provide guaranteed, exactly-once delivery of the message.

OTA Message Propagation Flow

The following diagram displays the message propagation flow of an OTA message with SSL enabled:

the picture is described in the document text

  1. The OTA client dequeues the message from the ECX_OUTBOUND queue.

  2. The OTA client verifies the maximum retry count.

  3. The OTA client constructs the HTTP message.

  4. The client initiates the HTTP handshake and request for certification with the destination server.

  5. The destination Web server sends its certification.

  6. The client receives and verifies the server's certification.

  7. If verified, the client starts the HTTP message head and body data stream.

  8. The server optionally verifies the username and password.

  9. The server verifies the transport protocol and version.

  10. The server verifies the Oracle E-Business Suite username and password.

  11. The server verifies that the message ID is not a duplicate.

  12. The server enqueues the message for consumption.

  13. The server builds the HTTP response message.

  14. The server sends the HTTP response back to the client.

  15. The client reads the response and updates the status tables. If the response indicates the message failed, the retry count is updated and the message is enqueued for retry.

Oracle Transport Agent Post Message

Two OTA servers communicate by sending and receiving a series of name/value pairs in the HTTP body of an HTTP POST/RESPONSE. Following is an example post from the sending OTA server (Note: the header authorization encryption follows the W3C standard):

HTTP Header
Http-Version: HTTP/1.1
Authorization: Digest username="myusername",
realm="testrealm@host.com",
 nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
 uri="/dir/index.html",
qop=auth,
nc=00000001,
cnonce="0a4f113b",
response="6629fae49393a05397450978507c4ef1",
opaque="5ccc069c403ebaf9f0171e9517f40e41"
 Content-length: 12345
Content-type: text/html
HTTP Body
TRANSPORT_PROTOCOL=OXTA
 TRANSPORT_PROTOCOL_VERSION=1.0
REQUEST_TYPE=SEND
MESSAGE_ID=A1234567890ZZ0987654321
MESSAGE_TYPE=XML
MESSAGE_STANDARD=OAG
 TRANSACTION_TYPE=PO
TRANSACTION_SUBTYPE=PROCESS
 DOCUMENT_NUMBER=12345
 PARTYID=9999
PARTY_SITE_ID=8888
 PROTOCOL_TYPE=HTTPS-OXTA
 PROTOCOL_ADDRESS=HTTPS://www.me.com/servlets/oracle.ecx.oxta. transportAgentServer
USERNAME=myusername
PASSWORD=myloginpassword
 ATTRIBUTE1=
 ATTRIBUTE2=
 ATTRIBUTE3=
 ATTRIBUTE4=
 ATTRIBUTE5=
 PAYLOAD=<xml   ... ...> 

The HTTP Body contains the message envelope, message payload, and the following transport parameters:

TRANSPORT_PROTOCOL

The Transport Protocol specifies the messaging protocol to the receiving servlet. The value will always be "OXTA" when sent by an OTA server. The receiving OTA server validates that the TRANSPORT_PROTOCOL is OTA, and then sends back the appropriate response in the HTTP response body.

TRANSPORT_PROTOCOL_VERSION

The Transport Protocol Version specifies the version of the messaging protocol used to send the message

REQUEST_TYPE

This parameter indicates the type of request sent from the OTA server. REQUEST_TYPE is not required on the receiving side. If no value is set, the default "SEND" type is used. Valid values are in the following list:

If the authorization passes, the response will contain an HTTP 200 response code and an OXTA 1000 status message. Refer to HTTP Status Codes for a list of status codes.

MESSAGE_ID

This is the unique message identifier set by the sending OTA server. The receiving OTA server uses this identifier to determine if the message is a duplicate. The identifier is the Oracle AQ message ID from the outbound XML Gateway queue.

MESSAGE_TYPE

This indicates the type of content in the payload. When used with XML Gateway, the value will always be "XML".

TRANSACTION_TYPE

Used by XML Gateway to determine the type of document sent. This is a user-defined value entered in the External Transaction Type field in the Transactions form. Sample values include PO, Invoice, and Shipping. For more information see Define Transactions.

TRANSACTION_SUBTYPE

Used by XML Gateway to determine the transaction subtype of the document sent. This is a user-defined value entered in the External Transaction Subtype field in the Transactions form. Sample values include Create or Change. For more information see Define Transactions.

DOCUMENT_NUMBER

This is the primary identifier of the business document in the payload. Examples include purchase order number and invoice number. This parameter is used in the Transaction Monitor as an identifier when checking the status of a document.

PARTYID

The sender/receiver negotiated identifier that identifies the receiver of the document (company level). This is a user-defined value that is entered in the External Source Location Code of the Trading Partner form. For more information see: Define Trading Partners.

PARTY_SITE_ID

The sender/receiver negotiated identifier that identifies the receiver of the document (company site level). The value of this parameter is the SOURCE_TP_LOCATION_CODE from the Trading Partner form. For more information see: Define Trading Partners.

PROTOCOL_TYPE

This is the application protocol to transmit the document. It also contains an identifier for the program to use to transmit the document over the protocol. The following table lists the valid values for PROTOCOL_TYPE. For more information, see Protocol Type.

PROTOCOL_TYPE Description
HTTP Straight HTTP post
HTTP-ATCH Straight HTTP post with attachment
HTTPS Straight HTTP post using SSL
HTTPS-ATCH Straight HTTP post with attachment, using SSL
HTTP-OXTA OTA Protocol over HTTP (guaranteed delivery)
HTTPS-OXTA OTA Protocol over HTTPS (guaranteed delivery)
OTAH-ATCH OTA Protocol over HTTP (guaranteed delivery) with attachment
OTAHS-ATCH OTA Protocol over HTTPS (guaranteed delivery) with attachment
SMTP Send document via SMTP (e-mail)

PROTOCOL_ADDRESS

This is the fully-qualified address to which to transmit the document. The following table lists sample protocol addresses for the protocol types shown:

PROTOCOL_TYPE Sample PROTOCOL_ADDRESS
HTTP http://www.me.com:8080/servlets/mycustom
HTTP-OXTA http://www.me.com:9000/servlets/oracle.apps.ecx.oxta.TransportAgentServer
HTTPS-OXTA http://www.me.com/servlets/oracle.apps.ecx.oxta.TransportAgentServer
SMTP Me@mydomain.com

USERNAME/PASSWORD

This is the username/password to authenticate on the receiving server. The OTA server uses this username and validates it against valid Oracle E-Business Suite users or valid Exchange users (buyer/supplier login). The username/password values are also in the authorization section of the HTTP header for optional Web server-level authentication.

ATTRIBUTE1

This contains the identifier of the system sending the message. This is a user-defined value entered in the ECX_OAG_LOGICALID profile option. See Define System Profile Options.

ATTRIBUTE2

Not used.

ATTRIBUTE3

This contains the identifier of the final destination for the document, when dynamic routing is implemented. This is a user-defined value entered in the Target Location Code field in the Trading Partner definition form. It is a routing mechanism to notify the receiver to route the document to another trading partner known to the receiver.

For more information about dynamic routing, see: Static and Dynamic Routing.

ATTRIBUTE4

Not used.

ATTRIBUTE5

Not used.

PAYLOAD

Contains the XML document to be processed.

Oracle Transport Agent Response Message

The OTA server uses standard HTTP response codes to determine if the HTTP post (at the HTTP protocol level) was successful. If successful, OTA will examine the HTTP header to determine if the OTA message was successfully delivered. If the HTTP response does not equal 200, OTA assumes the post failed and will requeue the message for retry (until maximum retry has been reached).

The following is an example of an HTTP response:

HTTP Header
 HTTP/1.1 200 OK
 Server: Apache/1.2.0
 Date: Fri, 15 Jun 2002 16:20:46 GMT
 Content-Length: 567
 STATUS_CODE: 1000
 STATUS_DESCRIPTION: OK
 MESSAGE_RECEIPT_ID: A9876543210987654321
 Content-type: text/html
HTTP Body
 <HTML><BODY> <TABLE>   <TR><TD>Status Code</TD><TD>1000</TD></TR> <TR><TD>Status Description</TD><TD>Message Successfully received</TD></TR>  <TR><TD>Message Receipt ID</TD><TD>A9876543210987654321</TD> </TR> </TABLE> </BODY></HTML> 

The HTTP Response body is created for information only and is not read by the sending OTA server. The sending OTA server uses the STATUS_CODE in the HTTP Response header to determine the success or failure.

If the Status Code value is 1000 (meaning success), the MESSAGE_RECEIPT_ID in the HTTP Response body contains a unique identifier generated by the receiving OTA server. This completes the cycle for the guaranteed delivery process.

If the Status Code is anything other than 1000, a failure has occurred. The STATUS_DESCRIPTION field will contain a brief description of the error. Refer to HTTP Status Codes for a list of status codes.

OTA and Attachments

For outbound documents, the OTA client uses information in the Message Map to fetch and bundle the attachment in its outbound package.

For inbound documents, OTA extracts the associated attachments from the inbound MIME message and deposits them into the FND module of the receiving instance.

Note: Oracle Transport Agent also supports MIME messages without attachments. Similarity to the message process with attachments, OTA uses the same approach to process the message, but without further processing attachments if they do not exist.

For more information about how OTA handles attachments, see Attachments and Oracle Transport Agent (OTA).

Authentication Methods

OTA operates according to the security layer implemented at your site. There are two authentication methods supported by SSL: Client Authentication and Server Authentication.

Client Authentication

The server identifies the client by requesting its client certificate. A client certificate is a digital certificate that certifies the identity of the client. A client certificate binds a system name to a specific secret key. Both the client and server certificates are issued by a Certification Authority (CA). Oracle E-Business Suite users can choose to support any CA they wish. Examples of CAs are Identris and Verisign.

Server Authentication

When a client connects to a Web server securely via HTTPS, the server sends back its server certificate to the client for verification. Once verified, the client sends the data, encrypted, to the server. Server Authentication allows the client to identify the server.

To add a trusted CA certificate to the wallet, use the following command line tool orapki:

orapki wallet add -wallet. -trusted_cert -cert ca.crt -pwd welcome

Note: The word welcome is the password of the default Apache wallet under $INST_TOP/certs/Apache.

A trusted CA certificate can also be added to the wallet by opening the wallet using the graphical tool owm and using Operations > Import Trusted Certificate.

Advantages of Client Authentication

Client authentication supplements the traditional username/password application-level security with encrypted, tamper-proof, digital certificates for transport-level security.

Client certificates eliminate anonymity. Every connection to the server from a client requires a client's certificate and a public key that verifies the certificate.

Implementation of Client Authentication

OTA enables client certificate authentication through a set of Java programs.

The SSL handshake begins when an SSL client connects to an SSL server. The SSL handshake protocol is used to authenticate the SSL server to a client and the client to the server. It also contains agreed upon encryption algorithm and keys.

Sequence of Events

  1. The client opens a connection and sends the ClientHello. This message contains the highest SSL version understood by the client, the session ID, and the list of compression methods supported.

  2. The server responds. When the SSL server receives the ClientHello, it responds with either a handshake failure alert or a ServerHello message (that is, the SSL version used by the client, the session ID, and the compression method chosen by the server for this session).

  3. The server sends the certificate along with the CA (who signed the certificate) certificate chain.

  4. The client verifies the server certificate with the CA certificate in the SSL Certificate Chain File (list of CAs that the Client trusts).

  5. The server sends a certificate request to the client.

  6. The client sends its certificate along with the CA (who signed the certificate) certificate chain. If no certificate is available, the client sends a "no certificate" alert. It is up to the SSL server to decide what to do if a no certificate alert is received. The SSL server could continue the SSL transaction with an anonymous client or could terminate the connection by sending a data handshake failure alert.

  7. The client sends a ClientKeyExchange. The client may send a key exchange message depending on the particular public key algorithm.

  8. The server verifies the client certificate with the CA.

  9. The application data is compressed and encrypted according to the compression method.

The OTA message propagation flow with client authentication enabled is displayed in the following diagram. The difference between this flow and the previous flow is the addition of the following two steps after the verfication of the server certificate and before the start of the head/body stream by the client:

Enabling Client Authentication

The initial release of OTA supported server authentication in which the client authenticates the server by requesting a server certificate in SSL mode. OTA is enhanced to support client authentication as well, so that it can respond to a server request for a client certificate. This is to support trading partners who wish to prevent any connection requests from anonymous clients that may harm the server.

In Release 12, the OTA is client authentication enabled by default. The default wallet used by the OTA is the same as the default wallet of the Oracle HTTP server, and this wallet has a user certificate. The same certificate will automatically be used for client authentication during handshake if client authentication is required by the server that the OTA is connecting to.

Note: Any time you make changes to the configuration or properties files, you must bounce the services for that server. As always, please backup the files before modification and test the changes in a non-production environment.

Creating Certificates

There can be only one user certificate in a wallet. If there is a chain of certificates issues by CA(s), the CA certificates should be added as trusted certificates in the same wallet. If creating a new wallet in a different location than $INST_TOP/certs/Apache, then the parameters javax.net.ssl.trustStore and javax.net.ssl.keyStore in $INST_TOP/ora/10.1.3/j2ee/oafm/config/oc4j.properties have to hand edited to point to the new wallet.

There are 4 ways of creating certificates and importing to a wallet:

Using the Graphical Tool Oracle Wallet Manager

Use the following steps to create certificates and import to a wallet:

  1. Open an Existing Wallet

    You need to open the existing wallet unless you create an entirely new wallet to be used by OTA If you create a new wallet, make sure to check the Auto Login check box in the Wallet menu, so that a cwallet.sso is created which can be opened by OTA without a password. The Certificate Request window mentioned in the next step can be opened by clicking on Add Certificate Request in the Operations menu.

  2. Create a Certificate Request

  3. Submit the Certificate Request to a Certifying Authority

  4. Import Your Server Certificate to the Wallet

    Note: Appending the CA certificate to $ORACLE_HOME/sysman/config/b64InternetCertificate.txt is necessary only if you haven't changed the default OTA wallet location from the Oracle HTTP server wallet.

  5. Restart the Middle Tier services if Needed

    Note: Using the adapcctl.sh to restart the Apache is necessary only if you haven't changed the default OTA wallet location from the Oracle HTTP server wallet. In addition, the oafm container should be restarted using adoafmctl.sh.

See My Oracle Support Knowledge Document 376700.1 "Enabling SSL with Oracle Application Server 10g and the E-Business Suite Release 12", Section 2: Middle Tier Setup for instruction details on each step.

Using the Command Line Tool ORAPKI

See My Oracle Support Knowledge Document 376694.1 "Using the Oracle Wallet Manager Command Line Interface in Release 12" for details on creating a certificate using the command line tool ORAPKI.

Note that skip "Section 1: Creating a Wallet" unless you configure an entirely new wallet to be used by OTA. If you create a new wallet, make sure to use the auto_login option, so that a cwallet.sso is created which can be opened by OTA without a password. In Section 4 "Importing a Certificate", appending the CA certificate to $ORACLE_HOME/sysman/config/b64InternetCertificate.txt is necessary only if you haven't changed the default OTA wallet location from the Oracle HTTP server wallet. Use the adapcctl.sh to restart the Apache only if you haven't changed the default OTA wallet location from the Oracle HTTP server wallet. In addition, the oafm container should be restarted using adoafmctl.sh.

Converting Existing Certificates

If you have existing unexpired certificates from a previous implementation of SSL, they can be converted and imported into a Release 12 wallet using the tools:

Copy your server.key, server.crt, and ca.crt to the wallet directory and issue the following command:

$ORACLE_HOME/Apache/Apache/bin/ssl2ossl -cert ./server.crt -key ./server.key -cafile ./ca.crt -wallet . -ssowallet yes

Using openssl to Create a Certificate and Then Converting it to Wallet

Perform the following steps within the directory that contains the OpenSSL executable code:

  1. Create a random seed and place it in the rand.dat file.

    For example:

    openssl md5 * > rand.dat
  2. Generate a private key.

    The following example creates the private key in PEM format and places it in the key.pem file.

    openssl genrsa -rand rand.dat -des3 1024 > key.pem
  3. Create the certificate signing request (CSR).

    The following command creates the public key for your private key and places it in the CSR. You must specify the private key file, the organization, and domain name. You must provide the pass phrase and location of the configuration file.

    openssl req -new -keyout key.pem -out csr.pem -config openssl.cnf
  4. Send the CSR to a certificate authority.

    Send the CSR (csr.pem) to a certificate authority, such as Verisign, and the CA will send you your digital certificate along with its certificate (CA certificate file).

  5. Convert the private key file to traditional format.

    All certificates are PEM-encoded except for the private key file. Convert it to traditional format using the openssl command.

    openssl pkcs8 -in key.pem -out key.pkc -topk8

Certificates created in this way using openssl can be converted to wallet as explained in the previous method, Converting Existing Certificates.

Common Errors

There are some common errors occurred during SSL handshake, see: Common SSL Issues for details.

Setup Parameters

In Release 12, OTA runs in the oafm oc4j container and the system properties are read from the oc4j.properties file of the oafm container which is $INST_TOP/ora/10.1.3/j2ee/oafm/config/oc4j.properties.

Parameters Set Through AutoConfig

The following parameter is set through AutoConfig:

applSysSchema=%s_applsys_user% : APPLSYS

This parameter indicates that the queues in applsys schema are used.

Parameters Controlling Throughout

These parameters set the number of database connections in your system for inbound and outbound requests. The optimum settings for these depend on the load in your system. Setting them too high could result in performance degradation. However, setting them too low could result in transactions having to wait for an excessive time before they are able to get a connection in or out. Both parameters default to 1.

OXTAInPoolSize=%s_oxtainpool_size% : 1

This parameter sets the number of database connections available for inbound requests.

OXTAOutThreads=%s_outbound_threads : 1%

This parameter sets the number of database connections available for outbound requests.

Proxy Parameters

The following parameters control whether a proxy is used for outgoing socket connections:

OXTAOutUseProxy=%s_oxta_proxy% : false

OXTAOutProxyHost=%s_oxta_proxyhost% : ""

OXTAOutProxyPort=%s_oxta_proxyport% : ""

SSL Parameters

In Release 12, OTA uses SSO wallet and uses JSSE APIs to operate the wallet with the following SSL parameters contained in oc4j.properties:

Note: There are two sets of variables; one is used for TrustMaterial and the other one is for KeyMaterial. The AutoConfig by default sets them to the same sets of values since both KeyMaterial and TrustMaterial are present in the default cwallet.

SSL Parameters
Parameter Name AutoConfig Variable Description Default Specified by AutoConfig
javax.net.ssl.trustStore s_ssl_truststore Indicates the location of the trust material for the TrustManager. $INST_TOP/certs/Apache/cwallet.sso
javax.net.ssl.trustStoreType s_ssl_truststoretype Specifies the trustStore file type of trust material for the TrustManager. SSO
test.trustmanager.algorithm s_ssl_trustmanageralgorithm Specifies the TrustManager instance corresponding to this algorithm. OracleX509
javax.net.ssl.keyStore s_ssl_keystore Indicates the location of the key material for the KeyManager. $INST_TOP/certs/Apache/cwallet.sso
javax.net.ssl.keyStoreType s_ssl_keystoretype Specifies the keyStore file type of key material for the KeyManager. SSO
test.keymanager.algorithm s_ssl_keymanageralgorithm Specifies the KeyManager instance corresponding to this algorithm. OracleX509

Load OXTA Servlet (s_load_oxta_servlet) Parameter

This parameter s_load_oxta_servlet is used to control loading of the Oracle Transport Agent servlets (both inbound and outbound) when oc4j starts up.

Parameters Not Set Through AutoConfig

The following parameters must be manually added to the xmlsvcs.properties file if you wish to change the default settings. The default settings are shown with each parameter.

Time Parameters

The following parameters control the amount of time allowed for transactions to complete over OTA:

OXTAOutBaseTimeout=10

The time in seconds allowed by OTA to complete the entire process flow for an outbound request. That is, the time it takes to:

  1. Open a connection.

  2. Send data.

  3. Receive a response.

    Note that this base time is adjusted for higher payloads based on the OutLinearTimeout factor described below.

OXTAOutLinearTimeout=500

This parameter sets a factor that applies to the timeout based on the size of the payload.

The timeout for a given request is calculated based on the following formula:

Timeout = OXTABaseTimeOut + (OXTAOutLinearTimeout/1000) * payload size/1024

where the payload size is in bytes.

For example, for a payload of 1 MB, the timeout using the default parameter settings is:

10 sec + [(500/1000) * 1048576/1024] = 523 seconds

In other words, by default, the factor 500 adds 513 seconds for every MB of data in the payload.

OXTAOutMaxAttempts=5

The number of times to attempt to send an outbound request.

OXTAOutResendDelay=1800

The time in seconds to wait before retrying to send a transaction.

OXTAThreadSleepTime=60

The amount of time in seconds the master thread sleeps between monitoring the Transport Handler threads.

OXTAMaxDbConnectAttempts=20

The maximum number of DB failures that can be tolerated before refraining from making any more connection attempts and going to long sleep for a time given by the parameter below.

OXTABackoffTime=3600

If the Transport Handler threads have died for OXTAMaxDbConnectAttempts number of times due to DB failure, the master thread refrains from further attempts and goes to sleep for a time period in seconds given by this parameter.

Payload Size

OXTAInMaxContent=1000000

The maximum payload size in bytes.

Debug Setting

FND logging is used for OTA, and the AFLOG parameters should be used for enabling the logging. They can be either set in the FND profile options or can be set specifically to the oafm container in which the OTA is running. If the latter option is used, set the following parameters in oc4j.properties:

AFLOG_ENABLED=true

DAFLOG_LEVEL=<1 for Statement level, 6 for Unexpected level. OTA logs only at either of these 2 levels>

AFLOG_MODULE=ecx.oxa%

AFLOG_FILENAME=<filename on midtier>

Since OTA uses Anonymous AppsLog instance, logging does not go to database if this parameter is omitted.

The old parameter OXTALogDebugMsg=false/true is used only in the standalone mode.

Proxy Settings

You must set the following parameters if you are using a proxy server for your outbound requests:

OXTAOutUseProxy=false

Set to "true" if you are using a proxy server.

OXTAOutProxyHost=<Your proxy server name - needed if Proxy=true>

Insert your proxy server name.

OXTAOutProxyPort=<Your proxy server port - needed if Proxy=true>

Insert your proxy server port.

Connecting to Non-OTA Servers

The OTA server (client) includes the capability to send documents to non-OTA servlets that do not employ the OTA messaging protocol. When sending a message, the OTA server initiates an HTTP post to transmit the document. The HTTP response from the receiving Web server indicates whether the receiver was an OTA server.

If the HTTP response does not contain the OTA protocol response body, the sending OTA server assumes the message was received by a non-OTA server. In this case, the standard HTTP response code (that is, 200 meaning "success") is used to determine the success or failure of the message. If the sending OTA server receives an HTTP-200, the message delivery is assumed to be successful. If the sending OTA server receives any other response, it is assumed the delivery failed.

Successful transmissions of documents to non-OTA servers are logged as successfully delivered to a non-OTA server. Delivering to a non-OTA server has the following disadvantages:

Please note that you can set up the OTA server to use HTTP 1.1 for sending documents to a specific non-OTA server by adding a system property with the following syntax:

HttpProtocolVersion-<servername>:<serverport>="1.X"

For example, add a system property HttpProtocolVersion-www.myserver.com:8080="1.1".

If there is no server port specified in the URL for the application, the port in the system property will have to be set to '-1'. For example, HttpProtocolVersion-www.myserver.com:-1="1.1".

Code Connection Samples

The following are code examples for remote Web servers to post a message to the Oracle E-Business Suite using either the HTTP or HTTPS protocol. Use this as a guide to create your own code.

The code to post a message to the Oracle E-Business Suite consists of three parts: the message envelope, the message payload, and the message response.

The message envelope attributes are as follows:

Define these as name-value pairs in your code. The USERNAME and PASSWORD should be set to something meaningful for the receiving Web server.

The PAYLOAD corresponds to your business document represented in XML format.

The receiving Web server sends the message response back to the sending Web server. The message response includes Message Receipt ID, Status Code, and Status Description. A status code of 1000 implies the message was successfully posted.

OTA Connection over HTTP

 import java.sql.*;
import java.net.*;
import java.io.*;
import java.util.*;
public class SendHTTP
{
  final  String[] columnNames = new String[] { "MESSAGE_TYPE", "MESSAGE_STANDARD",
"TRANSACTION_TYPE", "TRANSACTION_SUBTYPE", "DOCUMENT_NUMBER", "PARTYID", "PARTY_SITE_ID", "PARTY_TYPE",
  "PROTOCOL_TYPE", "PROTOCOL_ADDRESS", "USERNAME", "PASSWORD", "ATTRIBUTE1", "ATTRIBUTE2", "ATTRIBUTE3",
  "ATTRIBUTE4", "ATTRIBUTE5", "PAYLOAD" };
   Object[] columnVals = new Object[18];
  int numCols = 0;
  String Encoding = "UTF-8";
    URL url = null;
  String username = null;
  String password = null;
  String target = null;
  String filename = null;
  String MessageID = "SEND" + System.currentTimeMillis();
  String VALUE_SEP  = "=";
  String PAIR_SEP   = "&";
  tring NEW_LINE   = "\n";
    public SendHTTP()
  {
    numCols      = columnNames.length;
    columnVals   = new Object[numCols];
  }
  public   void createBasicMessage() throws Exception
  {
    logMessage("Creating the message");
    StringBuffer tmp = new StringBuffer("This is a test message sent from the Sample java program.");
   columnVals[0] = "XML"; //MESSAGE_TYPE
  columnVals[1] = "OAG"; //MESSAGE_STANDARD
  columnVals[2] = "ECX"; //TRANSACTION_TYPE
  columnVals[3] = "CBODO"; //TRANSACTION_SUBTYPE
  columnVals[4] = "12" ; //DOCUMENT_NUMBER
  columnVals[5] =  "206"; //PARTYID
  columnVals[6] =  "206"; //PARTY_SITE_ID
  columnVals[7] =  "I"; //PARTY_TYPE
  columnVals[8] =  "HTTP"; //PROTOCOL_TYPE
    columnVals[9] =  target;
  columnVals[10] = username ; //USERNAME
  columnVals[11] = password; //PASSWORD
  columnVals[12] = null  ; //ATTRIBUTE1
  columnVals[13] = null  ; //ATTRIBUTE2
  columnVals[14] = null  ; //ATTRIBUTE3
  columnVals[15] = null  ; //ATTRIBUTE4
columnVals[16] = null  ; //ATTRIBUTE5
  columnVals[17] = getPayload();// tmp  ;//Payload
  }
     public void sendMessage() throws Exception
  {
     int bytesRead;
     int total_bytes = 0;
     int bufSize     = 1024;
     char[] buf = new char[bufSize];
     logMessage("Started Sending the message.");
     url = new URL((String)columnVals[9]);
     int port = url.getPort();
     if(port == -1)
     port = 80;
     URL newurl = new URL(url.getProtocol(),url.getHost(),port, url.getFile());
     logMessage("Connecting to " + newurl.getHost() + " port " + port);
          HttpURLConnection conn = (HttpURLConnection)newurl.openConnection();
     conn.setDoOutput(true);
     conn.setDoInput(true);
     OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
     String httpReq = getRequestStr();
     logMessage("Sending to URL.");
     wr.write(httpReq);
     wr.flush();
     logMessage("Response Received  :-");
 logMessage("Message Receipt ID = "+conn.getHeaderField("MESSAGE_RECEIPT_ID"));
     logMessage("Status Code        = "+conn.getHeaderField("STATUS_CODE"));
     logMessage("Status Description = "+conn.getHeaderField("STATUS_DESCRIPTION"));
  }
  public  String getRequestStr() throws Exception
  {
       StringBuffer buf = new StringBuffer();
    StringBuffer httpBody = getHttpBody();
    long bodyLen = 0;
    bodyLen = httpBody.length();
    buf.append(httpBody);
    buf.append("\n");
    return buf.toString();
  }
  public StringBuffer getHttpHeader(long contentLength) throws Exception
  {
    StringBuffer buf = new StringBuffer();
    buf.append("POST " + url.getFile() + " HTTP/1.0\r\n");
    buf.append("Host: " + url.getHost() + ":" + url.getPort() + "\n");
    String userpass = username+ ":" +password;
    buf.append("Content-type: application/x-www-form-urlencoded\n");
    buf.append("Content-length: " + contentLength + "\n");
    buf.append("\r\n");
    return buf;
 }
  public StringBuffer getHttpBody() throws Exception
  {
    StringBuffer contentBuf = new StringBuffer();
    contentBuf.append(encode("TRANSPORT_PROTOCOL"));
    contentBuf.append(VALUE_SEP);
    contentBuf.append(encode("OXTA"));
    contentBuf.append(PAIR_SEP);
    contentBuf.append(encode("TRANSPORT_PROTOCOL_VERSION"));
    contentBuf.append(VALUE_SEP);
    contentBuf.append(encode("1.0"));
    contentBuf.append(PAIR_SEP);
    contentBuf.append(encode("REQUEST_TYPE"));
    contentBuf.append(VALUE_SEP);
    contentBuf.append(encode("SEND"));
    contentBuf.append(PAIR_SEP);
    contentBuf.append(encode("MESSAGE_ID"));
    contentBuf.append(VALUE_SEP);
    contentBuf.append(encode(MessageID));
    contentBuf.append(PAIR_SEP);
      for (int i = 0; i < 18; i++)
    {
       if(columnVals[i] != null)
       {
         contentBuf.append(encode(columnNames[i]));
         contentBuf.append(VALUE_SEP);
                  if(columnVals[i] != null)
            contentBuf.append(encode((String)columnVals[i]));
         else
         contentBuf.append("");
       if(i != 17 )
        contentBuf.append(PAIR_SEP);
       }
      }
     return contentBuf;
  }
  public  void logMessage(String msg)
  {
     System.out.println(msg);
  }
  public String encode(String str)
  {
     String str1 = null;
      try{
     str1 = URLEncoder.encode(str,Encoding);
     }catch(Exception e)
     {
       System.out.println("Unsupported Encoding format");
       System.exit(1);
     }
     return str1;
  }
  public String getPayload()
  {
    StringBuffer tmp = null;
    try 
    {
      BufferedReader in = new BufferedReader(new FileReader(filename));
      String s = null;
      tmp = new StringBuffer();
      while((s = in.readLine())!= null)
      {
         tmp.append(s + "\n");
      }
      in.close();
    }
    catch(Exception ex)
    {
      logMessage("Exception: in reading file");
      logMessage("Sending a string : 'This is a Test String' as payload");
    }
    if(tmp == null || tmp.length() == 0)
    return "This is a Test String";
    else
    return tmp.toString();
  }
  public static void main(String args[])
  {
    //USAGE Target username password;
    SendHTTP sp = new SendHTTP();
    try
    {
      if(args.length < 4)
      {
         sp.logMessage("Usage java sample <Target> <username> <password> <filename>");
         System.exit(1);
      }
      else
      {
        sp.target = args[0];
        sp.username = args[1];
        sp.password = args[2];
        sp.filename = args[3];
        sp.createBasicMessage();
        sp.sendMessage();
        sp.logMessage("Program exiting ");
      }
    }
    catch(Exception e)
    {
      sp.logMessage("Exception = "+e);
    }
  }   
}

OTA Connection over HTTPS

import java.sql.*;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.net.ssl.*;
public class SendHTTPS
{
  final  String[] columnNames = new String[] { "MESSAGE_TYPE", "MESSAGE_STANDARD",
  "TRANSACTION_TYPE", "TRANSACTION_SUBTYPE", "DOCUMENT_NUMBER", "PARTYID", "PARTY_SITE_ID", "PARTY_TYPE",
  "PROTOCOL_TYPE", "PROTOCOL_ADDRESS", "USERNAME", "PASSWORD", "ATTRIBUTE1", "ATTRIBUTE2", "ATTRIBUTE3",
  "ATTRIBUTE4", "ATTRIBUTE5", "PAYLOAD" };
    Object[] columnVals = new Object[18];
  int numCols = 0;
  String Encoding = "UTF-8";
  URL url = null;
  String username = null;
  String password = null;
  String target = null;
  String filename = null;
  String MessageID = "SEND" + System.currentTimeMillis();
  String VALUE_SEP  = "=";
  String PAIR_SEP   = "&";
  String NEW_LINE   = "\n";
   public SendHTTPS()
  {
    numCols      = columnNames.length;
    columnVals   = new Object[numCols];
  }
  public   void createBasicMessage() throws Exception
  {
    logMessage("Creating the message");
    StringBuffer tmp = new StringBuffer("This is a test message sent from the Sample java program.");
  columnVals[0] = "XML"; //MESSAGE_TYPE
  columnVals[1] = "OAG"; //MESSAGE_STANDARD
  columnVals[2] = "ECX"; //TRANSACTION_TYPE
  columnVals[3] = "CBODO"; //TRANSACTION_SUBTYPE
  columnVals[4] = "12" ; //DOCUMENT_NUMBER
  columnVals[5] =  "206"; //PARTYID
  columnVals[6] =  "206"; //PARTY_SITE_ID
  columnVals[7] =  "I"; //PARTY_TYPE
  columnVals[8] =  "HTTPS"; //PROTOCOL_TYPE
  columnVals[9] =  target;
  columnVals[10] = username ; //USERNAME
  columnVals[11] = password; //PASSWORD
  columnVals[12] = null  ; //ATTRIBUTE1
  columnVals[13] = null  ; //ATTRIBUTE2
  columnVals[14] = null  ; //ATTRIBUTE3
  columnVals[15] = null  ; //ATTRIBUTE4
  columnVals[16] = null  ; //ATTRIBUTE5
  columnVals[17] = getPayload();// tmp  ;//Payload
  }
  public void sendMessage() throws Exception
  {
     int bytesRead;
     int total_bytes = 0;
     int bufSize     = 1024;
     char[] buf = new char[bufSize];
     String proxyHost = "www-proxy.us.oracle.com";
     String proxyPort  = "80";
     Properties systemProperties = System.getProperties();
     systemProperties.setProperty("https.proxyHost",proxyHost);
     systemProperties.setProperty("https.proxyPort",proxyPort);
      logMessage("Started Sending the message.");
     url = new URL((String)columnVals[9]);
     int port = url.getPort();
     if(port == -1)
     port = 80;
     URL newurl = new URL(url.getProtocol(),url.getHost(),port, url.getFile());
     logMessage("Connecting to " + newurl.getHost() + " port " + port);
          HttpsURLConnection conn = (HttpsURLConnection)newurl.openConnection();
     conn.setDoOutput(true);
     conn.setDoInput(true);
     OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
     String httpReq = getRequestStr();
     logMessage("Sending to URL.");
     wr.write(httpReq);
     wr.flush();
     logMessage("Response Received  :-");
     logMessage("Message Receipt ID = "+conn.getHeaderField("MESSAGE_RECEIPT_ID"));
     logMessage("Status Code        = "+conn.getHeaderField("STATUS_CODE"));
     logMessage("Status Description = "+conn.getHeaderField("STATUS_DESCRIPTION"));
  }
  public  String getRequestStr() throws Exception
  {
    StringBuffer buf = new StringBuffer();
    StringBuffer httpBody = getHttpBody();
    long bodyLen = 0;
    bodyLen = httpBody.length();
    buf.append(httpBody);
    buf.append("\n");
    return buf.toString();
  }
  public StringBuffer getHttpHeader(long contentLength) throws Exception
  {
    StringBuffer buf = new StringBuffer();
    buf.append("POST " + url.getFile() + " HTTP/1.0\r\n");
    buf.append("Host: " + url.getHost() + ":" + url.getPort() + "\n");
    String userpass = username+ ":" +password;
    buf.append("Content-type: application/x-www-form-urlencoded\n");
    buf.append("Content-length: " + contentLength + "\n");
    buf.append("\r\n");
    return buf;
  }
  public StringBuffer getHttpBody() throws Exception
  {
    StringBuffer contentBuf = new StringBuffer();
    contentBuf.append(encode("TRANSPORT_PROTOCOL"));
    contentBuf.append(VALUE_SEP);
    contentBuf.append(encode("OXTA"));
    contentBuf.append(PAIR_SEP);
    contentBuf.append(encode("TRANSPORT_PROTOCOL_VERSION"));
    contentBuf.append(VALUE_SEP);
    contentBuf.append(encode("1.0"));
    contentBuf.append(PAIR_SEP);
    contentBuf.append(encode("REQUEST_TYPE"));
    contentBuf.append(VALUE_SEP);
    contentBuf.append(encode("SEND"));
    contentBuf.append(PAIR_SEP);
    contentBuf.append(encode("MESSAGE_ID"));
    contentBuf.append(VALUE_SEP);
    contentBuf.append(encode(MessageID));
    contentBuf.append(PAIR_SEP);
        for (int i = 0; i < 18; i++)
    {
       if(columnVals[i] != null)
       {
         contentBuf.append(encode(columnNames[i]));
         contentBuf.append(VALUE_SEP);
                if(columnVals[i] != null)
         contentBuf.append(encode((String)columnVals[i]));
         else
         contentBuf.append("");
         if(i != 17 )
        contentBuf.append(PAIR_SEP);
       }
     }
     return contentBuf;
  }
  public  void logMessage(String msg)
  {
    System.out.println(msg);
  }
  public String encode(String str)
  {
     String str1 = null;
     try{
     str1 = URLEncoder.encode(str,Encoding);
     }catch(Exception e)
     {
       System.out.println("Unsupported Encoding format");
       System.exit(1);
     }
     return str1;
  }
  public String getPayload()
  {
    StringBuffer tmp = null;
    try 
    {
      BufferedReader in = new BufferedReader(new FileReader(filename));
      String s = null;
      tmp = new StringBuffer();
      while((s = in.readLine())!= null)
      {
         tmp.append(s + "\n");
      }
      in.close();
    }
    catch(Exception ex)
    {
      logMessage("Exception: in reading file");
      logMessage("Sending a string : 'This is a Test String' as payload");
    }
    if(tmp == null || tmp.length() == 0)
    return "This is a Test String";
    else
    return tmp.toString();
  }
  public static void main(String args[])
  {
    //USAGE Target username password;
    SendHTTPS sp = new SendHTTPS();
    try
    {
      if(args.length < 4)
      {
         sp.logMessage("Usage java sample <Target> <username> <password> <filename>");
         System.exit(1);
      }
else
      {
        sp.target = args[0];
        sp.username = args[1];
        sp.password = args[2];
        sp.filename = args[3];
        sp.createBasicMessage();
        sp.sendMessage();
        sp.logMessage("Program exiting ");
      }
    }
    catch(Exception e)
    {
      sp.logMessage("Exception = "+e);
    }
  }   
}

Troubleshooting

For information on SSL issues, see Common SSL Issues.

HTTP Status Codes

The following table lists the error response codes returned in the HTTP Response by the OTA server.

Status Code Error Code Description
1000 OK Request handled successfully.
2000 ECX_OXTA_DB_UNAVAIL Database unavailable. Cannot get connection to the database.
2001 ECX_OXTA_SERVER_ERR Unexpected server-side error. Client should retry.
3000 ECX_OXTA_BAD_REQ Missing TRANSPORT_PROTOCOL, TRANSPORT_PROTOCOL_VERSION, or MESSAGE_TYPE.
3001 ECX_OXTA_UNKNOWN_REQ Invalid value for MESSAGE_TYPE.
3002 ECX_OXTA_AUTH_MISSVAL Incomplete credentials. Username or Password not available for request.
3003 ECX_OXTA_AUTH_FAILURE Authentication failure. Invalid user password.
3004 ECX_OXTA_PROTCL_NOTSUPP Oracle Transport Agent protocol version not supported by server.
3005 ECX_OXTA_PAYLOAD_NULL Message has NULL payload.
3100 ECX_OXTA_SEND_MISSVAL Required parameters for the SEND post are missing.
3101 ECX_OXTA_LEN_MISS Request header content length attribute not set.
3102 ECX_OXTA_LEN_TOOLARGE Size of content larger than specified in request header content length attribute.
3200 ECX_OXTA_AUTH2_MISSVAL Parameter missing for AUTH2 request. Verify that the party_site_id and the transaction_type are valid.
3201 ECX_OXTA_AUTH2_FAILURE AUTH2 request failed.
3300 ECX_OXTA_EME_MISSVAL E-mail address or payload was not passed in the EME request.
3301 ECX_OXTA_EME_INVALID_EMAIL Incorrect e-mail address format for EME request.
3302 ECX_OXTA_EME_SMTP_NOTSET Mail server not set up in config.
4000 ECX_OXTA_UNKNOWN_PROTCL Invalid protocol type for SEND request.
4001 ECX_OXTA_TIMEOUT Time out for this transport request reached.
4002 ECX_OXTA_CLIENT_ERR Unexpected client side exception.
4003 ECX_OXTA_MAX_ATTEMPTS Exceeded the max number of attempts for transport.
4100 ECX_OXTA_SMTP_NOTSET Mail server not set up in config.
4101 ECX_OXTA_INVALID_EMAIL Incorrect e-mail address format.
4102 ECX_OXTA_MAIL_ERR Error when trying to send mail.
4103 ECX_OXTA_MAILJAR_NOT_EXISTS SMTP not enabled. Ensure that mail.jar is present in your Java classpath.
4104 ECX_OXTA_ACTJAR_NOT_EXISTS SMTP not enabled. Ensure that activation.jar is present in your Java classpath.
4200 ECX_OXTA_INVALID_URL Incorrect URL format.
4201 ECX_OXTA_PROXY_FAILURE Cannot open connection to proxy server.
4202 ECX_OXTA_CONNECT_FAILURE Cannot connect to host:port.
4203 ECX_OXTA_UNKNOWN_RES Response from the server not in a format understood by the client.
4300 ECX_OXTA_INVALID_CACERT Failed to open the certificate file/failed to read certificate from the file.
4301 ECX_OXTA_SSLHANDSHAKE_FAILURE Failed to perform handshake when getting SSL connection.
4302 ECX_OXTA_SSLVERICHAIN_FAILURE Error when verifying chain certificate.
5000 ECX_OXTA_PROTOCOL_MISS Protocol value missing from inbound message.
5001 ECX_OXTA_USERNAME_MISS Username value missing from the inbound message.
5002 ECX_OXTA_PASSWORD_MISS Password value missing from the inbound message.