This document describes the UltraESB public API for mediating messages, and the configuration of the various transports, WS-Security and AS2 options
Overview
The UltraESB public API has been separated into its own JAR file, and published as a Maven 2 artifact at the AdroitLogic Maven 2 repository:
http://downloads.adroitlogic.org/maven2
Additionally, Javadocs for the public API is published at : http://api.adroitlogic.com
Mediating Messages within a Sequence
The UltraESB mediation is based around two simple classes - Mediation, and Message. While the Mediation class exposes the built-in support for common actions, the Message class exposes the various aspects of a message, so that user could develop own utilities, extensions, methods of custom logic for mediating messages as required. The payload of a Message belongs to an Object implementing the MessageFormat interface - which exposes the raw message payload where required. The MessageFormat is determined by the transport accepting a message, and maybe converted during mediation. For example, an HTTP/S request is held as a RawFileMessage - but maybe converted to and from a DOMMessage etc. A JMS Text Message will default to a StringMessage, while a Map Message will default to a MapMessage etc. In future other MessageFormats may be introduced with additional transports.
Variables exposed to Java and JSR-223 Script fragments
Every sequence is passed three variables as follows:
- msg - Represents the current message, and is defined by the interface Message
- mediation - Allows easy access to a rich and powerful set of mediation utility methods and defined by the interface Mediation
- logger - a logger category that maybe used for logging from within user code during mediation
Mediation utilities
The following common utility methods are exposed by the Mediation instance. In future, new methods may be made available in addition to these.
Refer to http://api.adroitlogic.org/org/adroitlogic/ultraesb/api/Mediation.html for the latest version
void |
addPreemptiveBasicAuthentication(Message msg, java.lang.String username, java.lang.String password) Adds an HTTP transport header for pre-emptive basic authentication for this message. |
void |
addPreemptiveBasicAuthentication(Message msg, java.lang.String username, java.lang.String password, java.lang.String charset, boolean proxy) Adds an HTTP transport header for pre-emptive basic authentication for this message. |
void |
convertFromFI(Message m) Convert the payload of the current message from a FastInfoset binary to an XML message (Note the XML payload is still kept as a RawFileMessage by default and maybe converted into a DOM message if required) |
void |
convertToDOM(Message m) Convert the current message into a DOMMessage |
void |
convertToFI(Message m) Convert the XML message into a FastInfoset binary message |
void |
dropMessage(Message m) Mark this message as a 'Dropped' message. |
org.w3c.dom.NodeList |
extractAsNodeListUsingXPath(Message m, java.lang.String exprn, java.lang.String[][] ns) Evaluate the given XPath expression against the XML payload, and return result as a NodeList This method converts the current payload into a DOMMessage |
java.lang.String |
extractAsStringUsingXPath(Message m, java.lang.String exprn, java.lang.String[][] ns) Evaluate the given XPath expression against the XML payload, and return result as a String This method converts the current payload into a DOMMessage |
boolean |
filter(Message m, java.lang.String exprn, java.lang.String[][] ns) Evaluate the given boolean XPath expression over the XML payload |
boolean |
filter(Message m, java.lang.String exprn, java.lang.String[][] ns, java.lang.String regex) Evaluate the given XPath expression over the XML payload and compare the resulting String value with the regular expression for a match. |
AS2Manager |
getAS2Manager() Get the AS2Manager from the bean with the id "as2Manager" |
java.sql.Connection |
getConnection(java.lang.String dataSource) Get a database connection from the datasource defined in the [Spring] configuration with the given id |
java.lang.String |
getCookie(Message msg, java.lang.String name) Return the value of the cookie with the given name |
javax.sql.DataSource |
getDataSource(java.lang.String dataSource) Get the DataSource with the specified id from the [Spring] configuration |
java.lang.String |
getJvmRoute(Message msg) Return the jvmRoute from the JSESSIONID cookie or jsessionid URL parameter of an HTTP/S request |
java.lang.String |
getSoapAddressingAction(Message msg) Get the WSA Action header |
java.lang.String |
getSoapAddressingFaultTo(Message msg) Get the WSA FaultTo header |
java.lang.String |
getSoapAddressingFrom(Message msg) Get the WSA From header |
java.lang.String |
getSoapAddressingMessageID(Message msg) Get the WSA MessageID header |
java.lang.String |
getSoapAddressingReplyTo(Message msg) Get the WSA ReplyTo header |
java.lang.String |
getSoapAddressingTo(Message msg) Get the WSA To header |
java.lang.String |
getSoapFaultCode(Message msg) Extract the SOAP 1.1 Fault/faultcode or SOAP 1.2 Fault/Code/Value if exists |
java.lang.String |
getSoapFaultDetail(Message msg) Extract the SOAP 1.1 detail or SOAP 1.2 Detail if exists |
java.lang.String |
getSoapFaultString(Message msg) Extract the SOAP 1.1 Fault/faultstring or SOAP 1.2 Reason/Text if exists |
java.lang.String |
getSoapHeaderAsString(Message msg, java.lang.String namespace, java.lang.String name) Extract the SOAP 1.1/1.2 header value as a String |
java.util.Map |
getSoapHeadersAsStrings(Message m) Extract the SOAP 1.1/1.2 header values as a Strings |
java.lang.Object |
getSpringBean(java.lang.String id) Get the Spring bean with the given ID from the [Spring] configuration |
java.lang.Object |
getSpringBean(java.lang.String id, java.lang.Class clazz) Get the Spring bean with the given ID from the [Spring] configuration |
WSSecurityManager |
getWSSecurityManager() Get the WS-Security Manager defined with the id "wssecMgr" |
boolean |
isHessian(Message msg) Check the message content type to see if it indicates a Hessian message |
boolean |
isSoap(Message msg) Check the message content type to see if it indicates a SOAP 1.1 or 1.2 message serialized as XML |
void |
mergeXMLAttachmentsUnderElement(Message msg, java.lang.String rootElemName) Replace the current XML payload with a top level element as specified, and merge the payloads from the current body, and attachments underneath that |
void |
mergeXMLAttachmentsUnderElement(Message msg, java.lang.String rootElemName, java.lang.String rootNS) Replace the current XML payload with a top level element as specified, and merge the payloads from the current body, and attachments underneath that |
java.lang.String |
readPayloadAsString(Message m) Return the current message payload as a String limited to 8K |
boolean |
remove(Message m, java.lang.String exprn, java.lang.String[][] ns) Remove the XPath expression specified node from the XML payload. |
void |
retainElementAsPayload(Message m, java.lang.String exprn, java.lang.String[][] ns) Replace the current XML payload with the resulting element from the XPath expression result |
void |
savePayloadToFile(Message m, java.lang.String filePath) Save the current message payload into the specified file |
void |
sendPart(Message msg, int code, int part, int size) Send the current payload as one single part of the complete payload. |
void |
sendResponse(Message msg, int code) Trigger off sending the current payload as a synchronous response message for the currently processing message |
void |
sendResponseAndDrop(Message m, int code) Trigger off sending the current payload as a synchronous response message for the currently processing message, and stop processing this message thereafter. |
void |
sendToEndpoint(Message m, java.lang.String endpointName) Send the current message to the endpoint with the given name. |
void |
setCookie(Message msg, java.lang.String name, java.lang.String value) Set a HTTP cookie on the message |
void |
setCookie(Message msg, java.lang.String name, java.lang.String value, java.lang.String path, int age) Set a HTTP cookie on the message |
void |
setCookie(Message msg, java.lang.String name, java.lang.String value, java.lang.String path, java.lang.String domain, int age, boolean secure) Set a HTTP cookie on the message |
void |
setPayloadFromByteArray(Message m, byte[] bytes) Set the payload of the current message to the byte array passed |
void |
setPayloadFromFile(Message m, java.lang.String filePath) Set the current payload of the message as the content of the given file |
void |
setPayloadFromString(Message m, java.lang.String text) Set the payload of the current message to the given String |
void |
setPayloadToSOAP11Fault(Message m, java.lang.String code, java.lang.String faultString, java.lang.String detail) Set the payload of the current message to a SOAP 1.1 fault message with the given code, faultString and detail |
void |
setPayloadToSOAP12Fault(Message m, java.lang.String code, java.lang.String reason, java.lang.String detail) Set the payload of the current message to a SOAP 1.2 fault message with the given code, reason and detail |
void |
transform(Message msg, java.lang.String xsltFilename) Transform the message payload by XSLT (without any parameters), assuming a non DOM result and assuming that the complete message payload will be used as the source of the transformation, and the result will replace the complete message payload |
void |
transform(Message msg, java.lang.String xsltFilename, java.lang.String exprn, java.lang.String[][] ns) Transform the message payload by XSLT (without any parameters), assuming a non DOM result |
void |
transform(Message msg, java.lang.String xsltFilename, java.lang.String exprn, java.lang.String[][] ns, boolean domResult, java.util.Map parameters) Transform the message payload by XSLT |
void |
validate(Message m, java.lang.String schema) Validate the current message against one single schema |
void |
validate(Message m, java.lang.String[] schemas) Validate the current message against one or more schemas |
void |
validate(Message m, java.lang.String[] schemas, java.lang.String exprn, java.lang.String[][] ns) Validate the current message - or an element of it selected via an XPath expression - against one or more schemas |
The Message object
The Message class exposes the following methods as its public API. In future, more methods maybe made available
Refer to http://api.adroitlogic.org/org/adroitlogic/ultraesb/api/Message.html for the latest version
void |
addAttachment(java.lang.String key, MessageFormat att) Add an attachment to the message identified by the specified key |
void |
addException(ErrorInfo e) Attach an error that this message encountered |
void |
addException(java.lang.Exception e) Attach an Exception that this message encountered |
void |
addMessageFileForRelease(MessageFile mf) Associate a MessageFile (a temporary file) for release back to the FileCache, once this message completes. |
void |
addMessageFormatForRelease(MessageFormat mf) Link a MessageFormat (i.e. |
void |
addMessageForRelease(Message m) Link a Message for GC along with this message |
void |
addMessageProperty(java.lang.String key, java.lang.Object value) Add a message property - i.e. |
void |
addResponseCorrelation(java.lang.String key, java.lang.Object value) Add an entry for correlation into the response message for this message. |
void |
addTransportHeader(java.lang.String key, java.lang.String value) Add a transport header to this message |
void |
beginTransaction() Begin a new Spring transaction and associate its context with this message |
Message |
cloneMessage() Clone the current message - without transport headers, properties or payload. |
void |
commitTransaction() Invoked to request a commit of the current transaction |
boolean |
containsAttachments() Does this message contain attachments? |
Message |
createDefaultResponseMessage() Create the default response message to this message |
MessageFormat |
detachPayload() Detach the current payload from this message. |
MessageFormat |
getAttachment(java.lang.String key) Get the attachment with the given key |
java.util.Map |
getAttachments() Return the Map of attachments keyed with the identifying string |
java.lang.String |
getContentType() Get the content type of the message if set. |
java.util.UUID |
getCorrelatedRequestUUID() The request message UUID for a response message |
MessageFormat |
getCurrentPayload() Get the current payload of the message |
java.lang.String |
getDestinationURL() Get the current destination URL for this message. |
java.util.Map |
getDuplicateTransportHeaders() Get the map of current transport header duplicate values |
java.util.List |
getExceptions() Get a list of errors this message encountered |
java.lang.String |
getFirstTransportHeader(java.lang.String key) Get the first transport header with the given key |
java.lang.String |
getFirstTransportHeaderIgnoreCase(java.lang.String key) This will perform a case insensitive lookup for the first occurrence of the given transport header |
ErrorInfo |
getLastException() Get the last error encountered and linked to this message |
Mediation |
getMediation() Return a reference to Mediation utilities |
java.lang.Object |
getMessageProperty(java.lang.String key) Get the message property associated with the specified key |
java.util.UUID |
getMessageUUID() Get the UUID of the message |
MessageFormat |
getOriginalPayload() The original payload of the message - as received from the transport, unless modified |
java.util.UUID |
getParentMessageUUID() The parent message UUID |
java.lang.String |
getProxyServiceID() Get the id of the proxy service to which this message belongs |
java.util.Map |
getTransportHeaders() Get the map of current transport header values ignoring duplicates |
java.util.List |
getTransportHeaders(java.lang.String key) Get a List of transport header values for the given key |
org.springframework.transaction.TransactionStatus |
getTxnStatus() Get the Spring TransactionStatus for this message |
void |
holdCompletion() Used to hold execution of the message completion handlers when the current sequence completes. |
boolean |
isHoldCompletionTask() Is this message currently marked to hold completion tasks on at the end of the execution thread (e.g. |
boolean |
isMarkedAsFailed() Is this message currently marked as failed? |
boolean |
isRequest() Is this message a request message? |
boolean |
isResponse() Is this message a response message? |
void |
removeTransportHeader(java.lang.String key) Remove all occurrences of the specified transport header |
void |
replaceTransportHeader(java.lang.String key, java.lang.String value) Replace the first occurrence of the transport header with the given value |
void |
resumeAndCommitTransaction() Invoked typically in a async-response flow to re-energize the suspended transaction, and then commit |
void |
resumeAndRollbackTransaction() Invoked typically in a async-response flow to re-energize the suspended transaction, and then roll it back |
void |
rollbackTransaction() Invoked to request a rollback of the current transaction |
void |
setContentType(java.lang.String contentType) Set the content type of the message |
void |
setCurrentPayload(MessageFormat currentPayload) Set the current payload of the message |
void |
setDestinationURL(java.lang.String destinationURL) Set the destination URL for this message |
void |
setMarkedAsFailed(boolean markedAsFailed) Mark this message as failed, by passing true. |
void |
suspendTransaction() Invoked typically in a request flow to suspend the active transaction, and to save its state into the response correlation map |
Message Formats (i.e. Payload formats)
Refer to the full API documentation for the MessageFormats listed below
- RawFileMessage - The default message format used by the HTTP/S transport and File (file, sftp, ftp, ftps) transport
- StringMessage - JMS Text messages etc
- DOMMessage - Messages parsed into XML (for XPath evaluation or XSLT transformation)
- MapMessage - JMS Map messages etc
- ObjectMessage - JMS Object messages etc
- ByteArrayMessage - JMS Bytes messages etc
- DataHandlerMessage - Email messages etc
AS2 Manager
The use of the AS2 support requires the definition of the AS2Manager to the configuration. This configures the local AS2 identifier, email address and keystore information - through the KeystoreManager. The AS2 support will be further improved in the subsequent releases, with end-user feedback received. Currently the AS2Manager exposes the following methods
void |
notifyReceiptOfMDN(Message msg, java.util.Map headers, java.io.InputStream in) Receive notification about the receipt of an asynchronous MDN |
void |
notifySendStatusFromTransport(int httpStatusCode, java.lang.String originalMessageID) Receive notification from transport level send operation |
void |
processIncomingAS2Message(Message msg) Routine to process a new AS2 message received over HTTP/S, and parse it and take necessary AS2 protocol level action on it, and populate the current message with the attachments for subsequent processing |
AS2SendMessageProcessingResult |
sendNewAS2Message(Message msg, Partner partner) Create an AS2 message using the current Message and its attachments, and send it to the specified Partner |
The core components in the use of AS2 is as per the following diagram. The AS2 support uses two proxy services "AS2Receiver" and "AS2Sender" through the HTTP/S transport, which interacts with the AS2Manager instance. An external partner thus may send a new AS2 message, or an asynchronous MDN to the AS2Receiver Proxy service URL, and it will pass it to the AS2Manager via the processIncomingAS2Message() method. After the AS2Manager processes a new AS2 message or MDN, it will issue the corresponding transport level closure or issuance of the synchronous MDN automatically, and then the control is returned to the AS2Receiver sequence with the current message set to the AS2 message payload received and its attachments if any. (See sample # 351)
To send a new AS2 message to a trading partner, one may typically use a Proxy service - such as a File transport proxy that will poll for messages to be sent to AS2 partners - and then invoke the AS2Manager.sendNewAS2Message() passing the Partner information and the message. It is perfectly possible for this process to be triggered by another Java bean/logic defined in the main Spring configuration, by calling directly to the AS2Manager. On a successful send with a MDN receipt, the notifyReceiptOfMDN() is called back, while on a transport level ack or error, the notifySendStatusFromTransport() is called back, and the message flagged as failed.

WS-Security Support
The WSSecurityManager configures the WS-Security support of the UltraESB. Configuration requires the specification of the identity/trust keystores and passwords, and the credentials against required certificates or aliases. There are two variations of the constructor to be used when the identity and trust stores are the same and different.
e.g. The definition of the WSSecurityManager to the configuration when the trust and identity keystores are the one and the same. The Map passed to the constructor specifies the alias and the password for the credentials to be used. Note that the passwords used in the configuration can be easily protected / encrypted using as per this article.
<bean id="wssecMgr" class="org.adroitlogic.soapbox.WSSecurityManager">
<constructor-arg value="samples/conf/keys/ws-sec-keystore.jks"/>
<constructor-arg value="password"/>
<constructor-arg>
<map>
<entry key="alice" value="password"/>
<entry key="bob" value="password"/>
</map>
</constructor-arg>
</bean>
Once the WSSecurityManager is configured, it could be used to verify security of incoming messages, and issue custom error messages - possibly hiding the original cause of the security failure as in the example given below. Refer to the sample configuration # 204 for more details.
<u:inSequence>
<u:java import="org.adroitlogic.soapbox.*;"><![CDATA[
try {
WSSecurityManager wssecMgr = (WSSecurityManager) mediation.getSpringBean("wssecMgr");
wssecMgr.verifyUsernameTokenAuthentication(msg);
wssecMgr.verifyTimestampedEncryptedAndSignedMessage(msg, true);
System.out.println("Validated User : " + msg.getMessageProperty(MessageSecurityContext.USER_NAME));
System.out.println("Validated Roles : " + msg.getMessageProperty(MessageSecurityContext.USER_ROLES));
} catch (Exception e) {
mediation.setPayloadToSOAP11Fault(msg, null, "Security validation failed", null);
mediation.sendResponse(msg, 500);
}
]]></u:java>
</u:inSequence>
The full sample # 204 configuration lists examples of how WS-Security is validated and used - including the use of Timestamps, Signatures and Encryption. Additionally, the same example shows how UsernameToken authentication maybe added to a message being sent via the UltraESB.
The WSSecurityManager exposes the following methods for mediation
void |
addDigestUsernameTokenAuthentication(Message msg, java.lang.String username, java.lang.String password) Add a WS-Security Username Token authentication element to the request, with a nonce, created and hashed password |
void |
addDigestUsernameTokenAuthenticationWithTimestamp(Message msg, java.lang.String username, java.lang.String password) Add a WS-Security Username Token authentication element and a Timestamp element to the request, with a nonce, created and hashed password |
void |
addPlainUsernameTokenAuthenticationWithTimestamp(Message msg, java.lang.String username, java.lang.String password) Add a WS-Security Username Token authentication element and a Timestamp elemtn to the request, with a nonce, created and hashed password |
void |
addUsernameTokenAuthentication(Message msg, java.lang.String username, java.lang.String password, boolean hashed, boolean addNonceAndCreated, boolean includeTimestamp) Add a WS-Security Username Token authentication element to the request |
void |
removeSecurityHeader(Message msg) Remove the WS-Security header from a message |
void |
timestampAndEncryptMessage(Message msg, java.lang.String encryptionAlias) Secure message with a timestamp and encrypt - using default timestamp TTL of 5 minutes and key size of 256 |
void |
timestampAndEncryptMessage(Message msg, java.lang.String encryptionAlias, long millis, java.lang.String algo) Secure message with a timestamp and encrypt - using specified timestamp TTL |
void |
timestampAndSignMessage(Message msg, java.lang.String signatureAlias) Secure message with a timestamp and signature - using default timestamp TTL of 5 minutes |
void |
timestampAndSignMessage(Message msg, java.lang.String signatureAlias, long millis) Secure message with a timestamp and signature - using specified timestamp TTL |
void |
timestampMessage(Message msg) Secure message with a timestamp - using default timestamp TTL of 5 minutes |
void |
timestampMessage(Message msg, long millis) Secure message with a timestamp - using specified timestamp TTL |
void |
timestampSignAndEncryptMessage(Message msg, java.lang.String encryptionAlias, java.lang.String signatureAlias) Secure message with a timestamp, signature and encrypt body - using default timestamp TTL of 5 minutes and keysize of 256 |
void |
timestampSignAndEncryptMessage(Message msg, java.lang.String encryptionAlias, java.lang.String signatureAlias, long millis, java.lang.String algo) Secure message with a timestamp, signature and encrypt body - using specified timestamp TTL |
void |
verifyTimestampedAndEncryptedMessage(Message msg, boolean remove) Verify that the message is timestamped and encrypted |
void |
verifyTimestampedAndSignedMessage(Message msg, boolean remove) Verify that the message is timestamped and signed |
void |
verifyTimestampedEncryptedAndSignedMessage(Message msg, boolean remove) Verify that the message is timestamped, encrypted and signed |
void |
verifyTimestampedMessage(Message msg, boolean remove) Verify that the message is timestamped and the timestamp valid |
void |
verifyUsernameTokenAuthentication(Message msg) Verify that the message contains UsernameToken authentication information, and that its valid |
void |
verifyUsernameTokenAuthentication(Message msg, boolean remove) Verify that the message contains UsernameToken authentication information, and that its valid |
Transports Configuration
The various transports allows many configuration options. These are well described in the links reachable from the following
HTTP/S Transport
JMS Transport
File Transport (i.e. file, sftp, ftp, ftps)
Email Transport (POP3, IMAP, SMTP)
| < Prev | Next > |
|---|