![]() ![]() ![]() ![]() ![]() ![]() |
Careful planning of development activities can greatly reduce the time and effort you spend developing a custom transport provider. The following sections describe transport provider concepts and functionality to help you get started:
A transport provider implements the interfaces of the Transport SDK and provides a bridge between AquaLogic Service Bus and mechanisms by which messages are sent or received. Such mechanisms can include specific transport protocols, such as HTTP, as well as other entities, such as a file or an e-mail message. A transport provider manages the life cycle and runtime behavior of transport endpoints. An endpoint is a resource where messages originate or are targeted.
Figure 2-1 illustrates the basic flow of messages through AquaLogic Service Bus. A client sends a message to AquaLogic Service Bus using a specific transport protocol. A transport provider processes the inbound message, handling communication with the service client endpoint and acting as the entry point for messages into AquaLogic Service Bus.
The binding layer, also shown in Figure 2-1, packs and unpacks messages, handles message security, and hands messages off to the AquaLogic Service Bus Pipeline.
Tip: | For more information on AquaLogic Service Bus message brokering and the role of the transport layer, see AquaLogic Service Bus Concepts and Architecture. For more detailed sequence diagrams that describe the message flow through AquaLogic Service Bus, see UML Sequence Diagrams. |
By default, AquaLogic Service Bus includes transport providers that support several commonly used transport protocols, such as HTTP, JMS, File, FTP, and others. These native providers let you configure proxy and business services that require these common transport protocols. These built-in providers are listed in Table 2-1.
Tip: | For more information using and configuring these native transport providers, see the AquaLogic Service Bus User Guide. |
This section briefly describes the purpose and features of the Transport SDK. This section includes these topics:
AquaLogic Service Bus processes messages independently of how they flow into or out of the system. The Transport SDK provides a layer of abstraction between AquaLogic Service Bus and components that deal with the flow of data in and out of AquaLogic Service Bus. This layer of abstraction allows you to develop new transport providers to handle unique transport protocols. For a list of the transport providers that are installed with AquaLogic Service Bus, see Table 2-1, Transport Providers Installed with AquaLogic Service Bus, on page 2-3.
The SDK abstracts from the rest of AquaLogic Service Bus:
This section describes the primary features of the Transport SDK.
A transport provider developed with the Transport SDK handles inbound and outbound messages as follows:
The Transport SDK handles outbound and inbound messages independently. An inbound message can be bound to one transport protocol and bound to a different transport protocol on the outbound endpoint.
For more information on how messages flow through AquaLogic Service Bus, see the AquaLogic Service Bus User Guide.
Certain transports include artifacts that need to be deployed to WLS server. For instance, a JMS proxy is implemented as a message-driven bean. This artifact, an EAR file, must be deployed when the new JMS proxy is registered. Similarly, the EJB transport provider employs an EAR file that must be deployed when a new EJB business service is registered. Other kinds of artifacts might require deployment, such as a JMS transport, which may create queues and topics as part of the service registration. The SDK allows you to support these artifacts and lets you participate in the WLS deployment cycle. If the deployment of one of these artifacts fails, the AquaLogic Service Bus session is notified and the deployment is canceled. This feature of the SDK allows for the atomic creation of services. If something fails, the session reverts to its previous state.
Note: | To participate in WLS deployment cycle, the transport provider must implement the TransportWLSArtifactDeployer interface. The primary benefit of this technique is atomic WebLogic Server deployment, which can be rolled back if needed. For more information on this interface, see Summary of General Interfaces and see When to Implement TransportWLSArtifactDeployer. |
Because the server has a limited number of threads to work with when processing messages, asynchrony is important. This feature allows AquaLogic Service Bus to scale to handle large numbers of messages. After a request is processed, the thread is released. When the business service receives a response (or is finished with the request if it is a one-way message), it notifies AquaLogic Service Bus asynchronously through a callback.
See also Support for Synchronous Transactions and The Threading Model.
With the Transport SDK, you can implement inbound property modes and outbound property modes. These connection and endpoint modes are specified in the transport provider’s XML Schema definition file. For more information on this file, see 3. Create an XML Schema File for Transport-Specific Artifacts. This schema is available to the AquaLogic Service Bus Pipeline for filtering and routing purposes.
This section lists related features that are provided by the transport manager. The transport manager provides the main point of centralization for managing different transport providers, endpoint registration, control, processing of inbound and outbound messages, and other functions. These features do not require specific support by a transport provider.
The Transport SDK supports load balancing and failover for outbound messages. Supported load balancing options are:
The transport manager handles these monitoring metrics:
This section explains the basic use cases for writing a custom transport provider. In some cases, it is appropriate to chose an alternative approach. This section includes the following topics:
One of the prime use cases for the Transport SDK is to support a specialized transport that you already employ for communication between your internal applications. Such a transport may have its own concept of setup handshake, header fields, metadata, or transport-level security. Using the Transport SDK, you can create a transport implementation for AquaLogic Service Bus that allows configuring individual endpoints, either inbound, outbound or both. With a custom transport implementation, the metadata and header fields of the specialized transport can be mapped to context variables available in a proxy service pipeline.
Use the Transport SDK when the transport provider needs to be seamlessly integrated into all aspects of AquaLogic Service Bus for reliability, security, performance, management, user interface, and the use of the UDDI registry.
Some cases where it is appropriate to use the Transport SDK to develop a custom transport include:
Alternatively, you can use the Transport SDK to support a specialized protocol over one of the existing transports provided with AquaLogic Service Bus. Examples of this could include supporting:
Creating a new AquaLogic Service Bus transport provider using the Transport SDK can be a significant effort. The Transport SDK provides a rich, full featured environment so that a custom transport has all of the usefulness and capabilities of the transports that come natively with AquaLogic Service Bus. But such richness brings with it some complexity. For certain cases, you might want to consider easier alternatives.
If you need an extension merely to support a different format message sent or received over an existing protocol, it may be possible to use the existing transport and use a Java Callout to convert the message. For example, suppose you have a specialized binary format (such as ASN.1 or a serialized Java object) being sent over the standard JMS protocol. In this case, you might consider defining the service using the standard JMS transport with the service type being a messaging service with binary input/output messages. Then, if the contents of the message are needed in the pipeline, a Java Callout action can be used to convert the message to or from XML. For information on using Java Callouts, see “Extensibility Using Java Callouts and POJOs” in the AquaLogic Service Bus User Guide.
Other cases where it is best not to use the Transport SDK to develop a custom transport provider include:
This section presents UML diagrams that depict the runtime and design-time components of a transport provider. This section includes these topics:
In general, a custom transport provider consists of a design-time part and a runtime part. The design-time part is concerned with registering endpoints with the transport provider. This configuration behavior is provided by the implementation of the UI interfaces. The runtime part implements the mechanism of sending and receiving messages.
When you develop a new custom transport provider, you need to implement a number of interfaces provided by the SDK. This section includes UML diagrams that model the organization of the design-time and runtime parts of the SDK.
Tip: | In AquaLogic Service Bus, implementations of the TransportProvider interface represent the central point for management of transport protocol-specific configuration and runtime properties. A single instance of a TransportProvider object exists for every supported protocol. For example, there are single instances of HTTP transport provider, JMS transport provider, and others. |
For more information, see Developing a Transport Provider for a list of the required interfaces. A summary of the interfaces and classes provided by the Transport SDK are discussed in Transport SDK Interfaces and Classes. Detailed descriptions are provided in Javadoc for AquaLogic Service Bus Classes.
The design-time part of a custom transport provider consists of the user interface configuration. This configuration is called by the AquaLogic Service Bus Console when a new business or proxy service is being registered. Figure 2-2 shows a UML diagram that depicts the structure of the design time part of a transport provider. Some of the interfaces described in the diagram include:
Note: | Each transport endpoint has a configuration that consists of some properties that are generic to all endpoints of any transport provider, such as a URI, and some properties that are specific to endpoints of that provider only. Figure 2-3 shows the relationship between the shared endpoint configuration properties and transport provider specific configuration properties. See Overview of Transport Endpoint Properties for more information. |
The runtime part of a custom transport provider:
In the runtime framework, the transport provider calls the transport manager to acknowledge that an inbound message has been received. The transport message context contains the header and body of the inbound message. For the outbound message, there is a TransportSendListener and TransportSender. The transport provider retrieves the header and body from the message.
Figure 2-2 shows a UML diagram that depicts the structure of the runtime part of a transport provider.
Before you develop a new transport provider using the Transport SDK, it is important to consider the transaction model for your message endpoints. This section discusses the transaction model used by AquaLogic Service Bus and how that model relates to the Transport SDK.
This section includes these topics:
A transport endpoint is an AquaLogic Service Bus resource, such as a JMS proxy service, where messages are originated or targeted. In AquaLogic Service Bus, transport endpoints are managed by protocol-specific transport providers, plug-in objects that manage the life cycle and runtime behavior of transport endpoints.
To understand the transactional model of AquaLogic Service Bus, it is useful to review some of the properties of service transport endpoints.
A given endpoint may or may not be transactional. A transactional endpoint has potential to start or enlist in a global transaction context when processing a message. The following examples illustrate how transactional properties vary depending on the endpoint:
For detailed information on specific proxy services, see the AquaLogic Service Bus User Guide.
A given endpoint can use one of the following message patterns:
The EJB and Tuxedo transports support synchronous transactions. Previously, the only transactional support in AquaLogic Service Bus was for the JMS transport, where transactions originated in and were bounded by the AquaLogic Service Bus domain. With the EJB and Tuxedo transports, transactions can originate outside of AquaLogic Service Bus and can pass through to external domains. Synchronous transactional transports support the following use cases:
Response pipeline processing is included in an incoming transaction when the inbound transport supports synchronous transactions. This case is supported when the inbound transport is paired with any other outbound transport, with the exception described in the note below.
Note: | A deadlock situation occurs when the inbound transport is synchronous transactional and the outbound transport is asynchronous transactional. The deadlock occurs because the outbound request is not available until after the transaction commits, but the transaction was started externally and does not commit until AquaLogic Service Bus gets the response and returns. The transport manager recognizes this situation and avoids the deadlock by throwing a runtime error. |
Note: | For example, if a synchronous transactional inbound endpoint is used, such as a Tuxedo proxy service, and the outbound endpoint is asynchronous transactional, such as a JMS proxy service, the outbound request does not commit the transaction until the response is received. It cannot be received until the external entity receives the request and processes it. |
Also in this case, the AquaLogic Service Bus Publish action performed in the response pipeline is part of the transaction just like publish actions in the request pipeline are part of the transaction.
Note: | There are several actions that can potentially participate in a transaction (in either the request or response pipeline). These include Publish, Service Callout, and Report actions. |
For example, if an inbound Tuxedo transport is synchronous transactional, it can be committed only after the request and response pipeline have been completed. In this case, the transport manager transfers the transaction context from the inbound to the outbound thread. When the response thread is finished, the transaction control and outcome are returned to the invoking client.
AquaLogic Service Bus Service Callouts allow you to make a callout from a proxy service to another service. If a Service Callout action is made to a synchronous transactional transport, the case of Exactly Once quality of service is supported in addition to Best Effort quality of service. Exactly Once means that messages are delivered from inbound to outbound exactly once, assuming a terminating error does not occur before the outbound message send is initiated. Best Effort means that each dispatch defines its own transactional context (if the transport is transactional). When Best Effort is specified, there is no reliable messaging and no elimination of duplicate messages; however, performance is optimized. See also Working with TransportOptions.
Callouts to synchronous transactional transports are optionally part of an existing transaction. For example, while the request pipeline is executing during a global transaction, Service Callouts are permitted to participate in the transaction. For example, if there is a callout to an EJB service, the service can participate in that transaction if it wants to.
For more information on Service Callouts, see “Service Callouts” in Using the AquaLogic Service Bus Console. For more information on message reliability, see the AquaLogic Service Bus User Guide.
Before calling the transport provider to send an outbound request the transport framework will suspend a transaction if the following conditions apply:
The suspended transaction will resume, after the “send” operation is complete.
If a given outbound service endpoint has multiple URIs associated with it, and is transactional, failover only occurs while the transaction, if any, is not marked for rollback. For example, if a URI is called, and the service returns an error, a failover is normally triggered. In this event, the transport framework detects that the transaction has been marked for rollback; therefore, the framework does not perform a failover to a different URI.
The Transport SDK allows customers and third-parties to plug in new transports into AquaLogic Service Bus. Within the AquaLogic Service Bus security model, transport providers are considered trusted code. It is critical that transport provider implementations are carefully designed to avoid potential security threats by creating security holes. Although this document does not contain specific guidelines on how to develop secure transport providers, this section discusses the following security goals of the Transport SDK:
Transport providers are free to implement whatever inbound authentication mechanisms are appropriate to that transport. For example: the HTTP transport provider supports these authentication methods:
The HTTPS transport provider supports SSL client authentication, in addition to the ones listed above. Both HTTP and HTTPS transport providers also support anonymous client requests.
The transport provider is responsible for implementing any applicable transport level authentication schemes, if any. If the transport provider authenticates the client it must make the client Subject object available to AquaLogic Service Bus by calling TransportManager.receiveMessage()
within the scope of weblogic.security.Security.runAs(subject)
. For information on this method, see http://download.oracle.com/docs/cd/E13222_01/wls/docs92/javadocs/weblogic/security/Security.html.
Tip: | For information on the Java class Subject, see http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/Subject.html. |
The proxy will use this Subject in the following ways:
If the transport provider does not support authentication, or if it supports anonymous requests, it must make sure the anonymous subject is on the thread before dispatching the request. Typically the transport provider will already be running as anonymous, but if this is not the case, then the provider must call:
Subject anonymous = SubjectUtils.getAnonymousUser()
Security.runAs(anonymous, action)
For information on SubjectUtils, see http://download.oracle.com/docs/cd/E13222_01/wls/docs92/javadocs/weblogic/security/SubjectUtils.html.
The transport provider is also responsible for providing any AquaLogic Service Bus Console configuration pages required to configure inbound client authentication.
The transport provider must clearly document its inbound authentication model.
Transport providers are free to implement whatever outbound authentication schemes are appropriate to that transport. The transport SDK includes APIs to facilitate outbound username/password authentication, (two-way) SSL client authentication, and JAAS Subject authentication.
Outbound username/password authentication can be implemented by leveraging AquaLogic Service Bus service accounts. Service accounts are first-class, top-level AquaLogic Service Bus resources. Service accounts are created and managed in the AquaLogic Service Bus Console. Transport providers are free to design their transport-specific configuration to include references to service accounts. That way the transport provider can make use of the credential management mechanisms provided by AquaLogic Service Bus service accounts.
Transport providers don't have to worry about the details of service account configuration. There are three types of service accounts:
An outbound endpoint can have a reference to a service account. The reference to the service account must be stored in the transport-specific endpoint configuration. When a proxy service routes a message to this outbound endpoint, the transport provider passes the service account reference to CredentialCallback.getUsernamePasswordCredential(ref)
. AquaLogic Service Bus returns the username/password according to the service account configuration. This has the advantage of separating identity propagation and credential mapping configuration from the transport-specific details, simplifying the transport SDK. It also allows sharing this configuration. Any number of endpoints can reference the same service account.
Note: | The CredentialCallback object is made available to the transport provider by calling TransportSender.getCredentialCallback() . |
CredentialCallback.getUsernamePasswordCredential()
returns a weblogic.security.UsernameAndPassword
instance. This is a simple class which has methods to get the username and password. The username/password returned depends on the type of service account. If the service account is of type static, the fixed username/password is returned. If it is mapped, the client subject is used to look up the remote username/password. If it is pass-through, the client’s username/password is returned.
Note: | A mapped service account throws CredentialNotFoundException if: |
Note: | In AquaLogic Service Bus 2.5, pass-through service accounts only work in two scenarios: |
Note: | Otherwise the pass-through service account throws CredentialNotFoundException. |
AquaLogic Service Bus also supports outbound SSL client authentication. In this case, the proxy making the outbound SSL request must be configured with a PKI key-pair for SSL. (This is done with a reference to a proxy service provider, the details are out of the scope of this document. For more information, see the AquaLogic Service Bus User Guide). To obtain the key-pair for SSL client authentication, the transport provider must call CredentialCallback.getKeyPair()
. The HTTPS transport provider is an example of this.
Some transport providers send a serialized JAAS Subject on the wire as an authentication token. To obtain the inbound subject the transport provider must call CredentialCallback.getSubject()
.
Note: | The return value may be the anonymous subject. |
Some transports require credentials to connect to services. For example, FTP endpoints may be required to authenticate to the FTP server. Transport providers can make use of static service accounts to retrieve a username/password for establishing the connection. Note that mapped or pass-through service accounts cannot be used in this case because these connections are not made on behalf of a particular client request. If a transport provider decides to follow this approach, the endpoint must be configured with a reference to a service account. At runtime, the provider must call TransportManagerHelper.getUsernamePassword()
, passing the reference to the static service account.
AquaLogic Service Bus enforces access control to proxy services for every inbound request. Transport providers are not required to enforce access control or to provide interfaces to manage the access control policy.
Note: | The access control policy covers the majority of the use cases; however, a transport provider can implement its own access control mechanisms (in addition to the access control check done by AquaLogic Service Bus) if required for transport provider specific reasons. If that is the case, please contact your BEA representative. In general BEA recommends transport providers let AquaLogic Service Bus handle access control. |
When access is denied, TransportManager.receiveMessage()
throws an AccessNotAllowedException wrapped inside a TransportException. Transport providers are responsible for checking the root-cause of the TransportException. A transport provider may do special error handling when the root cause is an AccessNotAllowedException. For example, the HTTP/S transport provider returns an HTTP 403 (forbidden) error code in this case.
Note: | AquaLogic Service Bus makes the request headers available to the authorization providers for making access control decisions. |
As explained in Outbound Request Authentication, AquaLogic Service Bus provides three types of service accounts. A transport provider can make use of service accounts to get access to the username/password for outbound authentication. A service account hides all of the details of identity propagation and credential mapping from AquaLogic Service Bus transport providers.
This section discusses the threading model used by AquaLogic Service Bus and how the model relates to the Transport SDK. This section includes these topics:
Figure 2-5 illustrates the AquaLogic Service Bus threading model for a hypothetical transport endpoint processing a single inbound message.
A front end artifact, such as a Servlet, is responsible for getting the inbound message. A request can be routed to an outbound endpoint and sent asynchronously. At this point, the thread is released. At some later point, a response is sent back to AquaLogic Service Bus (using a callback). The response is received, packaged, and handed to the AquaLogic Service Bus pipeline. Later, the pipeline notifies the inbound endpoint that the response is ready to be sent to the client. This processing is scalable because a thread is only tied up as long as it is needed.
The following actions occur in the same thread:
Note: | At this point, the initial request thread is released and placed back into the WebLogic Server thread pool for use by another request. |
The following actions occur in the same thread:
If the transport provider does not have a native implementation of an asynchronous (non-blocking) outbound call, it still needs to deliver the response back to AquaLogic Service Bus runtime on a separate thread than that on which the inbound request message was received. To do this, it can execute the call in a blocking fashion in the request thread and then use a Transport SDK helper method to deliver the response back to AquaLogic Service Bus runtime.
For example, the EJB transport provider does not have an asynchronous (non-blocking) outbound call. The underlying API is a blocking API. To work around this, the provider makes its blocking call, then schedules the response for processing with TransportManagerHelper.schedule()
. For more information on the EJB transport provider, see
“EJB Transport” in the AquaLogic Service Bus User Guide.
By design, the transport subsystem interacts asynchronously with AquaLogic Service Bus. The reason for this is that asynchronous behavior is more scalable, and therefore, more desirable than synchronous behavior. Rather than create two separate APIs, one for asynchronous and one for synchronous interaction, AquaLogic Service Bus runtime expects asynchronous interaction. It is up to the transport developer to work around this by a method such as posting a blocking call and posting the response in a callback. In any case, the response must be executed in a different thread from the request. See Table 2-2 for a list of AquaLogic Service Bus transport providers that support asynchronous outbound calls.
The threading diagram shown in Figure 2-5 focuses on routing. The transport subsystem behaves the same way for AquaLogic Service Bus Publish and Service Callout actions which can occur in the middle of the request or response pipeline processing. These actions occur outside the scope of the transport subsystem and in the scope of an AquaLogic Service Bus pipeline. Therefore, some differences exist between the threading behavior of Publish and Service Callout actions and transport providers.
Note, however, the following cases:
Tip: | A Service Callout action allows you to configure a synchronous (blocking) call to a proxy or business service that is already registered with AquaLogic Service Bus. Use a Publish action to identify a target service for a message and configure how the message is packaged and sent to that service. For more information on Service Callout and Publish actions, see the AquaLogic Service Bus Console online help and the AquaLogic Service Bus User Guide. |
This section includes these topics:
Transport providers have their own native representation of message content. For example, HTTP transport uses java.io.InputStream
, JMS has Message objects of various types, Tuxedo has buffers, and the WLS WebServices stack uses SAAJ. However, within the runtime of a proxy service, the native representation of content is the Message Context. While AquaLogic Service Bus supports some common conversion scenarios, such as InputStream to/from Message Context, this conversion between transport representation and the Message Context is ultimately the transport provider’s responsibility.
In general, the Transport SDK is not concerned with converting directly between two different transport representations of content. However, if two transports use compatible representations and the content does not require re-encoding, the SDK may allow the source content to be passed-through directly (for example, passing a FileInputStream from an inbound File transport to an outbound HTTP transport). However, if the source content requires any sort of processing, it makes more sense to unmarshall the source content into the Message Context first and then use the standard mechanisms to generate content for the outgoing transport.
Content is represented as an instance of the Source interface. Transport SDK interfaces that deal with message content, such as TransportSender and TransportMessageContext, all use the Source interface when passing message payloads. The requirements on a Source are minimal. A Source must support push- and pull-based conversions to byte-based streams using the two methods defined in the base Source interface. A Source may or may not take into account various transformation options, such as character-set encoding, during serialization, as specified by the TransformOptions parameter.
While all Source objects must implement the base serialization interface, the underlying representation of the Source object’s content is implementation specific. This allows for Source objects based on InputStreams, JMS Message objects, Strings, or whatever representation is most natural to a particular transport. Typically, Source implementations allow direct access to the underlying content, in addition to the base serialization methods. For example, StringSource, which internally uses a String object to store its content offers a getString()
method to get at the internal data. The ultimate consumer of a Source can then extract the underlying content by calling these source-specific APIs and potentially avoid any serialization overheads.
Sources may also be transformed into other types of Sources using a Transformer object. If a Source consumer, such as a transport provider, is given a Source instance that it does not recognize, it can often transform it into a Source instance that it does recognize. The underlying content can then be extracted from that known Source using the source-specific APIs. However, often a transport provider simply serializes the content and send it using the base serialization methods. See also Source and Transformer Classes and Interfaces.
Sources are the common content representation between the transport layer and the binding layer. The binding layer is the entity responsible for converting content between the Source representation used by the transport layer and the Message Context used by the pipeline runtime. How that conversion happens depends upon the type of service (its binding type) and the presence of attachments. While not strictly part of the Transport SDK, any transport provider that defines its own Source objects should be familiar with this conversion process.
When attachments are not present, the incoming Source represents just the core message content. The MessageContext is initialized by converting the received Source to a specific type of Source and then extracting the underlying content. For example, for XML-based services, the incoming Source is converted to an XmlObjectSource. The XmlObject is then extracted from the XmlObjectSource and used as the payload inside the $body
context variable. SOAP services are similarly converted to XmlObjectSource except that the extracted XmlObject must be a SOAP Envelope so that the <SOAP:Header>
and <SOAP:Body>
elements can be extracted to initialize the $header
and $body
context variables.
Below are the canonical Source types used for the set of defined service-types:
For binary services, no Source conversion is done. Instead, the Source is registered with an internal repository and the resulting <binary-content/>
XML is used as the payload inside $body
.
When attachments are present, the incoming Source is first converted to a MessageContextSource. From the MessageContextSource, two untyped Source objects are obtained, one representing the attachments and one representing the core message. The Source for the core message is handled as described previously. The Source representing attachments is converted internaly to XML and is used to initialize the $attachments
context variable and the internal repository containing the registered Sources that represent any binary attachment content. This entire process is illustrated in Figure 2-6.
A similar conversion occurs when creating a Source from data in the MessageContext to be passed to the transport layer. The core message is represented by a Source instance that can be converted to the canonical Source for the service type. In most cases, the Source will already be an instance of the canonical Source, but not always. When attachments are present, the Source delivered to the transport layer will be a source that can be converted to an instance of MessageContextSource. If the transport provider supports Content-Type as a pre-defined transport header, then the delivered Source will likely be an instance of MessageContextSource. Otherwise, the delivered Source will likely be an instance of MimeSource, but this can also be converted to a MessageContextSource.
The reason for this difference is that transports that natively support Content-Type as a transport header require that the top-level MIME headers appear in the transport headers rather than in the payload. Examples of this are HTTP and Email. Transports that do not natively support Content-Type must have these top-level MIME headers as part of the payload, as the Content-Type header is critical for decoding a multipart MIME package.
Below is a matrix showing the set of supported transformations offered by the built-in transformers. The column of Source names on the left indicates the initial Source type and the row of Source names on the top indicates the target Source type. An “X” in a given row R and column C means that it is possible to directly convert from initial Source R to target Source C. For example, there is some built-in transformer that handles converting a StringSource into an XmlObjectSource; however, there is no transformer that can convert a StringSource into an MessageContextSource. Typically, these transformers take advantage of their knowledge of the internal data representation used by both Source types.
Of special interest is the very first row of “X” values in the matrix, as it represents supported transformations from arbitrary Sources into specific Sources. For example, while there is no transformer that specifically handles converting an XmlObjectSource to a ByteArraySource, there is a transformer that will handle converting any instance of Source to a ByteArraySource. These generic transformations are done without any knowledge of the initial Source type but instead rely on the base serialization methods that are implemented by all Sources: getInputStream()
and writeTo()
. So, although it is ultimately possible to convert an XmlObjectSource to a ByteArraySource, it is not done using any special knowledge of the internal details of XmlObjectSource.
Note: | Many custom Sources implemented by Transports can be handled by these generic transformations, especially if the underlying data is an unstructured collection of bytes. For example, the File Transport uses a custom Source that pulls its content directly from a file on disk. However, as that data is just a set of bytes without structure, there is no need to provide custom transformations to, for example, XmlObjectSource. The generic transformation Source XmlObjectSource can handle this custom FileSource using just the base serialization methods that all Sources must implement. |
For more information, see Source and Transformer Classes and Interfaces.
![]() ![]() ![]() |