Nov 11, 2013

WLST Scripts to manage OSB configuration.

WebLogic uses the WLST build on Python and Jython for getting tasks programmatically standardized and, if necessary, automated.
Just as the MBeans in a standard WebLogic Domain, Oracle Service Bus uses its own MBeans on top of it. You can use this to request specific information about the configuration, resources such as proxy and business services. You also can export and import a certain configuration like you do in the Service Bus Console.
When you want to create a WLST script for some purpose, the following MBeans are the most important to start with:
  • SessionManagementBean: Used to create, save or discard a session, the same way as in the console. For doing this you can use the following methods:
createSession() 
- Creates the session ( can also be multiple )
activateSession()
- Commit your changes
discardSession()
- Rollback your changes before activate
sessionExists()
- Exit when actions are done or rollbacked.
These actions younormally do in the console using these buttons:
changecenter1
  • ALSBConfgurationMBean: For the import and export of OSB configurations, updating specific information such as endpoint URI’s, and investigate configurations and resources. With this MBean you can manage your OSB configuration, which, packaged in a JAR file, can be Proxy and BusinessServices, WSDL’s or other resources.
  • ServiceDomainMBean: This MBean finds any service enabled for monitoring, and get or reset statistics for services which are enabled for monitoring.

When you start WLST, standard WebLogic modules are loaded but specific OSB you should import in your script to use are:
from com.bea.wli.sb.management.configuration import ALSBConfigurationMBean
from com.bea.wli.monitoring import ServiceDomainMBean
to be found in com.bea.common.configfwk_1.5.0.0.jar, sb-kernel-api.jar and sb-kernel-impl.jar in your OSB library home.
Creating the session:
sessionManager = findService(SessionManagementMBean.NAME, SessionManagementMBean.TYPE)
sessionManager.createSession(sessionName)
Then do some stuff….
And save the session or discard when something went wrong:
# Activate the change session
print 'Activating my session...'
sessionManager.activateSession(sessionName, 'Doing stuff session activated')
except:
if sessionManager != None:
sessionManager.discardSession(sessionName)
raise
Use of resource references
For the identification of projects, folders and other resources you can use the Ref() class, and you will use it with the ALSBConfgurationMBean. You can create, delete or export projects and folders with the following methods:
    • createProject(Ref project, String Description)
    • createFolder(Ref folder, String Description)
    • delete() like a collection of references
    • importUploaded(ALSBImportPlan plan) to implement a customization plan
    • Customize(List customizations) - Change environment values with Customization plans, for changing different kind of Env Values, such as Assign, Find & Replace and Reference Mapping
    • ExportProjects(Collection Refs, String ….
Normally it’s done through this section in the sbconsole:
changecenter2
Below you see a snippet of how to import a Customization (with the customization stored in an XML file):

from com.bea.wli.sb.management.configuration import SessionManagementMBean
from com.bea.wli.sb.management.configuration import ALSBConfigurationMBean
from com.bea.wli.config import Ref ..
sessionName = createSessionName()
print 'Created session', sessionName
SessionMBean = getSessionMBean(sessionName)
print 'SessionMBean started session'
ALSBConfigurationMBean = findService(String("ALSBConfiguration.").concat(sessionName), "com.bea.wli.sb.management.configuration.ALSBConfigurationMBean")
print "ALSBConfiguration MBean found", ALSBConfigurationMBean
#customize if a customization file is specified
#affects only the created resources
if customFile != None :
print 'Loading customization File', customFile
iStream = FileInputStream(customFile)
customizationList = Customization.fromXML(iStream)
for customization in customizationList:
print '\n customization', customization.getDescription()
print customizationList.size()
ALSBConfigurationMBean.customize(customizationList)
print 'Customization applied'
SessionMBean.commitSession(sessionName)
print 'session committed'
except:
print "Unexpected error:", sys.exc_info()[0]
if SessionMBean != None:
SessionMBean.discardSession(sessionName)
raise
… and so on.

ServiceDomainMBean
Through this interface you can get loads of statistics of your services. Some of the methods to use are:
  • getMonitoredBusinessServiceRefs() and getMonitoredProxyServiceRefs for determining which services are enabled for monitoring
  • getBusinessServiceStatistics() and getProxyServiceStatistics() gives back runtime statistics collected. You can specify a server name, or get back cluster wide statistics from an aggregated view of statistics of all managed servers).
