Additional SOA Patterns – Supporting Composition Controllers

In this article by Sergey Popov, author of the book Applied SOA Patterns on the Oracle Platform, we will learn some complex SOA patterns, realized on very interesting Oracle products: Coherence and Oracle Event Processing.

(For more resources related to this topic, see here.)

We have to admit that for SOA Suite developers and architects (especially from the old BPEL school), the Oracle Event Processing platform could be a bit outlandish. This could be the reason why some people oppose service-oriented and event-driven architecture, or see them as different architectural approaches. The situation is aggravated by the abundance of the acronyms flying around such as EDA EPN, EDN, CEP, and so on. Even here, we use EPN and EDN interchangeably, as Oracle calls it event processing, and generically, it is used in an event delivery network.


The main argument used for distinguishing SOA and EDN is that SOA relies on the application of a standardized contract principle, whereas EDN has to deal with all types of events. This is true, and we have mentioned this fact before. We also mentioned that we have to declare all the event parameters in the form of key-value pairs with their types in <event-type-repository>. We also mentioned that the reference to the event type from the event type repository is not mandatory for a standard EPN adapter, but it's essential when you are implementing a custom inbound adapter in the EPN framework, which is an extremely powerful Java-based feature. As long as it's Java, you can do practically everything! Just follow the programming flow explained in the Oracle documentation; see the EP Input Adapter Implementation section:


import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.bea.wlevs.ede.api.EventProperty;

import com.bea.wlevs.ede.api.EventRejectedException; import com.bea.wlevs.ede.api.EventType;


import com.bea.wlevs.ede.api.EventTypeRepository; import com.bea.wlevs.ede.api.RunnableBean;


import com.bea.wlevs.ede.api.StreamSender; import com.bea.wlevs.ede.api.StreamSink; import com.bea.wlevs.ede.api.StreamSource; import com.bea.wlevs.util.Service;


import java.lang.RuntimeException;


public class cargoBookingAdapter implements RunnableBean, StreamSource, StreamSink




static final Log v_logger = LogFactory. getLog("cargoBookingAdapter");


private String v_eventTypeName; private EventType v_eventType;

       private StreamSender v_eventSender;


