Write for OTN
Earn money and promote your technical skills by writing a technical article for Oracle Technology Network.
Learn more
Stay Connected
OTN Architect Community
OTN ArchBeat Blog Facebook Twitter YouTube Podcast Icon

A Real-World Guide to Invoking OSB and EDN using C++ and Web Services

by Sebastian Lik-Keung Ma

A demonstration of extreme decoupling using OSB and EDN in Oracle SOA Suite 11g.

January 2014

Downloads
download-icon13-1Oracle SOA Suite
download-icon13-1Oracle JDeveloper

Introduction

In real-world organizations, software applications are written in diverse programming languages for disparate platforms (e.g., Java J2EE, C# .NET, C++, etc.). Service-Oriented Architecture (SOA) allows these applications to co-exist while progressively providing new services demanded by business changes.

This article demonstrates a complete, end-to-end, working example of how a C++ application can produce an event to the SOA infrastructure, and how a JDeveloper application can consume that event.

Sample Use Case

A fictitious manufacturing corporation, SM Corp., uses the HR outsourcing services of an external company, HR Contracts Private Limited. HR Contracts has been sending batch files of new contractors to SM Corp. daily. However, SM Corp. now needs more real-time information about these new contractors, who often arrive for work on the same day they are recruited by HR Contracts. Within SM Corp., there are many other applications that need to create records for these new contractors before they can start work, including the human resource system, the security access control system, and the medical insurance system.

Architecture

SM Corp. has Oracle SOA Suite in place. In addition to existing batch processing, real-time information should be published to interested subscribers. Further, both companies want minimum impact to existing systems and processes in terms of development, deployment and transaction handling. The architecture depicted in Figure 1, below, shows how this could be realized:

lik-keung-osb-edn-fig01
Figure 1: Extremely loose-coupling integration with OSB and EDN

The OSB provides enterprise-level decoupling in terms of security, physical location business terminology and data structure and communication protocol. Applications invoke proxy services; OSB would route these invocations to their configured business services.

Disparate applications run independently of each other. We do want an application's transaction to block or to fail when another application is faulted, degraded, or down. One-way calls, asynchronous web service calls, as well as message queues such as JMS (Java Messaging Service) and AQ (Advanced Queuing) are all options for providing asynchronous capabilities. Our architecture in Figure 1 uses EDN, a higher-level and more abstract way of publishing and subscribing to business events without getting into the lower-level connectivity details of JMS. Note that this also maps to an Event Driven Architecture (EDA).

The Event Producing part of the architecture is independent from the Event Consuming part. The modeled flow of control is as follows (referencing Figure 1):

Event Producing
  1. A custom application invokes web service that points to an OSB proxy service.
  2. The OSB proxy service routes the call to its business service.
  3. The business service invokes the web service published by a SOA composite application.
  4. The SOA composite application publishes a business event to EDN.

The flow ends here.

Event Consuming
  1. The EDN is signaled and receives the business event. It sends this event to a subscriber. an SOA composite application that listens to events of interest.
  2. The SOA composite application invokes a web service that points to an OSB proxy service.
  3. The OSB proxy service routes the call to its business service.
  4. The business service invokes the web service published by another custom application.

The flow ends here.

As you will soon see, web services, OSB and EDN form the core SOA enablers that make this extremely loose-coupling architecture possible. The end result is that the Event Producing part is completely independent from the Event Consuming part.

We will first explore the Event Producing part.

Event Producing

In this article, the three main players in the Event Producing part are:

  1. HelloPublisher: JDeveloper SOA composite application containing a Business Process Execution Language (BPEL) composite that publishes an event
  2. OSB: proxy service, business service and Web Service Definition Language (WSDL)
  3. HttpHelloOsbClient: Windows C++ console application that simulates an event-triggering application

HelloPublisher

When invoked via web service, this application will publish a NewEmployee event to EDN. Control will return immediately to the web service caller without blocking.

This SOA composite application contains just a BPEL composite with the following Event Definition (See Figure 2):

lik-keung-osb-edn-fig02
Figure 2: NewEmployeeEvent definition

The payload of NewEmployee event containing 3 strings: din, lastname and firstname (din refers to an employee ID).

lik-keung-osb-edn-fig03
Figure 3: NewEmployee event payload

The BPEL composite also exposes just a web service method called process (see Figure 4). It publishes NewEmployeeEvent when process method is invoked:

lik-keung-osb-edn-fig04
Figure 4: BPEL composite

Zooming into the BPEL, we have an Assign activity named Assign_ReceivedInput and an Invoke activity named Invoke1 (see Figure 5).

lik-keung-osb-edn-fig05
Figure 5: BPEL composite activities

The Assign_ReceiveInput activity contains only these simple mappings (see Figure 6):

  • The process method's input variables din, lastname and firstname are mapped to their similar NewEmployee event payload variables, respectively.
  • The process method's input variable din is mapped to its output variable (i.e., the method just returns the value of the input variable din).
lik-keung-osb-edn-fig06
Figure 6: Assign activity mappings

Invoke activity publishes NewEmployeeEvent (see Figure 7):

lik-keung-osb-edn-fig07
Figure 7: Invoke activity

In summary, HelloPublisher's web service method process simply publishes a NewEmployeeEvent and returns a string value immediately.

OSB - Proxy Service, Business Service and WSDL

To realize the benefits of SOA, it is best practice to provide access to a web service via an intermediary or a proxy. Consumers of these services are thus shielded from location and implementation changes of the actual web service.

Typically, we define the configuration for OSB as resources, using the OSB console, in this sequence: WSDL, business service and proxy service. An example result is shown in Figure 8:

lik-keung-osb-edn-fig08
Figure 8: OSB configuration

WSDL

The WSDL resource contains the location of the actual target application's web service. For example, the URL/Path to the HelloPublisher web service is:

http://<hostname>:<port>/soa-infra/services/default/HelloPublisher/bpelpublisher_client_ep?WSDL

The WSDL resource also imports XSD files that contain the types for HelloPublisher's event definitions.

lik-keung-osb-edn-fig09
Figure 9: WSDL

Business Service

The business service uses the WSDL resource we defined above. This binds to the actual web service method's Endpoint URI.

lik-keung-osb-edn-fig10
Figure 10: Business Service
lik-keung-osb-edn-fig11
Figure 11: Business Service uses WSDL's bindings

Proxy Service

Finally, the OSB proxy service would contain the routing to the business service resource we defined previously.

lik-keung-osb-edn-fig12
Figure 12: Proxy Service uses Business Service

HttpHelloOsbClient - C++ Invoking Web Service

HttpHelloOsbClient is a Windows C++ console application that knows and invokes only the proxy service provided by OSB. It triggers NewEmployEvent to be published.

This C++ program uses the lightweight native code Windows Web Services API (WWSAPI) to consume web services. Details on how to use WWSAPI can be found here:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd430435(v=vs.85).aspx

From an external application point of view, here are the steps to verify the URL path of the OSB Proxy web service:

  • Login to the OSB console: http://<hostnam>:<port>/sbconsole
  • Click Resource Browser on the left to see the available proxies you have deployed and their paths
  • If you click on one of the proxies, you will see your Endpoint URI (e.g., Endpoint URI /service/test/YourService)
  • Add ?WSDL to the end of your Endpoint URI to access the proxy WSDL (e.g., http://<hostname>:<port>/service/test/YourService?WSDL)

For example, if OSB is running on localhost with port 7001, the proxy service's WSDL is:

http://localhost:7001/HelloEDN/ProxyService/HelloEDNProxyService?WSDL

Figure 13 shows the C++ code segments that invoke the OSB proxy service:

lik-keung-osb-edn-fig13
Figure 13: InvokeOsbWebService(…) function

Tip: The code comments in Figure 14, below, contain hints to get WWSAPI working.

Figure 14 below shows internal code segments, with code comments.

#include <string>
#include <iostream> 
#include <sstream>
#include <WebServices.h>
#include "WsHelpers.h"
#include "HelloPublisherURL.wsdl.h" // produced by wsutil.exe 
#include "XMLSchema_-1547443801.xsd.h"
#include "XMLSchema_583194075.xsd.h"

using namespace std;

HRESULT InvokeOsbWebService(__in wstring url,
            __in wstring din, 
            __in wstring lastname,
         __in wstring firstname,
            __out wstring& result, 
            __in_opt WS_ERROR* error)
{
    HRESULT hr = S_OK;
    WsHeap heap;
    HR(heap.Create(2048, // max size
                   0, // trim size
                   0, // properties
                   0, // property count
                   error));   

    // Required settings for SOAP
    WS_CHANNEL_PROPERTY channelProperties[2];
    WS_ADDRESSING_VERSION addressingVersion = WS_ADDRESSING_VERSION_TRANSPORT;
    channelProperties[0].id = WS_CHANNEL_PROPERTY_ADDRESSING_VERSION;
    channelProperties[0].value = &addressingVersion;
    channelProperties[0].valueSize = sizeof(addressingVersion);

    WS_ENVELOPE_VERSION envelopeVersion = WS_ENVELOPE_VERSION_SOAP_1_1;
    channelProperties[1].id = WS_CHANNEL_PROPERTY_ENVELOPE_VERSION;
    channelProperties[1].value = &envelopeVersion;
    channelProperties[1].valueSize = sizeof(envelopeVersion);

    WsServiceProxy serviceProxy;
    HR(WsCreateServiceProxy(
    WS_CHANNEL_TYPE_REQUEST, 
    WS_HTTP_CHANNEL_BINDING, 
    NULL, 
    NULL, 
    0, 
    channelProperties, 
    WsCountOf(channelProperties), 
    &serviceProxy, 
    error));

    // C++ std::string... c_str() returns a readonly const pointer to a const object
    // We will not modify any string contents here, just get the first character and let 
    // WS_STRING retrieve the rest of the string value based on its length
    WS_STRING wsstrURL;
    wsstrURL.length = url.length();
    wsstrURL.chars = &url[0];

    WS_ENDPOINT_ADDRESS address = { wsstrURL };
    HR(serviceProxy.Open(&address,
                         0, // async context
                         error));

    // Initialize web service input and output args
    _NewEmployee employee;
    employee.din.length = din.length();
    employee.din.chars = &din[0];
    employee.firstname.length = firstname.length();
    employee.firstname.chars = &firstname[0];
    employee.lastname.length = lastname.length();
    employee.lastname.chars = &lastname[0];
    _processResponse* pResponse = NULL; // response will be allocated by callee

    // Invoke the web service call
    HR(BPELPublisherBinding_process(
       serviceProxy, 
       &employee, 
       &pResponse,
       heap, 
       NULL, 
       0,
       NULL, 
       error)); 

    // the response as result
    if (0 != pResponse && pResponse->result.length > 0)
    {
     result.assign(pResponse->result.chars, 0, pResponse->result.length);
    }

    HR(serviceProxy.Close(0, // async context
                          error));

    return S_OK;
}
Figure 14: InvokeOsbWebService(…) uses WWSAPI

Having published our business event to EDN, let's turn to Event Consuming.

Event Consuming

The main players of the Event Consuming part are:

  1. HelloSubscriber: JDeveloper SOA composite application containing a BPEL composite that subscribes to an event
  2. OSB: proxy service, business service and WSDL
  3. SampleHRApp: Oracle ADF (Application Development Framework) web application that simulates a custom HR application

HelloSubscriber

This SOA composite application listens to NewEmployeeEvent and invokes a proxy web service (Figure 15).

lik-keung-osb-edn-fig15
Figure 15: BPEL composite subscribing to event and invoking Proxy Service

To subscribe to NewEmployeeEvent, HelloSubscriber uses similar event definitions to those in HelloPublisher (see Figures 16 and 17).

lik-keung-osb-edn-fig16
Figure 16: NewEmployeeEvent definition

The payload for NewEmployee event:

lik-keung-osb-edn-fig17
Figure 17: NewEmployee event payload

More than one application can subscribe to NewEmployeeEvent. In our case, a custom Oracle ADF web application called SampleHRApp wants to receive NewEmployeeEvent notification so it can automatically create the new employee in its database if the employee record does not exist.

HelloSubscriber could, in fact, leverage ADF and consume SampleHRApp's ADF Service Data Object (SDO) directly. However, to stay consistent with best practices, HelloSubscriber would consume an OSB proxy service instead.

The steps for OSB ProxyService, BusinessService and WSDL are similar to the OSB section covered in the Event Producing section of this article.

For the sake of brevity, we have located (again, using steps similar to those described in the Event Producing section) the WSDL of the proxy service for SampleHRApp as:

http://localhost:7001/SampleHR/ProxyService/SampleHR?WSDL

On receiving NewEmployeeEvent, the BPEL would invoke the web service shown in Figure 18.

lik-keung-osb-edn-fig18
Figure 18: BPEL invoke OSB proxy service

Tip: It is important to leave Transaction Participation property to NEVER for now because we are not participating in any global transaction coordination (i.e., the target web service implementation will manage its own transaction).

HelloSubscriber BPEL contains just two activities: Assign activity and Invoke activity (Figure 19):

lik-keung-osb-edn-fig19
Figure 19: BPEL activities

The AssignToInvoke activity simply transfers input variables from the NewEmployeeEvent payload (din, lastname and firstname) to the respective output variables of the invoked web service method createEmployee (ignore the type mismatch between string and int for now; see Figures 20 and 21).

lik-keung-osb-edn-fig20
Figure 20: AssignToInvoke activity mappings
lik-keung-osb-edn-fig21
Figure 21: InvokeCreateEmployee activity calls web service method createEmployee

Conclusion

This article presents a working example of an end-to-end integration among disparate applications using SOA and EDA principles. The emphasis is on loose-coupling for development, deployment and run-time. Figure 22 shows the implementation overview, with concrete deployed modules (executables, jar files, etc.) highlighted in orange boxes.

lik-keung-osb-edn-fig22
Figure 22: Extremely loose-coupling integration with OSB and EDN - Implemented

An overview of the final result is illustrated in Figure 23. The custom C++ program HttpHelloOsbClient.exe called its internal method InvokeOsbWebService(…). This triggered a new employee event to be sent. The custom web application SampleHRApp managed to have the new employee record created automatically.

lik-keung-osb-edn-fig23
Figure 23: The Final Result

About the Author

Sebastian Lik-Keung Ma is a Software Applications Development Manager at Sembcorp Marine Limited. He has been a software development engineer and architect in Singapore and Germany for 20 years, specializing in C++, Java, and C#, providing distributed computing software applications. He earned his Master of Science degree from The University of Sheffield (UK).