A short sample below:
stats = cmo.getProxyServiceStatistics([ref],ResourceType.SERVICE.value(),'')
for ps in stats[ref].getAllResourceStatistics():
for s in ps.getStatistics():
if s.getType() == StatisticType.COUNT:
print s.getName() + "("+ str(s.getType()) +"): " + str(s.getCount())
if s.getType() == StatisticType.INTERVAL:
print ( s.getName() + "("+ str(s.getType()) +"): " + str(s.getMin()) + " " + str(s.getMax()) + " " + str(s.getAverage()) + " " + str(s.getSum())
if s.getType() == StatisticType.STATUS:
print s.getName() + "("+ str(s.getType()) +"): " + str(s.getCurrentStatus()) + "(" + str(s.getInitialStatus()) + ")"



Oct 18, 2012

Getting Started - XQuery Dev inside OSB Eclipse

       We can use XQuery/XSL in OSB to do the message transformation. But XQuery is preferred over the XSL because of the  performance advantage. In this post I will show how to develop an xquery using the osb workshop eclipse.

XQuery - Introduction
       XQuery is a light weight language which has got an xml like syntax. XQuery has 3 important parts as below
  1. Namespace declaration
  2. Set of function with their implementations
  3. Declaration of variables
  4. Mentioning the function with which the execution begins.
          For further understanding of the XQuery you can refer
http://www.w3schools.com/xquery/xquery_intro.asp


Sample XQuery

Listing-1    xquery version "1.0" encoding "Cp1252";
Listing-2    (:: pragma  parameter="$anyType1" type="xs:anyType" ::)
Listing-3    (:: pragma  type="xs:anyType" ::)
Listing-4    declare namespace xf = "http://tempuri.org/OSB%20Project%203/sample/";
Listing-5    declare namespace ns1 = "http://tempuri.org/OSB%20Project%203/sample/inputaddress";
Listing-6    declare namespace ns2 = "http://tempuri.org/OSB%20Project%203/sample/outputaddress";
Listing-7
Listing-8    declare function xf:sample($requestDoc as element(*))
Listing-9                    as element(*)
Listing-10    {
Listing-11                
Listing-12                 
Listing-13                  {
Listing-14                  $requestDoc/ns1:FirstName/text()
Listing-15                  }
Listing-16                 

Listing-17                 
Listing-18                  {
Listing-19                  $requestDoc/ns1:PhoneNumber/text()
Listing-20                  }
Listing-21                 

Listing-22                

Listing-23    };
Listing-24
Listing-25    declare variable $requestDoc as element(*) external;
Listing-26
Listing-27    xf:sample($requestDoc)

Explanation
Listing 1 - declaration of xquery
Listing 2 to 3 - comments
Listing 4 to 6 - Namespace declarations
Listing 8 to 9
     This is the code snippet for the function 'sample' which takes 'requestDoc' which is of type element(*),             that is the xml. It returns the type element(*) which is also an xml.

Listing 10 - shows the start of the xquery function
Listing 23 - shows the end of the xquery function
Listing 11 to 22 - the body of the function 'sample'
 Here we are doing the transformation.  What ever we write it in these lines will be the final output of the 
 xquery tranformation
Listing 14 or 19 - Here we are assigning the data obtained from request xml to the output response xml.

Listing 25 - declaring the request variable 'requestDoc' as 'external' as type 'element(*)'. So when we test this xquery from the OSB flow, we will bind the request xml with 'requestDoc' variable and we can transform the request xml to the response xml. 

Listing 27 - This is the last line of the xquery where the execution of the xquery begins. Suppose if we have multiple functions, what ever function is given in the last line of xquery will be the entry point of execution.

Development of XQuery in OSB Workshop - Eclipse
          Open the eclipse and create a project . Right click on the project and create a new xquery


Give some name



Now give the request binding variables.
Here I have added only one variable.
Give the 'Parameter Name' as 'requestDoc'  and click on 'Add' so that we can add the request binding variable.



Similarly mention the response also



Now we have created the xquery. It will be now opened in the osb eclipse editor. The editor has 3 parts.
  1. Design
  2. Source
  3. Test
We can use 'Design' part if we have the source and destination schemas.


Now click on 'Source' and you can see the xquery source code.



Now modify the xquery as below

xquery version "1.0" encoding "Cp1252";
(:: pragma  parameter="$anyType1" type="xs:anyType" ::)
(:: pragma  type="xs:anyType" ::)
declare namespace xf = "http://tempuri.org/OSB%20Project%203/sample/";
declare namespace ns1 = "http://tempuri.org/OSB%20Project%203/sample/inputaddress";
declare namespace ns2 = "http://tempuri.org/OSB%20Project%203/sample/outputaddress";
declare function xf:sample($requestDoc as element(*))
    as element(*)
     {
       
         
          {
          $requestDoc/ns1:FirstName/text()
          }
         

         
          {
          $requestDoc/ns1:PhoneNumber/text()
          }
         
       
};
declare variable $requestDoc as element(*) external;
xf:sample($requestDoc)


Sample request xml for Testing


 Sarat

9985663814

Testing the application


Now Click on the 'Test' tab inside the xquery editor for testing





Now we have successfully created an xquery and tested it. 



 Testing the XQuery inside OSB Message Flow

      Create a new sample osb project. If you are a beginner you can refer the below post

 In the request flow drag one 'replace' node 

     Click on 'XPath' and enter the value as '*'

     In Variable : body
     Now click on 'Expresssion' and click on 'XQuery Resource' and browse to the sample xquery
     and enter $body/* into the 'requestDoc'.


Now you  can deploy the application and test it.



Conclusion
   This topic is intended to give an introduction to Xquery development and using the same inside the osb message flow. You can better explore more.

Oracle Service Bus (OSB) Performance Tuning tips

          Once you are comfortable with developing and deploying applications in OSB, the next thing that comes for you will be how fast you can run your applications and what are the standard procedures that need to be followed up in order to achieve that. 


          Based on my experience, I have come up with few points which will help you fine tune your applications and get good response times. The fine tuning of any application should start from the design phase. The design can be high level design, deployment design, low level design and finally the standard way of implementing these things.

High level design
  One should follow the most suitable and efficient design pattern in-order to achieve good result. Considering different solutions for the same problem will be handy.

Deployment design & Server Configuration
  OSB applications runs on Weblogic Server, a J2EE application server. So you should be very careful while selecting the JVM parameters like heap memory, gc algorithm, nursery size and other Java options. 
  Deep level analysis need to be done in order to understand whether the application that you are building is CPU intensive or memory intensive.

Low level design
  This is nothing but the proper work flow pattern design. You should analyse which work flow pattern will be more efficient in terms of number of threads it creates, the memory utilization and CPU utilization. Also how much of static data need to be handled and how it should be cached and so on.

Best practices for developing highly efficient OSB applications.

1. Cache the static data that need to be configured in your application. You need to consider the below points
    a. how much of data need to be cached
    b. Which caching api to use.
    
         There are two popular caching api's available - Java Caching System (JCS) and Oracle Coherence caching which Oracle recommends.

 Java Caching System (JCS)

       This is a simple caching scheme where the static data will be cached per server. This can be easily integrated to OSB application and the complexity is very less. But this is not suitable for caching very large amount of data. The caching mechanism may fail under heavy load and the cached data over 50 rows from a table.

Oracle Coherence Caching
       This is the Oracle recommended caching mechanism. We need to configure the coherence cluster in the Weblogic server level in order to use this. This is very robust and stable cache mechanism which can handle heavy load and large amount of data. The cached data will be available through out the cluster. There are different methods available for clearing the Coherence cache.

2. Disable all tracing
    For high end performance , you need to disable all kinds of tracing. This can be easily done in sbconsole.
  sbconsole -> smart search
  If you are using coherence caching, make sure that you enable caching for the business   service used for that.

3. Datasources
   If you are using datasouce for select or query operations, then use non-XA driver. 

4.  XQuery tuning

  a. Avoid using '//' anywhere in the xquery
  b. use indexes for faster xquery parsing.
  c. Use FLOWR expressions instead of 'if' conditions for checking the existence of any tag.
  d. If you want to use any intermediate xpath continuously , then assign that to a variable         
      and use it rather than querying it multiple times.
  e. Using indexes for xqueries, if you are not sure that it will return multiple rows
  f. If you use multiple 'let' statements, group it under one 'let'
  g. Avoid declaring the namespaces above xquery, it will lead to different namespace
     prefixes during runtime. Instead put it inline with xquery xml tags.
  h. Avoid using of '*' to the maximum extend
  i. Split large sized dbquery xmls to multiple parts so that xquery parsing will be easy.
        Design the dbentries in such a way that you would be easily able to split with  
        respect to some parameters.
  j. Reduce the number of parameters passing to the XQuery. Instead you can pass a single
      xml which will have all the parameters mapped


Xquery Performance testing guidelines

1. Test with huge payloads
2. Testing with values inside payload in different order (better reverse the order in the payload and test) 

Nov 8, 2011

RESTful Services with Oracle Service Bus

 Recently I was asked about REST (see http://en.wikipedia.org/wiki/Representational_State_Transfer)

support in Oracle Service Bus. OSB 10gR3 has full support for REST and
implementing a REST approach in a proxy service is very simple. In this
example, we will create a proxy service that provides a REST interface to a
product catalog.

Why use OSB for REST?

Using the Oracle Service Bus to provide an interface as
simple as REST may seem odd at first. There are several good reasons for this
approach though.
  1. You automatically get all of the monitoring, reporting, security and more provided
    by OSB for your RESTful services

  2. You keep the benefits of mediation. For example, of our company in this example
    purchased another company that provided different products, you could use the
    OSB to act as a façade over both product catalogs while providing a single,
    unchanged REST interface.

  3. You
    can REST-ify existing, non-service enabled assets like EJBs

The Products Proxy Service

Let's get started. First we will create a new OSB
Configuration Project to house our REST services. I named the configuration
project RESTConfig in the sample source code. You can download
the sample source code here.
Inside of the RESTConfig project I then
created a standard OSB project named SimpleREST. Once the OSB
project was created, I was ready to start creating my REST project.
Next I created a proxy service named Products.
I used the default endpoint URI of SimpleREST/Products but in a
production environment you'll most likely want to customize that. Be sure to
define your proxy service as an Any XML Service so you can accept
and return XML of any flavor.
Now it is time to create our message flow. Here is where
it gets interesting. One of the fundamental concepts in REST is the use of the
native HTTP methods to allow the service consumer to express their intent. The
specific HTTP methods that we are interested in are: GET, POST, PUT, HEAD,
OPTIONS and DELETE. In this example I don't make use of the TRACE method.
However, you will be able to add that to your projects easily after reading
this.
The handling of each of those methods is different, so we
begin our message flow with a Conditional Branch node (see figure 1). I added a
branch for each of the methods I was interested in. In the Conditional Branch
node I set the XPath field to ./ctx:transport/ctx:request/http:http-method/text()
and theIn Variable field to inbound. This is the equivalent to the XPath
expression $inbound/ctx:transport/ctx:request/http:http-method/text().
The text() operation at the end is important because I
want to deal with the method in its plain text form and not as an XML
expression.


image001.jpg

Figure 1 Standard OSB REST Pattern
When adding the branches it is important to enclose the
contents of the Value field in single quotes (Figure 2) to denote it is a
string value. If you forget this, you will get an error about an unbound XML
node when you run the proxy service because OSB will treat the contents of the
Value field as a variable instead of a string literal.
image002.jpg
Figure 2 Don't forget the quotes!
For each branch, add a pipeline pair and name it
appropriately, as shown in figure 1. Before we fill in the GET Pipeline with
the necessary logic, let's take a moment to decide how we want the HTTP GET method
to be handled. Ideally, we want to be able to point a web browser or other REST
service consumer to a URL like: http://localhost:7001/SimpleREST/Products/id=# to
retrieve a product representation by its ID. Since the proxy service is
listening at http://localhost:7001/SimpleREST/Products,
the remainder of the URL (i.e. the id=#) will be accessible in the message
flow as the relative-URI part of the $inbound variable.

The GET Method

Now that we know what the URL should look like for a GET,
we can fill in the logic. In the GET Pipeline (Figure 3) we will add two Assign
actions. The first Assign action will get the first part of the relative URL
(i.e. the id part). We won't do anything
with this part in this example, but you can use this technique to ensure that
the URL used had the correct format. The expression to use in the first Assign
statement is as follows:

fn:tokenize(data($inbound/ctx:transport/ctx:request/http:relative-URI),
'=')[1]
This expression will take the relative-URL value and
tokenize it using the '=' character, returning the first token. So if the
relative-URI is "id=27" this expression will return the "id" string. Why XPath
counts from 1 instead of 0 I don't know. Set the Variable field to attr and you are
done with the first Assign statement.
The second Assign statement is very similar to the first,
except we are retrieving the second part of the relative-URI. Its expression is
as follows:

fn:tokenize(data($inbound/ctx:transport/ctx:request/http:relative-URI),
'=')[2]
Set the Variable field to productID. In the sample code I include
a Log statement to output the contents of these variables to the console
image003.jpg
Figure 3 The GET Pipeline
In the Response Pipeline we will construct our response
message for the GET. We will just mock up a product document for this tutorial.
The following code snippet (which you will put into the Expression field
of the Replace action) shows the value that the Replace action will put into
the $body
variable, which is then returned to the caller.


{$productID}
Foobar
19.99
Listing 1 Constructing the response document
Set the XPath field to just a period (.) and be
sure to select the Replace Node Contents  radio button. If you deploy
the project you can test it using your web browser. Assuming your OSB server is
running on the default port 7001, you can use the following URL:
http://localhost:7001/SimpleREST/Products/id=2
Your web browser should show you the following:


2
Foobar
19.99
Note: Capitalization counts even with REST
Alternatively, you can use the OSB Test Console instead of
a web browser. I recommend using the Test Console (Figure 4) because it gives
you more control over the service call and visibility into the message flow. To
test the GET method, right-click on the Products.proxy file in the
Workshop IDE and select Debug As -> Debug on Server.... When the Test
Console appears, click on the down-arrow icon in the Transport section. This
will allow you to set the relative-URI and http-method fields directly.
image004.jpg
Figure 4 The Transport section of the Test Console
When you are happy with your settings, press the Execute
button to run the test. The Test Console (Figure 5) will return the results and
provide you with the response metadata and the invocation trace, which is
useful when debugging your proxy services.
image005.jpg
Figure 5 The Test Console response
Now that we have the GET branch taken care of. Let's take
a quick look at the other HTTP methods that we are supporting.

The POST Method

The HTTP POST method is traditionally used with REST to
create new entities. The message content that is POSTed can be in XML format, or
in the format used by HTML forms, which is still the most common mechanism for
submitting data to a web site in use today. However,, I highly recommend that
you keep your information in XML format instead of the HTML Form format simply
because the HTML Form only  supports the GET and POST verbs, whereas with REST
we also want to use the other verbs, like PUT and DELETE.
The POST Pipeline shows how to handle the POST method. It's
pretty simple in that it extracts the specific information it wants from the
$body and then creates and returns an XML representation, simulating the
creation of a product. You can use the OSB Test Console to test this method by
setting the http-method field to post and then typing in the payload as
follows:


Widget
99.99
The two Assign statements in the POST Pipeline simply
extract the name and price information and return a representation of the new
product, with a hard-coded ID of 777

The PUT Method

The PUT method is used to update an entity. It operates
very much like the POST method does, except this method will expect to see the
ID in the submitted product representation. You can test this operation in
pretty much the same way that you tested the POST, just change the http-method
to PUT and use the following as your payload:


999
Widget
99.99
Here we will add a little error checking to ensure that
the ID for the product has been specified. The If-Then action (Figure 6) uses
the expression: exists($body/Product/ID) to test
for the presence of the ID element.
image006.jpg
Figure 6 The PUT Pipeline
If the ID element is defined, we then use a single Assign
statement to create our entire response document as follows:


{$body/Product/ID/text()}
   {$body/Product/Name/text()}
   {$body/Product/Price/text()}
If the ID element is missing from the $body, then we throw
an error to alert the service consumer of the problem. In the response pipeline
we simply set $body
to the value of $responseDoc, what was created in our Assign statement.

The HEAD Method

The HEAD method is used to return metadata about a
representation to the caller. It's called the HEAD method because the metadata
is returned in the HTTP headers. This metadata can be anything you want it to
be, but a good place to start is the standard HTTP headers used by the
Inbound-Response to the Inbound-Request. Figure 6 shows the message flow for
HEAD Pipeline (Figure 7). All we do is populate the data of a single Transport
Header action in the response pipeline.
image007.jpg
Figure 7 Implementing the HEAD method
Its up to you and your specific needs to define which
headers you want to send back for the HEAD method, but I recommend sending at
least the HTTP Content-Type header with a value along the lines of 'text/xml; charset=utf-8'.
This will help the HTTP clients know how to parse the text that is returned.
Setting the Connection header to 'keep-alive' is also generally a good idea.

The OPTIONS Method

Finally, the OPTIONS method is used to convey to the
caller which HTTP methods are appropriate for the Products entity. In this
case, all we need to do is to specify a Transport Header for the outbound
response (see figure 8).
image008.jpg
Figure 8 Implementing the OPTIONS Pipeline
Configure the Transport Header as shown in figure 9.
image009.jpg
Figure 9 Transport Header Settings
The expression for the header is 'GET, HEAD, PUT, DELETE, OPTIONS'. It
may not be necessary to add the OPTIONS clause, since you have to call it in order to get
the response in the first place, but I show it for completeness. That covers
the basics of using OSB to implement RESTful service patterns. As you can see,
it's quick and simple to do. Using this technique you can wrap any
functionality in your enterprise using a REST service interface.

The DELETE Method

The DELETE method is very straight forward. It expects to
have a product ID specified on the URI and it simply deletes the product with
that ID. Due to its trivial nature, it is not implemented in the sample code.

Calling RESTful Services from OSB

In addition to providing a REST interface, OSB can also
invoke REST services. For this part of the exercise we will provide a standard
SOAP interface to OSB. OSB will then take those SOAP calls and invoke the REST
services accordingly. The WSDL for our SOAP interface defines the following
operations:

getProductDetail(productID)
createProduct(name)
updateProduct(productID)
deleteProduct(productID)
Each of these operations will be performed by the REST
services we created earlier in this tutorial.
We begin by creating a proxy service named CallREST based
on the Products.wsdl file (in the WSDL folder of the SimpleREST project). Since
the WSDL defines several SOAP operations, we start the message flow with an
Operational Branch node, and create branches for each of the operations we want
to handle. Once that is done, add a Pipeline Pair to the getProductDetail
branch, as show in Figure 10.
image010.jpg
Figure 10 The basic structure for the CallREST message flow
The getProduct Pipeline consists of a single Stage
node, as shown in Figure 11. The initial Assign statement is used to extract
the product ID from the request document and store it in the $productID
variable. The next node is a Service Callout
image011.jpg
Figure 11 The getProduct Pipeline stage
The Service Callout (Figure 12) is where most of the work
is done. To configure the Service Callout, be sure to check the Configure

Payload Document radio button since REST does not use a SOAP format. Set the Request
Variable field to requestBodyDocument

and the Response Variable field to responseBodyDocument. That's all you need to do for the Service Callout action.
image012.jpg
Figure 12 Service Callout contents
The first action is a Transport Header. Configuring this
action is simple. Set the Direction field to Outbound Request.
Also, be sure to check the Pass all Headers checkbox.
Immediately after the Transport Header action are two
Insert actions. The first insert action (Figure 13) is used to specify the HTTP
GET method. Configure it as shown in Figure 13 
image013.jpg
Figure 13 Specifying the HTTP GET method
The second and last Insert action (Figure 14) in the
request pipeline shows how to specify the relative-URI of the request. The expression:
id={$productID}
is used to create the value of the relative-URI of the outbound request
variable.
image014.jpg
Figure 14 Specifying the Relative-URI of the request
At this point our request of the REST service is properly
formatted. Once the REST service is invoked, the response will be returned to
our message flow in the responseBodyDocument
variable. In the Response Action pipeline of the service callout, we add a
single Replace action (see Figure 15) to take the response document from the
REST service and format it to meet the needs of our SOAP operation.
image015.jpg
Figure 15 Formatting the that our operation returns
The remaining branches follow a similar pattern so there
is no need to document them here. If you want to see the sample code for this
blog entry, you can download it from here:

Conclusion

As you can see from this sample, it is very easy to use
Oracle Service Bus to both call existing REST services, and to have OSB provide
a REST interface to existing SOAP services. The benefit of REST is the
simplicity of the interface design. By marrying OSB and REST, you get the
simplicity of REST, while maintaining the ability to define SLA's on each
service or operation, maintain visibility over these operations using OSBs
built in monitoring and reporting, and still retaining the necessary agility by
being able to quickly alter the OSB message flows and aggregating/orchestrating,
multiple services in the "backend" without the implicit knowledge of the
service consumer.