private EventTypeRepository v_EvtRep = null; public cargoBookingAdapter(){








*  Called by the server to pass in the name of the event


*  v_EvTypee to which event data should be bound.




public void setEventType(String v_EvType){ v_eventTypeName = v_EvType;





*  Called by the server to set an event v_EvTypee


*  repository instance that knows about event


*  v_EvTypees configured for this application




*  This repository instance will be used to retrieve an


*  event v_EvTypee instance that will be populated


*  with event data retrieved from the event data file


*  @param etr The event repository.




@Service(filter = EventTypeRepository.SERVICE_FILTER)


public void setEventTypeRepository(EventTypeRepository etr){ v_EvtRep = etr;






*  Executes to retrieve raw event data and


*  create event v_EvTypee instances from it, then


*  sends the events to the next stage in the


*  EPN.


*  This method, implemented from the RunnableBean


*  interface, executes when this adapter instance


*  is active.




public void run()




if (v_EvtRep == null){


throw new RuntimeException("EventTypeRepository is


not set");




//  Get the event v_EvTypee from the repository by using


//  the event v_EvTypee name specified as a property of


//  this adapter in the EPN assembly file.


v_eventType = v_EvtRep.getEventType(v_eventTypeName); if (v_eventType == null){

throw new RuntimeException("EventType(" + v_eventType + ") is not found.");







*   Actual Adapters implementation:




*  1. Create an object and assign to it


*      an event v_EvTypee instance generated


*      from event data retrieved by the


*      reader




*  2. Send the newly created event v_EvTypee instance


*      to a downstream stage that is


*      listening to this adapter.










The presented code snippet demonstrates the injection of a dependency into the Adapter class using the setEventTypeRepository method, implanting the event type definition that is specified in the adapter's configuration.


So, it appears that we, in fact, have the data format and model declarations in an XML form for the event, and we put some effort into adapting the inbound flows to our underlying component. Thus, the Adapter Framework is essential in EDN, and dependency injection can be seen here as a form of dynamic Data Model/Format Transformation of the object's data. Going further, just following the SOA reusabilityprinciple, a single adapter can be used in multiple event-processing networks and for that, we can employ the Adapter Factory pattern discussed earlier (although it's not an official SOA pattern, remember?) For that, we will need the Adapter Factory class and the registration of this factory in the EPN assembly file with a dedicated provider name, which we will use further in applications, employing the instance of this adapter. You must follow the OSGi service registry rules if you want to specify additional service properties in the <osgi:service interface="com.bea.wlevs.ede.api.AdapterFactory"> section and register it only once as an OSGi service.


We also use Asynchronous Queuing and persistence storage to provide reliable delivery of events aggregation to event subscribers, as we demonstrated in the previous paragraph. Talking about aggregation on our CQL processors, we have practically unlimited possibilities to merge and correlate various event sources, such as streams:


<query id="cargoQ1"><![CDATA[


select * from CragoBookingStream, VoyPortCallStream


where CragoBookingStream.POL_CODE = VoyPortCallStream.PORT_CODE and VoyPortCallStream.PORT_CALL_PURPOSE ="LOAD"


Here, we employ Intermediate Routing (content-based routing) to scale and balance our event processors and also to achieve a desirable level of high availability. Combined together, all these basic SOA patterns are represented in the Event-Driven Network that has Event-Driven Messaging as one of its forms.


Simply put, the entire EDN has one main purpose: effective decoupling of event (message) providers and consumers (Loose Coupling principle) with reliable event identification and delivering capabilities. So, what is it really? It is a subset of the Enterprise Service Bus compound SOA pattern, and yes, it is a form of an extended Publish-Subscribe pattern.


Some may say that CQL processors (or bean processors) are not completely aligned with the classic ESB pattern. Well, you will not find OSB XQuery in the Canonical ESB patterns catalog either; it's just a tool that supports ESB VETRO operations in this matter. In ESB, we can also call Java Beans when it's necessary for message processing; for instance, doing complex sorts inJava Collections is far easier than in XML/XSLT, and it is worth the serialization/ deserialization efforts. In a similar way, EDN extends the classic ESB by providing the following functionalities:


        Continuous Query Language


        It operates on multiple streams of disparate data


        It joins the incoming data with persisted data


        It has the ability to plug in to any type of adapter


        It has the ability to plug to any type of adapters


Combined together, all these features can cover almost any range of practical challenges, and the logistics example we used here in this article is probably too insignificant for such a powerful event-driven platform; however, for a more insightful look at Oracle CEP, refer to Getting Started with Oracle Event Processing 11g, Alexandre Alves, Robin J. Smith, Lloyd Williams, Packt Publishing. Using exactly the same principles and patterns, you can employ the already existing tools in your arsenal. The world is apparentlybigger, and this tool can demonstrate all its strength in the following use cases:


      As already mentioned, Cablecom Enterprise strives to improve the overall customer experience (not only for VOD). It does so by gathering and aggregating information about user preferences through the purchasing history, watch lists, channel switching, activity in social networks, search history and used meta tags in search, other user experiences from the same target group, upcoming related public events (shows, performances, or premieres), and even the duration of the cursor's position over certain elements of corporate web portals. The task is complex and comprises many activities, including meta tag updates in metadata storage that depend on new findings for predicting trends and so on; however, here we can tolerate (to some extent) the events that aren't processed or are not received.


  •    For bank transaction monitoring, we do not have such a luxury. All online events must be accounted and processed with the maximum speed possible. If the last transaction with your credit card was at Bond Street in London, (ATM cash withdrawal) and 5 minutes later, the same card is used to purchase expensive jewellery online with a peculiar delivery address, then someone should flag the card with a possible fraud case and contact the card holder. This is the simplest example that we can provide. When it comes to money laundering tracking cases in our borderless world—the decision-parsing tree from the very first figure in this article—based on all possible correlated events will require all the pages of this book, and you will need a strong magnifying glass to read it; the stratagem of the web nodes and links would drive even the most worldly wise spider crazy.


For these mentioned use cases, Oracle EPN is simply compulsory with some spice, like Coherence for cache management and adequate hardware. It would be prudent to avoid implementing homebrewed solutions (without dozens of years of relevant experience), and following the SOA design patterns is essential.


Let's now assemble all that we discussed in the preceding paragraphs in one final figure. Installation routines will not give you any trouble; just install OEPE 3.5, download it, install CEP components for Eclipse, and you are done with the client/ dev environment. The installation of the server should not pose many difficulties either ( When the server is up and running, you can register it in Eclipse(1). The graphical interface will support you in assembling event-handling applications from adapters, processor channels, and event beans; however, knowledge of the internal organization of an XML config and application assembly files (as demonstrated in the earlier code snippets) is always beneficial.

In addition to the Eclipse development environment, you have the CEP server web console (visualizer) with almost identical functionalities, which gives you a quick hand with practically all CQL constructs (2).

Applied SOA Patterns on the Oracle Platform

Parallel Complex Events Processing

High service performance combined with High Availability


Extracting the highest possible performance in events processing or in any distributed computing systems for that matter can be achieved only if we can leverage data caching. A new layer called data grid as a distributed in-memory processing fabric must be established around most I/O and processor-consuming frameworks and service resources, primarily around ESB and databases. Regarding service resources and DB in particular, the clustering technique has been around for quite a long time; therefore, we doubt that your mission-critical DBs are not installed on RAC using SAN and so we will not dwell into it.


To serve HA and high-performance purposes, this fabric must satisfy certain criteria:


      Data Grid/fabric partitioning around a resource-consuming framework must be dynamic and automatic; that is, you should be able to add new servers into the cluster, automatically change the partition, and consequently, data replication and the processing workload.


      The amount of data distributed around every grid node must be configurable.


      The aggregate data throughput of the fabric is linearly proportional to the number of servers.


      The in-memory data capacity and data-indexing capacity of the fabric is linearly proportional to the number of servers.


    The aggregate I/O throughput for disk-based overflow and disk-based storage of data is linearly proportional to the number of servers.


      Partitioning must provide load balancing and a configurable level of data redundancy to maintain the required level of data resiliency (usually, zero tolerance to data losses).


      As every node should maintain data management (I/O processing) at the proportional level, the scalability rate must be close to the linear and directly proportional to the number of nodes in a data grid cluster.


      As a logical outcome from the preceding points, the more nodes in the grid, the more resilient the fabric would be.


     Another logical outcome is that the number of served clients (task submitters) is proportional to the number of nodes in the grid. Proportion must be linear, of course.


     Clients (task submitters) must see this fabric through a unified interface, completely decoupling the client from the fabric's size/complexity.


      The fabric load balancer must work well with other load balancers in the environment.


      To increase resilience, each grid node server must back up a configurable amount of data from other servers.


      Load balancing and workload distribution is an essential part of the fabric's architecture, and they should not represent SPOF either. Thus, hub-and-spoke or single message, or the workload broker pattern is not applicable here. All dispatchers must be redundant and interconnected to provide maximum resilience.


As you may have already noticed, all these characteristics are properties of the Oracle Coherence product, which is based on the distributed Java cache specification and is essential to implement the last two use cases.


If we look at the SOA patterns catalog again, we will probably find only one pattern related to the requirements of this distributed fabric: Service Grid. Generally, it is related to the replication of service state deferrals, that is, the BPEL dehydration DB, which is highly important to replicate the following:


        The MDS store


        The SOA infrastructure dehydration store


        Audit and process cubes


Although it's highly important, it's only a small part of what Coherence can provide; this SOA pattern is only the tip of the iceberg as we have lots of service components patterns that are employed for maintaining a declared list of Coherence characteristics. In a similar way, you can see the Observer pattern as the low-level architectural pattern, supporting EDN at the service component level. Here, we have several patterns that support data caching, serialization, replicating, and processing. Before touching on them, let's briefly look at the roots of Coherence.


At the very basic level, Coherence uses the idea of a HashMap (java.util) as probably the fastest way of storing, sorting, and retrieving data with two main functions around the data object: put(key,..) and get(key,value). So, as you can see,  once again we are dealing with key-value pairs that make the whole idea highly universal and suitable not only for EDN, but for all kinds of data implementation processes, for NoSQL in particular. We can combine multiple entry keys into logical storage units, so-called buckets.


Coherence takes this idea further by representing partitions that are stored on single or multiple cache servers. It also provides mechanisms for taking the key-value pairs of buckets/entry from the local cache and distributing them between the partitions. Thus, Coherence in general is a distributed implementation of java.util.hashmap.


How do we distribute objects? We had this technique long before SOA was developed (CORBA and RMI; look at the classic Java Distributed Computing, Jim Farley, O'Reilly Media), and this is the serialization we mentioned here a countlessnumber of times. Well, you can say that serialization is quite a heavy process, and actually, we have confirmed it many times as well. It is slow and serialized objects can be large; how can we optimize memory utilization, especially considering the problems associated with the already mentioned MapMessage interface?


In addition to classic serialization, Coherence provides two additional extensions for object distribution:


       The ExternalizableLite interface with two main methods, readExternal and writeExternal. It performs a bit of data compression to optimize memory  utilization.


•   The other is Portable Object Format (POF), which is a more advanced ExternalizableLite implementation.


 Of course, compression comes with a cost; it requires some more processing power, and the implementation is not always simple; however, it is worth all the effort:


       POF supports the ability to automatically apply indexes to the classes. This ability solves one-third of the generic distributed cache tasks which includes indexing, Partitioning, and replication.


      POF supports interoperability between multiple languages, that is, it's not just Java anymore; you can use C# and some other languages, including .NET and C++. That's a really big advantage of Coherence.


      What's even bigger about Coherence POF is that it allows you to version data. It is hard to overstress this feature. If data grid is the fabric, stretched around at least three products (OSB, SOA Suite, and Oracle EP) and three frameworks (EBS, EBF, and ABCS), then we expect it to run 24/7 and not jeopardize but support our new deployments. POF supports multiple versions of the same object in the memory, and most importantly, these versions will be used by the same service without data conflicts.

The last advantage is possible because of the key-value nature of HashMap. Imagine that Version 1 of App1 uses Object Version 1 with tree fields/properties and App1 Version 2 has the same Object with four fields. When Object Version 2 is serialized, it will be presented with all the fields; however, when it is deserialized for Version 1 of App1 to provide updates in the old application, the extra pieces of data (fields 4, 5, and so on), POF will create the extra bucket as a byte array for extra fields in V2 and squeeze them into it without reading/parsing and then add it to the stream. When the Object is serialized again, this portion will be added back to Object Version 2, so we will maintain consistent backward compatibility.


So now let's see how Coherence addresses two other main fabrics' tasks: Partitioning and Distribution. Coherence supports several Distribution models, and the most obvious one is direct replication (fast read / slow write), which is the first thing that comes to mind. We must remember that for data/object consistency, all our replications must be synchronous. If we have two grid nodes with two replicated data objects each (objects are different on single node, but nodes are identical; this is a complete replication), we have to synchronize each object between the two nodes every time the objects get updated. The problem with this method becomes obvious when we move to more nodes and more objects. Synchronous objects' synchronization soon will consume all our HW resources.


Well, actually lots of Distributed Caches (fast write / slow read) work on that model. With Coherence, we have better options: the Partitioned Cache. Let's not keep all the objects in one node, but partition it. If we have four data objects, then let's split them equally between two nodes (Obj1 and Obj2 on Node1, which is the primary for these objects and Obj3 and Obj4 on Node2 with the same rules). For resiliency backup, copies of objects 1 and 2 will be stored on Node2 and vice versa. They will be synchronized when the master object data is updated. Thus, we considerably reduced the number of synchronous replications in the Coherence fabric.


When Node1 goes down, Node2 will be promoted as the primary for all objects, which is basically the first model with a single node. The extreme implementation of this method would be one node per single primary and backup object. Coherence allows you to configure this replication model according to your realities; it is always a trade-off between performance, resilience, and cost. The good news is that Coherence takes care of proxy layers between task submitters and task processors, and data indexing and internal buckets' synchronization. Of course, Coherence is also responsible for promoting backup nodes to the primary when the master node(s) become unavailable.


So, we have a highly performing Replicated Cache and very scalable Partitioned Cache. We have the third model that is devised to combine the best sides of both: Coherence Near Cache and the fastest possible access to MRU and MFU data. In this approach, every node has a local cache store of limited size and a large backend store. Imagine that a submitter is working with Node2 and holding the master object Obj2; at a certain moment Obj3 will be required. Coherence will transport Obj3 from its master node (Node3, for instance) and put it into a smaller local cache (for example, MFU). If a service changes (invalidate) Obj3 at its main location, its updated replica will be propagated to the local cache of Node2. Thus, the local cache keeps a local snapshot of the distributed information. There are several cache invalidation strategies that are completely configurable:


      If your business can tolerate a proportion of the objects becoming temporarily out of date, then you can use the fastest strategy known as Listen None strategy, ideal for data with a slow rate of change.


      If your most recently used data is also the most frequently used one, that is, your application is only interested in the data stored in the local cache, then Listen Present is the best strategy.


      Listen All strategy is the heaviest, but it covers all the possible scenarios in backend caches.


     If you do not know which of the last two strategies is best for you, choose Listen Auto; it will dynamically switch between Listen Present and Listen All based on the cache's statistics.


As you can see, Coherence provides a lot of functionalities and is probably the most advanced distributed cache system in the market. Apparently, just one SOA pattern mentioned in the catalog must be supported by a number of underlying patterns, actually implement indexing, Partitioning, and replication in various forms, suitable for all possible user scenarios.


Luckily, Coherence is not only one of the most complex Oracle products, but it is also arguably the best documented one, thanks to the Coherence Incubator Project ( and to all who contributed to it, providing practical examples of various implementation patterns. We urge you to read and try the published materials. Here, we will just mention the basic patterns that are available for implementation, as the title of this book requires.

The following table includes Coherence Object Distribution patterns:




The Messaging pattern

We need an absolutely reliable SPOF and ultrafast sore-and-forward messaging network without a central hub (as in Hub-and -Spoke) as a potential bottleneck.

Coherence from the moment of its creation has been a message distribution system that is capable of supporting queues and topics.

The advantage of this pattern implementation is that in Coherence, you do not need to wrap objects into messages, that is, you can skip serialization operations; you use the same distributed infrastructure around your applications without establishing a new one.

Although the main purpose of Coherence is different than just being a distributed hubless SAF, some of us who experienced troubles with the original WLS will agree that SAF greatly appreciates this pattern implementation. Definitely, old JMSes and AQs can perform the same task cheaply in all ways; still, this pattern is the foundation of the next one.

One word of caution, which is common for all object distribution patterns: plan the distribution path carefully between your nodes and place the aggregation nodes close to the processing nodes for better throughput.

The Event Distribution pattern (EDN)

If you want something done fast, do it yourself and do it in cache. Only cache is a cache; if your service component can put the updated object into a distributed cache, then it would be the fastest way possible to propagate the event notification. Thus, the need for cache in events processing is justified.

Yes, Coherence is the cache we need and the change of objects' state will not go unnoticed with properly arranged invalidation strategy (if you do not know which one to use, go for Listen Auto). Remember the last figure from the previous paragraph? Coherence is the closest companion of Oracle Event Processing and can provide the following:

  •   Five types of channels for files, errors, and all types of caches, both local and distributed
  •   Guaranteed delivery of events. Lo events losses

This pattern sets the necessary infrastructure for the next pattern in line.

The Push Replication pattern

How to keep all the objects in all the Greed nodes synchronized in the most fastest and reliable way? How to propagate the changes from one cluster to another?

As the name suggests, data is pushed from the place where changes occurred to all the nodes that are configured to be notified. This is a bit more than a pattern; its an entire framework within Coherence that provides the following types of objects push:

  • active-passive
  •  active-active
  •  hub-and-spoke
  • multi-master
  • centralized replication

We touched upon some of these aspects while discussing the three possible distribution models and ways of data invalidation.

 The following table includes Coherence Object Processing patterns:




The Command pattern

An operation on a certain object that should be executed possibly several times (or none) must be represented as an executable object called Command in the context of the object's data. Command must clearly provide a method for executing the task.

This is a distributed version of the classic Command pattern, and the code presented in the incubator is quite self explanatory. The executable method provided by the Command interface simply called execute, which requires a single parameter: ExecutionEnvironment. This is where the context is encapsulated, and Context Manager is responsible for maintaining it.

To be distributable and replicable within the data grid, context and command objects must be serializable (ExternalizableLite or PortableObject would be even better)

This pattern does not always return a value back to the task submitter (client). If a return value is expected, the Functor pattern must be allied. This pattern is an extension of Command and should be omitted for brevity

Processing pattern

The previous pattern (Command) is responsible for creating an executable object based on the data object's context (as depicted in the 3D composite event matrix's figure, for instance), but this is just a prerequisite (although critical) for distributed computing. We must make sure that the client will see the fabric as one big computer with a unified way to submit, start, pause, and resume the predefined task with the associated data object. This processing framework must seamlessly support not only computers assembled into the Coherence grid, but also the ones that are plugged using Coherence Extend (TCP or JMS connectors to remote systems).

Coherence as a virtually unlimited distributed network of data storage buckets and associated data processing nodes represents the possibility of asynchronously processing (almost) everything that is called or run by Java. This pattern allows the client to use the fire-and-forget submission model for the predefined object (with the data structure declared in the key-value form and standard executable method). This pattern is capable of reporting back about task submission's outcome to keep the submitter informed about the progress of the execution. Based on the status (or even without it), the submitter has the ability of canceling the processing if submission doesn't reach the final stage of processing. Due to the asynchronous nature of the execution, the client has the ability to disconnect from the processing grid and connect later to collect the results or even delegate it to another client. The last option is possible because the client will decide on the ID that is associated to submission.

There are more patterns in the incubator (, including Coherence Commons (similar to Apache Commons) that holds lots of useful utilities. However, of all the patterns, the Processing pattern is arguably of paramount importance and is available for implementation on Coherence. This pattern is so full of functionalities and covers so many requirements that sometimes it is very rightfully called a framework. This pattern will require the following components:


        Submission dispatchers, polling the individual submission from local submission caches and registering them on Dispatch Controller, which in turn passes this registration to logging.


        A registered and logged task passed to the task dispatcher. The client is notified about the submission's outcome.


        The task dispatcher dispatches the task (executable submissions with the implementation of the Task interface) to the Task processor. Here, we can have different variations of the tasks. If a submission contains Java runnables and callables, it will be executed locally by LocalDispatcher, but this is


not desirable due to limited distribution capabilities. The task can also be resumable, which means that it can be suspended during the execution.


        TaskProcessor is the actual worker that executes the task. TaskProcessor is assigned according to TaskDispatchPolicies, which could be simple Round-robin or Attribute Matching. The last type is purely content-based routing/mediation.


        The submission's result is returned to the SubmissionResult cache.


Although very schematic, this sequence is quite complete to recognize the resemblance with patterns; please see thefigure with the block diagram forComposition Controller with Business Delegate and Service Locator. Exactly as with Service Broker / Business Delegate patterns, follow the ensuing steps:


  1. First of all, we decouple the consumer and actual worker.


  1. We use the dynamic execution capability (here in Java).


  1. We can postpone the execution until a certain event has occurred.


  1. We can route our object conditionally or unconditionally to the predefined TaskProcessor (Service) and we use an external policy for the Task-Process association.

Coherence empowers these patterns with the highest resiliency and top processing speed. Its distribution model is based on event mappings and notifications,


and it fully supports multithreading. All of this makes it a perfect companion for Oracle EPN.


Here, we would like to discuss two most common types of Coherence implementations, and we will traditionally start with the classic OSB and Coherence integration.


Coherence and OSB


In simpler cases, if our business service returns something close to static or if, as we mentioned above, our service consumer can tolerate the not really up-to-date result object, and if in addition to that (optionally), service operations are quite expensive, then we can configure our business service to cache results.



Cached results can be configured for time-to-live (TTL), so after the cache result expires, the next call will result in updating the cache with a fresh result by executing the business service. The cached result is stored on a separate Coherence JVM, so it does not take any resources from OSB JVM and can be distributed/partitioned between the Coherence nodes. Although these machines are completely separated, WebLogic Administration Server can still control Coherence servers on individual machines using its own node manager client, which is connected to individual node managers on each Coherence machine.

To establish this integration, you can follow the ensuing steps:


  1. Configure startup arguments in the server's Start tab as described in the OSB documentation (, and bestpractices at


  1. Now we have to configure the business service for caching in Coherence. Go to Advanced Properties in Message Handling configuration and check Supported for Result Caching. Also set expiration time at the bottom of thepage. If nothing special is part of your requirements, you can set it according to the default setting. You can also preset the fixed interval or establish something that is more business-oriented using the XPath expression, which is linked to expiration timestamps in your SBDH-compliant message header.


  1. As you remember, distributed cache is a partition of key-value pairs. So, we need to link the cached data to our object key, which could be a part of our Message Header, that is, $body/*:CTUMessage/*:MessageHeader/. Put your XPath expression in the Cache Token Expression field.


Using this configuration, you can considerably reduce the number of business service invocations and provide the output much faster.

 Coherence and event processing


Now, we will approach a more complex realization that is related to CEP. So, we can move the data object whenever and wherever we want to, and we can execute the methods, thanks to the Coherence Processing pattern. However, being essentially a distributed cache, Coherence is not really at its best when it comes to continuous aggregation, that is, accumulating and filtering data for an extended period of time. It will be quite right to call Coherence processing stateless, and that's logical as it will be quite dif ficult to replicate and partition stateful object/processing nodes. Yes, Coherence has EntityAggregators, which is built-in and customizable, but their main purpose is to reduce the number of entities in the cache, combining and aggregating the identical ones (by their attributes) in order to reduce the cache size and provide the result. Aggregators are constantly updating entities, but not in a time-based aggregation manner. Also, we must keep in mind the limited ways of accessing distributed cache, that is, we do not have adapters in the common sense; that's not the purpose of Coherence.


Event Processing at the same time is very good for time-based continuous aggregation of different streams; aggregations can be incrementally evaluated and grouped by values. We have quite an efficient adapter framework with abilities to implement custom adapters within adapter factories. The downside of the Oracle EDN is that we have no way to make our continuous aggregation parallel. Something that is going on in an isolated JVM for quite some time cannot be really replicated unless we perform the same operations exactly in another JVM. Operations are highly stateful. If we fail, we will have to start all over again, and all the previous results are wasted (if we are processing using CEP alone).


The natural approach here would be the combining benefits of both products in one form of MapReduce patterns (read and; these articles are really good),where roles will be distributed as follows:


  • Coherence (Map):
    • Entity aggregation using key affinity/no-entity duplicates Entity indexing
    • Maintaining the highest resilience through Partitioning and backup
    • Supporting partition transactions and preparing results for the final aggregation
    • A handy publishing mechanism
  • Oracle Event Processing (Reduce):
    • Continuous aggregation and grouping
    •  CQL provides great flexibility for adjustments and declarative modifications
    •  Coherence provides some sort of consistent entity views; therefore, if we fail, we can restart our analysis again without losing events

Surely, the presented implementation types (the second one is very schematic; please see the Oracle documentation for details on implementation, are not the only ones possible in OFM. Coherence can be highly beneficial for caching Oracle DB data (as any data). Coherence also provides a mechanism called CohQL to query the cache, SQL-style. In other words, we have plenty of means to implement the data grid in our SOA infrastructure around all the runtime frameworks with embedded tools for integration and data manipulation.



In this article, we have learned about complex SOA patterns, realized on very interesting Oracle products: Coherence and Oracle Event Processing. Combined in line with the SOA patterns and enhanced by the business monitoring tool (BAM), these products present a new Oracle approach in the event-driven architecture—fast data.

Resources for Article:

Further resources on this subject:

You've been reading an excerpt of:

Applied SOA Patterns on the Oracle Platform

Explore Title