Skip navigation
1 2 Previous Next

Developer Solutions

17 Posts authored by: Venkatesh Yadavalli-Oracle

Introduction

An application programming interface (API) is an interface to a service at an endpoint that provides controlled access to a business process or data. Businesses today are treating APIs as a primary product and are adopting the “API First” strategy for increased efficiency, revenue, partner contribution and customer engagement. These companies want to expose their core business values as APIs to partners to bring in more revenue but at the same time secure their core data and processes which enables faster service delivery with low cost.

 

APIs, Microservices and Cloud

Microservices is an architectural style that is increasingly being used for building cloud native applications, where each application is built as a set of services. These services communicate with one another through contractually agreed upon interfaces – APIs. It is an alternative architecture for building applications which provides a better way of decoupling components within an application boundary.

 

The number and granularity of APIs that a microservice-based application exposes demands for robust API management that involves creating, publishing APIs, monitoring the life cycle and enforcing usage policies in a secure and scalable environment.

 

Also, with more and more enterprises of all sizes leveraging cloud platforms to build innovative applications, effective API management in the cloud and/or on-premises is pivotal to meet their business and customer needs.

 

Oracle API Platform Cloud Service

Oracle’s API Platform Cloud Service (API platform CS) provides an integrated platform to build, expose and monitor APIs to backend services including capabilities like security enforcement, message routing, track usage…etc. This blog will introduce you to the various capabilities offered by Oracle API Platform Cloud Service with the help of a simple use case. The following diagram illustrates the architecture overview of Oracle’s API Platform CS.

 

apics_diagram.png

 

API Platform Cloud Service offers a centralized API design with distributed API runtime which makes it easy to manage, secure, and publicize services for application developers by offering innovative solutions.

There are several components in the Oracle API Platform Cloud Service - Cloud Service Console, the Gateway, the Management Portal, and the Developer Portal. Following is a short description of each of these components:

  • API Platform Cloud Service Console: Provision new service instances, start and stop service instances, initiate backups, and perform other life cycle management tasks.
  • Gateway: This is the security and access control runtime layer for APIs. Each API is deployed to a gateway node from the Management Portal or via the REST API.
  • Management Portal: This is used to create and manage APIs, deploy APIs to gateways, and manage gateways, and create and manage applications. You can also manage and Deploy APIs and manage gateways with the REST API.
  • Developer Portal: Application developers subscribe to APIs and get the necessary information to invoke them from this portal.

 

Personas of API life cycle

  • API Designer/API Product Manager - Collects customer requirements, documents the API and gets agreement with the consumer on the design of the API
  • API Manager/Implementer - Creates, tests, deploys, monitors and manages APIs, apply policies supporting the design and ensuring security
  • Gateway Manager - Deploys and configures gateway nodes, reviews and approves API deployment requests, monitors and manages the gateways
  • API Consumer - Application developer who consumes APIs to meet the requirements of an application. Searches the API catalog to identify existing APIs, registers desired APIs with application.

 

Sample Use case

In this blog we will build a simple API called Book Store that exposes functions of an online book store.  This blog emphasizes on the API implementation specific features of API Platform CS. To keep things simple we will mock one simple function – list books, which returns a list of books along with their titles, authors and expose it as an API. This blog does not discuss about all the features of Oracle API Platform Cloud Service. Please refer here for comprehensive documentation.

 

Note: The steps defined in the subsequent sections of this blog assume that you have access to an instance of Oracle API platform Cloud service with Gateway configurations and appropriate user grants to be able to implement and deploy APIs.

 
Create an API

In this section you create an entry for an API you want to manage in the API Platform CS Management Portal.

1) Sign in to the Management Portal as a user with the API Manager role

Management portal login page.png

2) Click on the “Create API” button to create a new API by providing name, version and description

Create API.png

3) The newly created Book Store API should be listed under the APIs page as shown below:

BookStore_API.png

Register Application to an API

API consumers register their applications to APIs they want to use. Application developers use the Developer Portal to register to APIs while API managers use Developer Portal and the Management Portal. In this section you register an application to the BookStore API.

 

1) From the APIs page, click the API you want to register an application to and Click on Registrations tab. Click on Register Application to register an application to this API.

Register_Application.png

2) The following Register Application page comes up listing all the existing applications from which you can choose or you can create a new application.

Register_Application_1.png

3) In this case, click on the Create an application link to create a new application and provide the details as in the below screenshot. Click Register button to register the Books App application with Book Store API

Register_Application_2.png

4) Once the application is registered with the API, it should be displayed under the “Registrations” tab as follows. Also notice that you can suspend this registration or de-register this application by clicking the respective buttons that appear when you hover on the application name. You can also approve or reject a developer’s request to register their application to an API from this page.

Register_Application_3.png

5) Each application that is registered is issued an App key which can be sent along the request to ensure that access to the API is granted only to the registered applications. Click on the Applications tab and click on the Books App application to view the application details along with the App key. You can also re-issue the App key by clicking on the Reissue key button.

Application_Key.png

Implement the API

Now that we have created an API and registered an application that can access the API, in this section we implement the API by applying policies to configure the request and response flows.

 

Click on the BookStore API to start implementing the API. The following page comes up with API Implementation activity highlighted.

API_Implementation.png

As a first step of API implementation, we configure the API endpoints. Endpoints are locations at which an API sends or receives requests or responses. APIs in API Platform CS have two endpoints in the request flow:

  1. API Request
  2. Service Request

 

Configure API Request URL

The API Request URL is the endpoint at which the gateway will receive requests from users or applications for your API

1) When you hover on to the API request section, you will see an “Edit” button using which you can configure the API request URL.

API_Request_URL_1.png

2) Click Next to configure the URL as follows. In the API Endpoint URL field, provide the endpoint URL for the Book Store API, apply and save the changes.

API_Request_URL_2.png

In this case we have specified /bookstore/books to be the relative URI. You can also choose the protocol to be HTTP or HTTPS or both.

 

Create a backend service

We need to create a backend service that would process the requests forwarded by the bookstore/books API. As mentioned earlier, we create a mock implementation of this service using Apiary. Oracle Apiary provides you with the ability to design APIs using either API Blueprint or Swagger 2.0. Please refer to http://apiary.io to learn more about Oracle Apiary, its features and to register for a free account.

 

Note: This task assumes that you have already registered with Apiary and have valid access credentials to login into Apiary.

 

1) Navigate to http://apiary.io  and Sign In using your account

apiary_login.png

2) Create a new API by clicking on Create New API project as follows, you can choose to design your API using API Blueprint or with Swagger. In this case we use API Blueprint, click on Create API button to create the Book Store API.

apiary_new_api.png

3) The API editor opens with a sample API definition which can be edited to define the API for /books as follows:

For the sake of simplicity, just replace the content in the left window with the following text. We have mocked the implementation of /bookstore/books service by providing two book entries.

 

FORMAT: 1A

HOST: http://bookstore.apiblueprint.org/

# BookStoreAPI

Bookstore is a simple API allowing consumers to view all the books along with their title and author.

## Books Collection [/bookstore/books]

### List All Books [GET]

+ Response 200 (application/json)

    {

        [

            {

                "Title": "Thus Spoke Zarathustra",

                "Author": "Friedrich Nietzsche"

            } ,

            {

                "Title": "The Fountainhead",

                "Author": "Ayan Rand"

            }

        ]

      }

 

4) When you click on Save button, you should see the right side window updated accordingly, based on the content you just provided.

apiary_bookstore_api.png

5) When you click on the List All Books link, you will see the following page with a mock server URL (https://private-2dd84-bookstoreapi.apiary-mock.com/bookstore/books , note that this URL would be different when you try to execute this example) for the /bookstore/books API service implementation

apiary_bookstore_api_1.png

6) Click on the Try button to invoke the mock service URL and validate the output. You will see a HTTP 200 response with the following output on the right side window. This confirms that the mock service URL is returning the book entries in response.

apiary_bookstore_api_2.png

 

Configure Service Request URL

The service request is the URL at which your backend service receives requests. The gateway routes the request to this URL when a request meets all policy conditions to invoke your service.

 

1) Click on the “Edit” button you see when you hover on the Service Request section on the API Implementation page

service_request_url.png

2) Enter the policy name and provide description and click on Next as shown below

service_request_url_2.png

3) In the Backend service URL input field, provide the mock server URL that was noted in step #5 in the above section as follows. Apply and Save the changes.

service_request_url_3.png

Apply Policies

You can apply policies to an API to secure, throttle, route, or log requests sent to it. Requests can be rejected depending on the policies applied, if they do not meet criteria specified for each policy.

 

1) The API Implementation page lists all the policies currently supported as follows, you can apply any policy by hovering onto the policy name and clicking on the Apply button.

Policy_list.png

 

Configuring all policies is beyond the scope of this blog, we apply couple of security and traffic management polices to the BookStore API to illustrate how to manage APIs by applying the policies. Please refer to Applying Policies section of API Platform CS documentation for more details.

 

Note: Policies in the request flow can be used to secure, throttle, route, manipulate, or log requests before they reach the backend service while polices in the response flow manipulate and log responses before they reach the requester.

 

2) Let us say we want to restrict the BookStore API to be consumed only by a specific application, a key validation policy can be applied on the request flow which ensures that requests from unregistered (anonymous) applications are rejected.

  • As discussed in Register Application to an API section above applications can be registered to an API and a unique App key is generated and assigned for each application.
  • These keys can be distributed to clients when they register to use an API on the Developer Portal.
  • At runtime, if this key is not present in the given header or query parameter, or if the application is not registered, the request is rejected.

To apply this policy, hover on the key validation policy under Security and click on Apply button. In the policy configuration page, give a name to the policy and you can specify the order in which this policy has to be triggered by selecting the policy from "Place after the following policy" drop down. Currently we have API Request policy that is already configured.

Key_validation_1.png

When you click the Next button you can specify the key delivery approach. The application key can be passed in header or as a query parameter. In this case we choose Header and specify the key name as “api-key”, click on Apply and save the changes. At runtime, the request is parsed for this key name and if found its value is validated against the registered application’s App key value. The request would be processed only if the values match else they would be rejected.

Key_validation_2.png

3) Let us apply another policy to restrict the number of requests our BookStore API can take within a specific time period. An API rate limiting policy can be used to limit the total number of requests an API allows over a time period that you specify, this time period can be defined in seconds, minutes, hours, days, weeks, or months.

 

To configure this policy, hover on the API Rate Limiting policy under Traffic Management and click on Apply button, in the resulting page provide a policy name and specify the order in which this policy should be triggered, in this case we want this policy to be triggered after the key validation policy.

API_Rate_Limiting_1.png

Click Next to configure the time period and the number of requests. We want the Gateway to reject requests for this API if they exceed 5 per minute.

API_Rate_Limiting_2.png

Note: Other traffic management related policies like API throttling can be implemented to delay request processing if they exceed the set threshold. Please refer to the API platform CS documentation for more details.

The API implementation should look like below after configuring the above policies:

API_Implementation_1.png

 

Deploy the API

In this section you will deploy the BookStore API to a gateway and activate the API. To deploy an endpoint, API Managers must have the Manage API or Deploy API grant for the API in addition to the Deploy to Gateway or Request Deployment to Gateway grant for a gateway.

 

Note:  This task assumes that the gateway nodes are configured and the user has the required grants to be able to deploy the API to the gateway. Please refer to Managing Gateways section for more details on configuring Gateways and their topology and Grants section for more details on granting users access to resources.

 

1) To deploy the API to the gateway, click on the Deployments icon just below the API Implementation.

deploy_api_1.png

2) Click on the Deploy API button, the resulting page lists all the gateways configured and allow you to choose a gateway onto which you want to deploy this API to. You can also choose the Initial deployment state of this API

deploy_api_2.png

Please note that the gateways can be configured anywhere - on oracle cloud , or third party cloud or on-premise.

 

3) When you click on the Deploy button, a request for API deployment is submitted and once the deployment is successful, the Deployments page would look as follows showing the Gateway Load Balancer URL which is your endpoint for sending the API requests.

deploy_api_3.png

 

Invoke the API

Now that you have successfully implemented your API and deployed the API to the gateway, you can send requests to the API and validate if the policies work as intended. 

You can use Postman or any other REST client to send requests to the API. In this case we use Postman to invoke the API.

 

Scenario # 1

Open Postman and initiate a GET request to the Load Balancer URL that has been shown on the Deployments page.

The request to the API fails with error – 401 (Unauthorized access), this is because the key validation policy got triggered and was looking for a header called “api-key”, which we have not set while submitting the request.

invoke_api_1.png

Scenario # 2

Add a request header with key as “api-key” and provide the App key of the registered BooksApp as value and submit the request. This will return a couple of book entries which we have mocked as part of the API service implementation in Apiary.

invoke_api_2.png

Scenario # 3

Submit 5 requests to this API within a minute time period; you will see the response from the API retrieving the book entries. When the request for the API is made for the 6th time within 1 minute, the API Rate limit policy that we have configured gets triggered and rejects the request as shown below:

invoke_api_3.png

The requests submitted after sometime (when the invocation rate comes to acceptable limit) are accepted and processed as usual again until any policy execution fails.

 

Once the API has been tested, you can publish this API to development portal from where developers can discover the API and register apps for consuming the APIs. Also API Platform Cloud Service Management Portal provides Analytics around who is using your API, how APIs are being used, and how many requests are rejected along with other metrics like request volumes…etc. Discussion on these aspects is beyond the scope of this blog.

 

Conclusion

This blog discussed about the concepts of API management and its importance in the context of Microservices and cloud native applications. It provides an overview of Oracle API Platform Cloud Service and briefly discussed about its key components. Using a simple use case we illustrated how APIs can be created, configured, deployed, consumed and monitored using Oracle API platform Cloud service. This blog is limited to discuss specific aspects of Oracle API platform CS, please refer to Oracle API platform CS documentation for further details.

 

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

This blog introduces you to building event-driven microservices application using CQRS and Event sourcing patterns. Following is a brief definition of the concepts that would be discussed during the course of this blog, more details about these can be obtained from the resources provided at the end of this blog.

 

What is a Microservice?

While there is no single definition for this architectural style, Adrian Cockcroft defines microservices architecture as a service-oriented architecture composed of loosely coupled elements that have bounded contexts.

 

What is a Bounded Context?

A Bounded Context is a concept that encapsulates the details of a single domain, such as domain model, data model, application services, etc., and defines the integration points with other bounded contexts/domains.

 

What is CQRS?

Command Query Responsibility Segregation (CQRS) is an architectural pattern that segregates the domain operations into two categories – Queries and Commands. While queries just return some results without making any state changes, commands are the operations which change the state of the domain model.

 

Why CQRS?

During the lifecycle of an application, it is common that the logical model becomes more complicated and structured that could impact the user experience, which must be independent of the core system.
In order to have a scalable and easy to maintain application we need to reduce the constraints between the read model and the write model. Some reasons for keeping reads and writes apart could be:

  • Scalability (read exceeds the write, so does the scaling requirements for each differs and can be addressed better)
  • Flexibility (separate read / write models)
  • Reduced Complexity (shifting complexity into separate concerns)

 

What is Event sourcing?

Event sourcing achieves atomicity by using a different, event-centric approach to persisting business entities. Instead of storing the current state of an entity, the application stores a sequence of ‘events’ that changed the entity’s state. The application can reconstruct an entity’s current state by replaying the events. Since saving an event is a single operation, it is inherently atomic and does not require 2PC (2-phase commit) which is typically associated with distributed transactions.

 
Overview

This blog explains how CQRS and Event Sourcing patterns can be applied to develop a simple microservice application that consists of a single bounded context called “Cart” with add, remove and read operations. The sample does not have any functional significance but should be good enough to understand the underlying patterns and their implementations.  The following diagram depicts a high level flow of activities when using CQRS and Event sourcing patterns to build applications:

 

cqrs-es_1.jpg

Figure 1 CQRS and Event sourcing

 

The sample referred in this blog uses the following technology stack:

  • Spring Boot for building and packaging the application
  • Axon framework with Spring for CQRS and Event Sourcing. Axon is an open source CQRS framework for Java which provides implementations of the most important building blocks, such as aggregates, repositories and event buses that help us build applications using CQRS and Event sourcing architectural patterns. It also allows you to provide your own implementation of the above mentioned building blocks.
  • Oracle Application Container cloud for application deployment

With this background, let us start building the sample.

 

Identify Aggregate Root

First step is to identify the bounded context and domain entities in the bounded context. This will help us define the Aggregate Root (for example, an ‘account’, an ‘order’…etc.). An aggregate is an entity or group of entities that is always kept in a consistent state. The aggregate root is the object on top of the aggregate tree that is responsible for maintaining this consistent state.

To keep things simple for this blog, we consider ‘Cart’ as the only Aggregate Root in the domain model. Just like the usual shopping cart, the items in the cart are adjusted based on the additions or removals happening on that cart.

 

Define Commands

This aggregate root has 2 commands associated with it:

  • Add to Cart Command – Modeled by AddToCartCommand class
  • Remove from Cart Command – Modeled by RemoveFromCartCommand class
publicclass AddToCartCommand {

    private final String cartId;
    private final int item;

    public AddToCartCommand(String cartId, int item) {
        this.cartId = cartId;
        this.item = item;
    }

    public String getCartId() {
        return cartId;
    }

    public int getItem() {
        return item;
    }
}

public class RemoveFromCartCommand {

 private final String cartId;
 private final int item;

 public RemoveFromCartCommand(String cartId, int item) {
      this.cartId = cartId;
      this.item = item;
 }

 public String getCartId() {
      return cartId;
 }

 public int getItem() {
      return item;
 }
  }

 

As you notice, these commands are just POJOs used to capture the intent of what needs to happen within a system along with the necessary information that is required. Axon Framework does not require commands to implement any interface nor extend any class.

 

Define Command Handlers

A command is intended to have only one handler, the following classes represent the handlers for Add to Cart and Remove from Cart commands:

 

@Component
public class AddToCartCommandHandler {

 private Repository repository;

 @Autowired
 public AddToCartCommandHandler(Repository repository) {
      this.repository = repository;
 }

 @CommandHandler
 public void handle(AddToCartCommand addToCartCommand){
      Cart cartToBeAdded = (Cart) repository.load(addToCartCommand.getCartId());
      cartToBeAdded.addCart(addToCartCommand.getItem());
 }

}

@Component
public class RemoveFromCartHandler {

 private Repository repository;

 @Autowired
 public RemoveFromCartHandler(Repository repository) {
      this.repository = repository;
    }

 @CommandHandler
 public void handle(RemoveFromCartCommand removeFromCartCommand){
      Cart cartToBeRemoved = (Cart) repository.load(removeFromCartCommand.getCartId());
      cartToBeRemoved.removeCart(removeFromCartCommand.getItem());

 }
}

 

We use Axon with Spring framework, so the Spring beans defined above have methods annotated with @CommandHandler which makes them as command handlers. @Component annotation ensures that these beans are scanned during application startup and any auto wired resources are injected into this bean. Instead of accessing the Aggregates directly, Repository which is a domain object in Axon framework abstracts retrieving and persisting of aggregates.

 

Application Startup

Following is the AppConfiguration class which is a Spring configuration class that gets initialized upon application deployment and creates the components required for implementing the patterns.

 

@Configuration
@AnnotationDriven
public class AppConfiguration {

 @Bean
 public DataSource dataSource() {
      return DataSourceBuilder
                .create()
                .username("sa")
                .password("")
                .url("jdbc:h2:mem:axonappdb")
                .driverClassName("org.h2.Driver")
                .build();
 }

 /**
 * Event store to store events
 */
 @Bean
 public EventStore jdbcEventStore() {
      return new JdbcEventStore(dataSource());
 }

 @Bean
 public SimpleCommandBus commandBus() {
      SimpleCommandBus simpleCommandBus = new SimpleCommandBus();
      return simpleCommandBus;
 }

 /**
 *  Cluster event handlers that listens to events thrown in the application.
 */
 @Bean
 public Cluster normalCluster() {
      SimpleCluster simpleCluster = new SimpleCluster("simpleCluster");
      return simpleCluster;
 }


 /**
 * This configuration registers event handlers with defined clusters
 */
 @Bean
 public ClusterSelector clusterSelector() {
      Map<String, Cluster> clusterMap = new HashMap<>();
      clusterMap.put("msacqrses.eventhandler", normalCluster());
      return new ClassNamePrefixClusterSelector(clusterMap);
 }

 /**
*The clustering event bus is needed to route events to event handlers in the clusters. 
 */
 @Bean
 public EventBus clusteringEventBus() {
     ClusteringEventBus clusteringEventBus = new ClusteringEventBus(clusterSelector(), terminal());

     return clusteringEventBus;
 }

 /**
 * Event Bus Terminal publishes domain events to the cluster
 *
 */
 @Bean
 public EventBusTerminal terminal() {
      return new EventBusTerminal() {
            @Override
            public void publish(EventMessage... events) {
                normalCluster().publish(events);
 }
            @Override
            public void onClusterCreated(Cluster cluster) {

            }
 };
 }

 /**
 * Command gateway through which all commands in the application are submitted
 *
 */

 @Bean
 public DefaultCommandGateway commandGateway() {
      return new DefaultCommandGateway(commandBus());
 }

 /**
* Event Repository that handles retrieving of entity from the stream of events.
 */
 @Bean
 public Repository<Cart> eventSourcingRepository() {
EventSourcingRepository eventSourcingRepository = new EventSourcingRepository(Cart.class, jdbcEventStore());
      eventSourcingRepository.setEventBus(clusteringEventBus());

     return eventSourcingRepository;
 }
}

 

Let us take a look at the key Axon provided infrastructure components that are initialized in this class:

 

Command bus

As represented in “Figure 1” above, command bus is the component that routes commands to their respective command handlers.  Axon Framework comes with different types of Command Bus out of the box that can be used to dispatch commands to command handlers. Please refer here for more details on Axon’s Command Bus implementations. In our example, we use SimpleCommandBus which is configured as a bean in Spring's application context.

 

Command Gateway

Command bus can directly send commands but it is usually recommended to use a command gateway. Using a command gateway allows developers to perform certain functionalities like intercepting commands, setting retry in failure scenarios…etc. In our example, we use Axon provided default which is DefaultCommandGateway that is configured as a Spring bean to send commands instead of directly using a command bus.

 

Event Bus

As depicted in “Figure 1”, the commands initiated on an Aggregate root are sent as events to the Event store where they get persisted. Event Bus is the infrastructure that routes events to event handlers. Event Bus may look similar to command bus from a message dispatching perspective but they vary fundamentally.

Command Bus works with commands that define what happen in the near future and there is only one command handler that interprets the command. However in case of Event Bus, it routes events and events define actions that happened in the past with zero or more event handlers for an event.

Axon defines multiple implementations of Event Bus, in our example we use ClusteringEventBus which is again wired up as a Spring bean. Please refer here for more details on Axon’s Event Bus implementations.

 

Event Store

We need to configure an event store as our repository will store domain events instead of the current state of our domain objects. Axon framework allows storing the events using multiple persistent mechanisms like JDBC, JPA, file system etc. In this example we use a JDBC event store.

 

Event Sourcing Repository

In our example, the aggregate root is not created from a representation in a persistent mechanism, instead is created from stream of events which is achieved through an Event sourcing repository. We configure the repository with the event bus that we defined earlier since it will be publishing the domain events.

 

Database

We use in memory database (h2) in our example as the data store. The Spring Boot’s application.properties contains the data source configuration settings:

# Datasource configuration
spring.datasource.url=jdbc:h2:mem:axonappdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.validation-query=SELECT 1;
spring.datasource.initial-size=2
spring.datasource.sql-script-encoding=UTF-8

spring.jpa.database=h2
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create

 

As mentioned above, this example uses a JDBC event store to store the domain events generated in the system. These events are stored in a default tables (part of Axon framework event infrastructure) specified by the Axon framework. We use the following startup class for creating the database tables required by this example:

 

@Component
public class Datastore {

 @Autowired
 @Qualifier("transactionManager")
 protected PlatformTransactionManager txManager;

 @Autowired
 private Repository repository;

 @Autowired
 private javax.sql.DataSource dataSource;
    // create two cart entries in the repository used for command processing 
 @PostConstruct
 private void init(){

 TransactionTemplate transactionTmp = new TransactionTemplate(txManager);
 transactionTmp.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                UnitOfWork uow = DefaultUnitOfWork.startAndGet();
                repository.add(new Cart("cart1"));
                repository.add(new Cart("cart2"));
                uow.commit();
            }
 });

 // create a database table for querying and add two cart entries
 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
 jdbcTemplate.execute("create table cartview (cartid VARCHAR , items NUMBER )");
 jdbcTemplate.update("insert into cartview (cartid, items) values (?, ?)", new Object[]{"cart1", 0});
 jdbcTemplate.update("insert into cartview (cartid, items) values (?, ?)", new Object[]{"cart2", 0});
 }

 

This startup class creates two cart entries in the repository used for command processing and creates a database table called “cartview” which is used for processing the queries.

 

A quick recap on what we did so far:

  • We have identified “Cart” as our Aggregate root and have defined commands and command handlers for adding and removing items from the Cart.
  • We have defined a startup class which initializes the infrastructure components required for CQRS and Event sourcing.
  • A startup class has also been defined to create the database tables and setup the data required by this sample.

 

Let us now look at our AggregateRoot - “Cart” which is defined as below:

 

Aggregate Root

 

publicclass Cart extends AbstractAnnotatedAggregateRoot {
 @AggregateIdentifier
 private String cartid;

 private int items;

 public Cart() {
 }

 public Cart(String cartId) {
      apply(new CartCreatedEvent(cartId));
 }

 @EventSourcingHandler
 public void applyCartCreation(CartCreatedEvent event) {
      this.cartid = event.getCartId();
      this.items = 0;
 }

 public void removeCart(int removeitem) {

 /**
* State is not directly changed, we instead apply event that specifies what happened. Events applied are stored.
*/
 if(this.items > removeitem && removeitem > 0)
      apply(new RemoveFromCartEvent(this.cartid, removeitem, this.items));

 }

  
   
 @EventSourcingHandler
 private void applyCartRemove(RemoveFromCartEvent event) {
 /**
* When events stored in the event store are applied on an Entity this method is 
* called. Once all the events in the event store are applied, it will bring the Cart * to the most recent state.
*/

      this.items -= event.getItemsRemoved();
 }

 public void addCart(int item) {
 /**
* State is not directly changed, we instead apply event that specifies what happened. Events applied are stored.
*/
 if(item > 0)    
      apply(new AddToCartEvent(this.cartid, item, this.items));
 }

 @EventSourcingHandler
 private void applyCartAdd(AddToCartEvent event) {
 /**
* When events stored in the event store are applied on an Entity this method is 
* called. Once all the events in the event store are applied, it will bring the 
* Cart to the most recent state.
*/

      this.items += event.getItemAdded();
 }

 public int getItems() {
      return items;
 }

 public void setIdentifier(String id) {
      this.cartid = id;
 }

 @Override
 public Object getIdentifier() {
      return cartid;
 }
}

 

Following are some key aspects of the above Aggregate Root definition:

  1. The @AggregateIdentifier is similar to @Id in JPA which marks the field that represents the entity’s identity.
  2. Domain driven design recommends domain entities to contain relevant business logic, hence the business methods in the above definition. Please refer to the “References” section for more details.
  3. When a command gets triggered, the domain object is retrieved from the repository and the respective method (say addCart) is invoked on that domain object (in this case “Cart”).
    1. The domain object instead of changing the state directly, applies the appropriate event.
    2. The event is stored in the event store and the respective handler gets triggered which makes the change to the domain object.
  4. Note that the “Cart” aggregate root is only used for updates (i.e. state change via commands). All the query requests are handled by a different database entity (will be discussed in coming sections).

 

Let us also look at the events and the event handlers that manage the domain events triggered from “Cart” entity:

 

Events

 

As mentioned in the previous sections, there are two commands that get triggered on the “Cart” entity – Add to Cart and Remove from Cart. These commands when executed on the Aggregate root will generate two events – AddToCartEvent and RemoveFromCartEvent which are listed below:

 

publicclass AddToCartEvent {

 private final String cartId;
 private final int itemAdded;
 private final int items;
 private final long timeStamp;

 public AddToCartEvent(String cartId, int itemAdded, int items) {
      this.cartId = cartId;
      this.itemAdded = itemAdded;
      this.items = items;
      ZoneId zoneId = ZoneId.systemDefault();
      this.timeStamp = LocalDateTime.now().atZone(zoneId).toEpochSecond();
 }

 public String getCartId() {
      return cartId;
 }

 public int getItemAdded() {
      return itemAdded;
 }

 public int getItems() {
      return items;
 }

 public long getTimeStamp() {
      return timeStamp;
 }
}

public class RemoveFromCartEvent {
 private final String cartId;
 private final int itemsRemoved;
 private final int items;
 private final long timeStamp;

 public RemoveFromCartEvent(String cartId, int itemsRemoved, int items) {
      this.cartId = cartId;
      this.itemsRemoved = itemsRemoved;
      this.items = items;
      ZoneId zoneId = ZoneId.systemDefault();
      this.timeStamp = LocalDateTime.now().atZone(zoneId).toEpochSecond();

 }

 public String getCartId() {
      return cartId;
 }

 public int getItemsRemoved() {
      return itemsRemoved;
 }

 public int getItems() {
      return items;
 }

 public long getTimeStamp() {
      return timeStamp;
 }
}

 

Event Handlers

 

The events described above would be handled by the following event handlers:

 

@Component
public class AddToCartEventHandler {

 @Autowired
 DataSource dataSource;

 @EventHandler
 public void handleAddToCartEvent(AddToCartEvent event, Message msg) {
      JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

      // Get current state from event
      String cartId = event.getCartId();
      int items = event.getItems();
      int itemToBeAdded = event.getItemAdded();
      int newItems = items + itemToBeAdded;


      //  Update cartview
      String updateQuery = "UPDATE cartview SET items = ? WHERE cartid = ?";
      jdbcTemplate.update(updateQuery, new Object[]{newItems, cartId});

 }
@Component
public class RemoveFromCartEventHandler {

 @Autowired
 DataSource dataSource;

 @EventHandler
 public void handleRemoveFromCartEvent(RemoveFromCartEvent event) {

      JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

      // Get current state from event
      String cartId = event.getCartId();
      int items = event.getItems();
      int itemsToBeRemoved = event.getItemsRemoved();
      int newItems = items - itemsToBeRemoved;

      // Update cartview
      String update = "UPDATE cartview SET items = ? WHERE cartid = ?";
      jdbcTemplate.update(update, new Object[]{newItems, cartId});

 }
}

 

As you notice, the event handlers update the “cartview” database table which is used for querying the “Cart” entity. While the commands get executed on one domain, the query requests are serviced by a different domain there by achieving CQRS with Event sourcing.

 

Controllers

 

This example defines 2 Spring controller classes one each for updating and querying the Cart domain. These are REST endpoints that could be invoked from a browser as below:

 

http://<host>:<port>/add/cart/<noOfItems>

http://<host>:<port>/remove/cart/<noOfItems>

http://<host>:<port>/view

 

@RestController
public class CommandController {

 @Autowired
 private CommandGateway commandGateway;

 @RequestMapping("/remove/{cartId}/{item}")
 @Transactional
 public ResponseEntity doRemove(@PathVariable String cartId, @PathVariable int item) {
       RemoveFromCartCommand removeCartCommand = new RemoveFromCartCommand(cartId, item);
      commandGateway.send(removeCartCommand);

      return new ResponseEntity<>("Remove event generated. Status: "+ HttpStatus.OK, HttpStatus.OK);
 }

 @RequestMapping("/add/{cartId}/{item}")
 @Transactional
 public ResponseEntity doAdd(@PathVariable String cartId, @PathVariable int item) {

      AddToCartCommand addCartCommand = new AddToCartCommand(cartId, item);
      commandGateway.send(addCartCommand);

     return new ResponseEntity<>("Add event generated. Status: "+ HttpStatus.OK, HttpStatus.OK);
 }


}

@RestController
public class ViewController {

 @Autowired
 private DataSource dataSource;

@RequestMapping(value = "/view", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
 public ResponseEntity getItems() {

      JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
      List<Map<String, Integer>> queryResult = jdbcTemplate.query("SELECT * from cartview ORDER BY cartid", (rs, rowNum) -> {

      return new HashMap<String, Integer>() {{
                put(rs.getString("CARTID"), rs.getInt("ITEMS"));
            }};
 });

      if (queryResult.size() > 0) {
        return new ResponseEntity<>(queryResult, HttpStatus.OK);
      } else {
        return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
      }

 }

}

 
Deployment

 

We use Spring Boot to package and deploy the application as a runnable jar into Oracle Application Container cloud. The following Spring Boot class initializes the application:

 

@SpringBootApplication

public class AxonApp {

 // Get PORT and HOST from Environment or set default
 public static final Optional<String> host;
 public static final Optional<String> port;
 public static final Properties myProps = new Properties();

 static {
      host = Optional.ofNullable(System.getenv("HOSTNAME"));
      port = Optional.ofNullable(System.getenv("PORT"));
 }

 public static void main(String[] args) {
      // Set properties
      myProps.setProperty("server.address", host.orElse("localhost"));
      myProps.setProperty("server.port", port.orElse("8128"));

      SpringApplication app = new SpringApplication(AxonApp.class);
      app.setDefaultProperties(myProps);
      app.run(args);

 }
}

Create an xml file with the following content and place it in the same directory as the pom.xml. This specifies the deployment assembly of the application being deployed to Oracle Application Container Cloud.

 

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
 <id>dist</id>
 <formats>
 <format>zip</format>
 </formats>
 <includeBaseDirectory>false</includeBaseDirectory>
 <files>
 <file>
            <source>manifest.json</source>
            <outputDirectory></outputDirectory>
 </file>
 </files>
 <fileSets>
 <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory></outputDirectory>
            <includes>
                <include>${project.artifactId}-${project.version}.jar</include>
            </includes>
 </fileSet>
 </fileSets>
</assembly>

 

To let Application Container cloud know the jar to run once the application is deployed, you need to create a “manifest.json” file specifying the jar name as shown below:

{
 "runtime": {
 "majorVersion": "8"
    },
 "command": "java -jar AxonApp-0.0.1-SNAPSHOT.jar",
 "release": {},
 "notes": "Axon Spring Boot App"
}

 

The following diagram depicts the project structure of this sample:

prjstructure.png

Figure 2 Project Structure

 

The application jar file along with the above manifest file should be archived to zip and uploaded into Application Container cloud for deployment. Please refer here for more details on deploying Spring Boot Application in Application Container cloud.

 

Once the application is successfully deployed, you would be able to access the following URLs to trigger the services on the Cart:

http://<host>:<port>/view

http://<host>:<port>/add/cart/<noOfItems>

http://<host>:<port>/remove/cart/<noOfItems>

 

When you first hit the “view” REST endpoint, you can see the 2 carts that we added in our startup class with number of items added to them. You can add or remove items from the Cart using the other two REST calls and can retrieve the updated item count using the “view” REST call. The result from the above REST invocations is a simple JSON structure displaying the Carts and the no of items in the Cart at a given point of time.

 

Conclusion

 

This blog is restricted to introduce you to developing microservice applications using CQRS and Event sourcing patterns. You can refer to the following resources to know more about other advanced concepts and recent updates in this space.

 

References

 

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Oracle Process Cloud service (PCS) provides REST API enabling other applications to integrate with PCS. More details on REST API for Oracle Process Cloud service can be found here. Oracle Process Cloud Service accepts OAuth tokens as an alternative to basic authentication for the REST APIs. In this post we discuss how PCS REST API can be accessed using an OAuth token to create a new business process instance.

 

The scenario discussed in this blog involves a web application deployed in JCS-SX that triggers a business process (“Funds Transfer Process”) deployed in PCS. The “Funds Transfer” process considered in this blog is a simple business process which validates certain attributes of the incoming request and forwards the request for manual approval if needed. The web application obtains the OAuth token from the OAuth server and passes the token to PCS REST API for authentication.

 

The following diagram depicts the high level interactions between JCS-SX, PCS and the OAuth server:

pcs_oauth_blog_image.png

This use case considers that both JCS-SX and PCS instances have been provisioned in the same identity domain. When provisioned in the same identity domain, the resources and clients needed for communicating using OAuth are automatically configured along with an OAuth server which is used for obtaining the tokens. You can navigate to “OAuth Administration” tab from “My Services” and see the following OAuth resources and clients registered by default. Please refer to Managing OAuth Resources and Clients for more details.

 

Note: You need to have an Identity Administrator role to be able to access the "OAuth Administration" page.

pcs_oauth_blog_image_1.png

Note: Please note the client identifier (Id) (highlighted in red box above) and its respective “secret” (secret) that can be viewed by clicking on the “Show Secret” button of the JCS SX OAuth client. This information will be used by the web application to obtain an access token for the client and access PCS REST API.

 

The JCS-SX OAuth client is used to invoke the PCS REST API from the web application, hence ensure that the PCS resource is accessible for this client. You can manage the accessibility of the resources by clicking on the “Modify” menu option under the action palette in “Register Client” section against the JCS-SX OAuth client as shown below:

pcs_oauth_blog_image_2.png

Note: This blog assumes that the business process (“Funds Transfer Process”) is deployed in PCS, the export of the business process is provided in the appendix section for your reference.

 

With the prerequisites in place we can now proceed to obtain the client access token that would be used by the web application to invoke the PCS REST API. This sample uses the OAuth grant types – client_credentials and password to retrieve the client access token involving the following steps:

  1. Obtain client assertion using the client credentials.
  2. Obtain an access token using the client assertion obtained in the above step

 

Note: When it comes to making webservice calls within Oracle Platform Services one can use owsm policies for identity propagation and does not necessarily deal with OAuth tokens explicitly.This is just an illustration of how you could use OAuth token for authenticating with PCS without using owsm policies.

 

These steps are detailed further using specific code snippets.

 

Store the details of the business process to be invoked and the details required to access the OAuth token server in a HashMap.

 

Note: To keep things simple for the purpose of this blog, details like client secret, user name , password are stored in a java HashMap, however it is highly recommended to use Oracle Credential Store Framework (CSF) to ensure secure management of credentials. Please look at “References” section at the end of this blog for more information regarding this.

 

    public static HashMap populateMap() {
        HashMap map = new HashMap();
        // PCS
        map.put("PCS_URL", "https://<PCS_HOST>:443/bpm/api/3.0/processes");
        map.put("PCS_PROCESS_DEF_ID", "default~MyApplication!1.0~FundsTransferProcess");
        map.put("PCS_FTS_SVC_NAME", "FundsTransferProcess.service");
        // OAuth
        map.put("TOKEN_URL", "https://<ID_DOMAIN_NAME>.identity.<DATA_CENTER>.oraclecloud.com/oam/oauth2/tokens");
        map.put("CLIENT_ID", "<CLIENT_ID>");
        map.put("SECRET", "<SECRET>");
        map.put("DOMAIN_NAME", "<ID_DOMAIN_NAME>");
        map.put("USER_NAME","<PCS_USER_NAME>");
        map.put("PASSWORD","<PCS_USER_PWD>");
        return map;
    }
   
    public String getOAuthToken() throws Exception{
        String token = "";
        
        String authString = entryMap.get("CLIENT_ID")+":"+entryMap.get("SECRET");
                
        Map clientAssertionMap = getClientAssertion(authString);
        
        token = getAccessToken(authString,clientAssertionMap);
        
        return token;
    }

 

Note: The values specified in the above code for the keys – PCS_PROCESS_DEF_ID, PCS_FTS_SVC_NAME are only for reference. After you deploy the funds transfer business process in PCS, you can retrieve the details of the business process by executing the following curl command and replace the above values appropriately:

 

curl -u <PCS_USER_NAME>:<PCS_USER_PWD> -H "Content-Type:application/json" -H "Accept:application/json" -X GET https://<PCS_HOST>:443/bpm/api/3.0/process-definitions

 

The “getOAuthToken” method is implemented to retrieve the client assertion by accessing the OAuth server (token endpoint) and passing client_id:client_secret as a basic authorization header. These details can be obtained from OAuth Administration tab as mentioned in a note above. The following code snippet shows how this can be implemented:

 

    private Map<String,String> getClientAssertion(String authString) throws Exception{
        
        resource = client.resource( entryMap.get("TOKEN_URL")+"");
        
        ClientResponse res = null;
        String payload = "grant_type:client_credentials";
        
        MultiPart multiPart = new MultiPart().bodyPart(new BodyPart(payload.toString(), MediaType.APPLICATION_JSON_TYPE));
        
        MultivaluedMap formData = new MultivaluedMapImpl();
        formData.add("grant_type", "client_credentials");
                
        try {
        res = 
            resource.header("X-USER-IDENTITY-DOMAIN-NAME",  entryMap.get("DOMAIN_NAME"))
            .header("Authorization", "Basic " + DatatypeConverter.printBase64Binary(authString.getBytes("UTF-8")))
            .header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
            .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
            .accept(MediaType.APPLICATION_JSON_TYPE)
            .post(ClientResponse.class,formData);
        } catch (Exception e) {
            System.out.println("In catch: "+e);
            e.printStackTrace();
            throw e;
        }
        
        String output = res.getEntity(String.class);
        JSONObject newJObject = null;
        org.json.simple.parser.JSONParser parser = new org.json.simple.parser.JSONParser();
        try {
             
             newJObject = (JSONObject) parser.parse(output);
            
            } catch (org.json.simple.parser.ParseException e) {
                e.printStackTrace();
        }
              
        Map<String,String> assertionMap = new HashMap <String,String>();
        
        assertionMap.put("assertion_token",newJObject.get("access_token")+"");
        assertionMap.put("assertion_type",newJObject.get("oracle_client_assertion_type")+"");
        
        if (res != null && res.getStatus() != 200) {
            System.out.println("Server Problem (getClientAssertion): "+res.getStatusInfo());
            throw new Exception (res.getStatusInfo().getReasonPhrase());
        }
        return assertionMap;
    }

 

The above implementation uses a Jersey client to access the token server and obtain a client assertion and client assertion type. Also note that grant_type:client_credentials being passed in the payload. The following code snippet uses the password grant_type to obtain the client access token from the token server by passing in the client assertion obtained earlier along with user name and password.

 

    private String getAccessToken(String authString,Map clientAssertionMap) throws Exception{
        resource = client.resource(entryMap.get("TOKEN_URL")+"");
        
        String clientAssertionType = (String) clientAssertionMap.get("assertion_type");
        String clientAssertion = (String) clientAssertionMap.get("assertion_token");
                                              
        ClientResponse res = null;
        
        MultivaluedMap formData = new MultivaluedMapImpl();
        formData.add("grant_type", "password");
        formData.add("username", entryMap.get("USER_NAME"));
        formData.add("password", entryMap.get("PASSWORD"));
        formData.add("client_assertion_type", clientAssertionType);        
        formData.add("client_assertion", clientAssertion);        
        
        try {
        res = 
            resource.header("X-USER-IDENTITY-DOMAIN-NAME",  entryMap.get("DOMAIN_NAME"))
            .header("Authorization", "Basic " + DatatypeConverter.printBase64Binary(authString.getBytes("UTF-8")))
            .header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
            .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
            .accept(MediaType.APPLICATION_JSON_TYPE)
            .post(ClientResponse.class,formData);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        
        String output = res.getEntity(String.class);
        
        JSONObject newJObject = null;
        org.json.simple.parser.JSONParser parser = new org.json.simple.parser.JSONParser();
        try {
           
           newJObject = (JSONObject) parser.parse(output);
        
        } catch (org.json.simple.parser.ParseException e) {
           e.printStackTrace();
        }
        
       String token = newJObject.get("access_token")+"";
        
        if (res != null && res.getStatus() != 200) {
            System.out.println("Server Problem (getAccessToken): "+res.getStatusInfo());
            throw new Exception (res.getStatusInfo().getReasonPhrase());
        }
        return token;
    }

 

The PCS resource can now be accessed using the client access token, the following code snippet invokes the PCS REST API to create a new process instance of the “Funds Transfer” Business Process. The payload consists of the details of the process to be created like process definition id, service name and the input values entered by the user in a JSP page. Please note that the OAuth token obtained in the previous step is being set to the “Authorization” header.

    public String invokeFundsTransferProcess(String token,FundsTransferRequest ftr) throws Exception {
     
        StringBuffer payload = new StringBuffer();
        payload.append("{");
        payload.append("\"processDefId\":\""+entryMap.get("PCS_PROCESS_DEF_ID").toString()+"\",");
        payload.append("\"serviceName\":\""+entryMap.get("PCS_FTS_SVC_NAME").toString()+"\",");
        payload.append("\"operation\":\"start\",");
        payload.append("\"params\": {");
        payload.append("\"incidentId\":\""+ftr.getIncidentId()+"\",");
        payload.append("\"sourceAcctNo\":\""+ftr.getSourceAcctNo()+"\",");
        payload.append("\"destAcctNo\":\""+ftr.getDestAcctNo()+"\",");
        payload.append("\"amount\":"+ftr.getAmount()+",");
        String tsfrType;
        if(ftr.getTransferType().equals("tparty"))
            tsfrType = "intra";
        else
            tsfrType = "inter";

        payload.append("\"transferType\":\""+tsfrType+"\"");
        payload.append("}, \"action\":\"Submit\"");
        payload.append("}");
     
        MultiPart multiPart = new MultiPart().bodyPart(new BodyPart(payload.toString(), MediaType.APPLICATION_JSON_TYPE));

        resource = client.resource(entryMap.get("PCS_URL").toString());
        ClientResponse res = null;  
        try {
        res = 
            resource.header("Authorization", "Bearer " + token)
            .type("multipart/mixed")
            .accept(MediaType.APPLICATION_JSON)
            .post(ClientResponse.class, multiPart);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
        
        if (res != null && res.getStatus() != 200) {
            System.out.println("Server Problem (PCSRestOAuthClient.invokeFundsTransferProcess): "+res.getStatusInfo() +" while invoking "+entryMap.get("PCS_URL").toString());
            throw new Exception (res.getStatusInfo().getReasonPhrase());
        }
    
    return res.getStatus()+"";
    }

 

A simple JSP page is used to capture user input and trigger the Funds Transfer Business Process.

pcs_oauth_blog_image_4.png

Upon successful initiation of the Funds Transfer process, you should be able to see an instance of the process getting created and processed in the "Tracking" page of PCS as shown below:

pcs_oauth_blog_image_3.png

 

Known Issues:

Depending on the JDK you use, you might see a "javax.net.ssl.SSLHandshakeException: server certificate change is restricted during renegotiation" error when trying to invoke the PCS REST API from JCS-SX. Please set the following system properties on your JCS-SX and restart the server to work around this issue:

  1. Set "weblogic.security.SSL.minimumProtocolVersion" to "TLSv1.2" in JCS - SaaS Extension and restart JCS - SX
  2. If the problem still persists, set "jdk.tls.allowunsafeservercertchange" to "true" and restart JCS - SaaS Extension

 

Appendix:

Funds Transfer business process (PCS export) for reference -  MyApplication.zip (attached)

 

References:

 

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Oracle PaaS enables building extensions to HCM cloud to provide custom functionality addressing specific business needs. These extensions can be built as bespoke Java web applications which are deployed in PaaS like JCS - SaaS Extension (JCS-SX) and can be embedded into HCM UI as a hyperlink or web page. Please refer to this link for some examples on SaaS extensions using JCS-SX.

 

When accessing the bespoke application from HCM application page, you might have to pass some information specific to the page to the bespoke application which could be used for further processing. This blog explains how to embed an external java web application into HCM UI as a hyperlink and pass context-specific parameters along with security token (JWT in this case) in the dynamic URL generated in Oracle HCM Cloud to the external application. For the sake of simplicity, the web application is just a simple JSP page which displays the values obtained from the HCM.

 

Prerequisites

  • The bespoke web application is deployed in JCS-SX that is associated with the HCM instance. Also if the external web page content is embedded into the region on HCM as a "Web Page", the web application should be manually configured to disable Framebusting by adding the following entry to the web.xml :

<context-param>

  <description> Security precaution to prevent clickjacking - bust frames if the ancestor window domain (protocol, host, and port) and the frame domain are different. Options for this parameter are always and never.</description>

        <param-name>org.apache.myfaces.trinidad.security.FRAME_BUSTING</param-name>

        <param-value>never</param-value>

</context-param>

  • A user account with a user ID identical to the logged-in Oracle HCM Cloud user's user ID is required to be created in JCS-SX. New user can be added by navigating to the "Users" tab on the "My Services" page and clicking on the "Add" button.
  • HCM Cloud user should have administrative role like HCM Application Administrator to be able to edit application pages. Additionally users having access to “Source” view of the page can work with page layout components, this access can be enabled as shown below:

register_app.png

 

Note: All HCM development/customization activities should be performed in an activated sandbox.

 

Registering the external application with HCM

Before you can access the external application from within HCM, it has to be registered with HCM, this can be done using the “Manage Third Party Applications” option present under “Setup and Maintenance Page” as shown below:

register_app_1.png

 

Specify the full URL of the bespoke java application (up to the context root) and the application name in the “Create Third Party Application” page:

register_app_2.png

Define hyperlink to bespoke application from HCM Application Page

A link (named “Employee Details”) will be added to the “Employment Information” (Home -> My Team -> MyTeam ->  <Select an Employee> -> Employment Information) page which points to the bespoke application deployed in JCS-SX. The following steps would enable to create and define this link:

 

    1. Navigate to Employment Information page and click on “Customize Workarea Pages…” link under Administration category as shown below:

hcm_1.png

   2. In the “Customize Page” window that comes up, select “Site” as the customization layer. Switch to the “Source” view of the page as shown below:

hcm_2.png

    3. We will add the “Employee Details” link to the panel highlighted below. This panel can be selected by moving the cursor adjacent to “Years Since Last Promotion” heading.

hcm_3.png

     4. Once the panel is selected, click on the “Add Content” button on the top left corner and click on the “+Add” button against the “Hyperlink” option from the “Components” category as shown below:

hcm_4.png

          Note: If you want to embed the output of external page into a region in the HCM page, you can choose “Web Page” instead of hyperlink.

 

    5. The hyperlink by default gets added as the first element in the panel with title “Click edit icon to define hyperlink”, you can move the hyperlink to the position of your choice within the panel.

hcm_5.png

    6. Select  “Click edit icon to define hyperlink” and click “Edit” on the top (adjacent to “Add Content”) to define the hyperlink properties as shown below:

         hcm_6.png

 

    7. Click on the “Secured Token” tab and then click on the “Create Secure Destination” (Key symbol) as shown below:

    hcm_7.png

    8. Select the name of the web application (specified when registering the application), specify the page that is being pointed to through this hyperlink (in this case it is empDetails.jsp) and give a name to the secured token that you want the JWT token to be tagged to.

hcm_8.png

           Note: HCM Cloud generates a JWT token and assigns it to the key specified in the “Secured Token” field. In this case it is “jwt_tkn”. In the bespoke web application, the token can be fetched as a request parameter.

 

     9. Click on the “Display Options” tab, You can edit the “Text” attribute and change the title of the hyper link, change it to “Employee Details” in this case.

 

    10. On the “Display Options” tab click on the drop down arrow button adjacent to the “Destination” text box and select “Expression Builder”, an Edit box appears as shown below:

      hcm_10.png

The URL configuration specified in the “Secured Token” tab is displayed in the text box:

#{EndPointProvider.externalEndpointByModuleShortName['hcmapp']}/empDetails.jsp?jwt_tkn=#{applCoreSecuredToken.trustToken}

Note that, ‘hcmapp’ is the name of the app we registered with HCM, ‘empDetails.jsp’ is the page this hyperlink would be pointing to and ‘jtw_tkn’ is the name given to the JWT token being passed.

 

    11. The exposed attributes of the current page can be accessed from the “Binding Params” drop down. For example, when you select “Business Unit” attribute from the drop down, the expression for accessing the attribute value is populated in the text box as below:

hcm_11.png

    12. You can identify expressions for the page attributes that needs to be sent along with the URL to the external web application and append them to the URL derived in step # 10 as shown below:

     hcm_12.png

       As depicted above, page attributes like person number, business unit name, and employer name are passed to the external web application in the URL.

 

    13. Click on the “Close” button on top right corner to exit from the page customization view.

 

After the “Employee Details” hyperlink has been added to the page, the “Employment Information” page looks like below:

      hcm_13.png

 

When you click on the “Employee Details” hyperlink, the web application deployed on JCS-SX opens up displaying the attribute values passed in the URL as follows:

hcm_14.png

 

 

Conclusion

This blog demonstrated the steps to access an external java web application from HCM UI as a hyperlink and pass context-specific parameters in the dynamic URL generated in Oracle HCM cloud to the external application deployed in JCS-SX. Please refer to this documentation for more details on page customization in fusion applications.

 

The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Business Process Management (BPM) enables enterprises to rapidly adapt their business to reflect the constantly changing market conditions. BPM is now offered as a Platform as a Service (PaaS) offering, combining the benefits of application development and process support in an integrated cloud model.

 

Typically business processes constitute applications / systems from various LOBs, partners and external parties some of them on cloud and some on-premises. This requires a powerful integration platform to efficiently and easily integrate systems both on cloud and on-premises. Oracle Process Cloud service and Oracle Integration Cloud service are two PaaS offerings from Oracle which enables enterprises to rapidly design, manage business processes and integrations in the cloud.


In this post we will look at the steps involved in developing a simple business process (Funds Transfer Process) using Oracle Process Cloud Service (PCS) which calls an integration deployed in Oracle Integration Cloud Service (ICS) to communicate with an on-premise web service to complete the funds transfer process. The following diagram depicts a high level overview of how the Funds Transfer sample will be realized:


blog_sample_overview.png

Figure 1: Overview of Funds Transfer Sample


Note: Although this post attempts to explain all the key steps involved in building this sample, it does not delve into the security aspects.


The following flow chart represents the business process that we will be building, “Call Funds Transfer Service” in the below diagram represents a SOAP based invocation of ICS integration:

FT_flow_chart.png

Figure 2: Funds Transfer Flow Chart


The final state of Funds Transfer business process we will look as follows:

final_fts_business_process.png

  Figure 3: Funds Transfer Business process (final state)


The content of this post is segregated into three parts:

  • The first part discusses about business processes in PCS, REST connector and Human task configurations.
  • The second part would focus on developing integration flow in Oracle Integration Cloud service (ICS) and creating connectors for on premise web service integration.
  • The third part will bring all these capabilities together to realize the Funds Transfer business process.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

This is the final part of the blog post - "Business Process Orchestration and Integration in Cloud using Oracle PaaS" emphasizing on the high level steps to invoke the ICS integration from the business process via SOAP connector, deploying, executing and tracking the business process instances. While the Part-1 discussed about business processes in PCS, REST connector and Human task configurations, the Part-2 detailed about developing integration flow in Oracle Integration Cloud service (ICS) and creating/configuring connectors for on-premise web services.

 

Create and configure SOAP connector

As depicted in Figure: 3, the activity “Call ICS” is a service call to an ICS integration exposed as a SOAP endpoint. PCS provides a “SOAP connector” that can be configured to call a SOAP service. The following diagrams show how to create and configure a SOAP connector.


Click on the “Connectors” link on the left panel and select “New Web Service Connector” as shown below:

SOAP_Connector_Config_2.png

Figure 41: Add Service Connector


In the “Add service connector” wizard that opens up, select “Upload from File” option, choose the WSDL file of ICS integration (downloaded as specified in Figure: 40 of Part-2). Specify the name for the connector and also configure the security attributes as shown below:


Note: For the process in PCS to be able to invoke the ICS integration, it should be authenticated. This example uses App Id- Basic Auth security policy. This username/password pair is stored in a Credential store configured under Administration page in PCS console as shown in Figure: 43

add_service_connector.pngadd_service_connector_1.pngadd_service_connector_2.png

   Figure 42: Configure SOAP connector


Manage Credentials

Navigate to the PCS home page and select “Configure” icon to create a new credential store. Click on “Add new Credential” as shown in the following diagram, specify the key name and provide the username and password. These credentials can be used when configuring the connection’s security by mentioning the key name.

configure_settings.pngmanage_credentials.png

Figure 43: Manage Credentials


Implement “Call ICS” activity of Funds Transfer process

Now that the SOAP connector has been successfully configured to connect to the ICS integration, use this SOAP connection for implementing the “Call ICS” activity in the Funds Transfer business process as shown below:

SOAP_Connector_Config_1.png

    Figure 44: Configure ICS service call in business process


Define the input and output data mapping of the “Call ICS” activity as shown in the below two diagrams:

SOAP_Connector_data_mapping_1.pngSOAP_Connector_data_mapping_2.png 

    Figure 45: Request data mapping                                                                                                                                                                          Figure 46: Response data mapping


Note: For simplicity, the on premise web service has been implemented such that it returns a “Success” response if all the request attributes have non null values.


This step completes the implementation of the funds transfer business process which should like below:

final_fts_business_process.png

   Figure 47: Final state funds transfer business process


Deploy the business process

The application can be validated for any anomalies by clicking on the  button as depicted on the right top of the above diagram. Once the process is validated it can be deployed. Click on the “Management” link on the top as depicted in the previous diagram, in the next page, click on “Deploy” link appearing on the left top, “Deploy Application to My Server” wizard opens up. Deploy the application following the below diagrams:

deploy_pcs.pngdeploy_pcs_1.pngdeploy_pcs_2.pngdeploy_pcs_3.png

Figure 48: Deploy business process


Once the business process is successfully deployed, you can retrieve the WSDL of the deployed business process as below:

pcs_deployment_webservices.pngpcs_deployment_webservices_1.png

   Figure 49: Funds Transfer business process exposed as web service


When “Web services” menu option is selected as shown above, the “Manage Web Services” page opens up showing all the business processes contained in the deployed application as shown below. This WSDL can be used to trigger the Funds Transfer business process as a web service by passing the data as specified in the “Start” activity. The created process instances can be tracked by clicking on the “Track Instances” icon as shown below:

develop_processes.png

Figure 50: PCS Home page


The following diagram shows a successfully executed Funds Transfer business process going through the manual approval.

FT_Flow_with_Human_Task_success.png

    Figure 51: Track business process instances


Conclusion: This completes the blog post - "Business Process Orchestration and Integration in Cloud with Oracle PaaS". In this post, we have seen how Oracle PCS and ICS offerings put together eases the development of effective and standard driven business process orchestrations and integrations in Cloud.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

This is the Part-2 of the blog post - "Business Process Orchestration and Integration in Cloud using Oracle PaaS" emphasizing on the ICS aspects like creating and configuring integration and SOAP connector to invoke an on-premise web service for completing the funds transfer process. The Funds Transfer business process uses ICS for connecting to an on-premise web service to complete the process execution, please refer to Part-1 for business process orchestration and related configurations.

 

When you log into the ICS server, you will see the following landing page from where you can create connections and integrations. To create a new integration you would first need to create a connection that can used in the integration.

ics_landing_page.png

   Figure 23: ICS Home page


Click on the “Integrations” icon, you will see the Integrations page displaying the existing integrations (if any) as below:

ics_fts_integration.png

   Figure 24: Existing Integrations


Create an agent group

The Funds Transfer business process involves invoking an on-premise web service via ICS integration to complete the transfer process. Connectivity to on-premise in ICS is established using an “Agent”, click on the “Agents” link on the left panel which opens the Agents page displaying the existing agent groups as shown below:


Note: You have to download and install the ICS connectivity agent which is the bridge to connect ICS to on-premise services. Details about downloading, installing/configuring the ICS agent is beyond the scope of this post, please find more details here.


ics_agent_group_1.png

   Figure 25: Create Agent Group


Click on “Create a new Agent Group” button on the right side for creating a new agent group which would be used to invoke an on-premise web service. Name the agent group as “ICS_OnPrem_AG”, this name would be specified when configuring the connection.


ics_agent_group.png

   Figure 26: New Agent Group Information


Create Connections


Click on the “Connections” icon to see the Connections page, click on “Create Connection” button on the right side for creating a connection as shown below to connect to the on-premise SOAP service:

ics_soap_adapter.png

   Figure 27: Create Connection - Select Adapter


Select “SOAP” from the list of adapters shown and provide new connection details as shown below:

ics_create_new_connection.png

   Figure 28: New Connection Information

 

Configure the connection attributes as shown below; this connection uses a SOAP adapter to connect to an on-premise web service via the agent group (ICS_OnPrem_AG) which was created earlier.


Note:  This example assumes that there is a web service deployed and running on an on-premise Weblogic server, the WSDL of this web service is specified while configuring the SOAP adapter.

ics_ft_connection_3.png

  Figure 29: Configuring SOAP connection for on premise service invocation


Click “Configure Connectivity” button to specify the WSDL details of the on premise service as follows:

ics_configure_connectivity.png

   Figure 30: Configure Connectivity


Before you can use the connection in an integration flow, ensure that the connection is tested and the state of the connection is shown as 100% as shown below (on the extreme right):

ics_ft_connection_2.png

  Figure 31: Ready to use Connection


Create a connection (FTS_Source) for configuring the source endpoint as follows:

ics_fts_source_connection.png

  Figure 32: Create connection for integration source


Note: The ICS integration will be invoked as a SOAP service hence the source node of the integration (please refer to Figure: 34) is configured with a connection that uses SOAP adapter. The WSDL file uploaded here will be used for initiating the integration from outside ICS. Please refer to ICS documentation for more details.


Create an Integration Flow

Now we have the on-premise connection and source connection ready, create an integration using these connection definitions by selecting “Basic Map Data” pattern as shown below:

ics_create_new_integration.pngics_create_new_integration_1.png

   Figure 33: Create new Integration


The Integration flow canvas opens up with source and target nodes; there is a palette on the right side which lists all the defined connections. Locate the connection from the palette that you have created for connecting to the on-premise web service (FTS_ON_PREM) and drag/ drop the connection onto the target node as shown below:

ics_fts_integration_target.png

   Figure 34: Drag and Drop connection onto target node


You will see a “Configure SOAP endpoint” page as shown below, give a name to this endpoint and click “Next”. The summary tab (shown below) displays the details of the web service and the operation being invoked using this endpoint configuration.

ics_configure_soap_endpoint.pngics_configure_soap_endpoint_1.png

   Figure 35: Configure SOAP endpoint


Locate the connection from the palette that you have created for source connection (FTS_Source) and drag/ drop the connection onto the source node.After configuring the source and target nodes of the integration it should look like below:

ics_fts_mapping.png

   Figure 36: Integration with configured source and target connections


Map Request and Response

Click on the “Click Below to create Map” link (shown in the above diagram) to add data transformers to the request and response paths as shown below:

ics_ft_on_prem_integ_req_mapping.pngics_ft_on_prem_integ_res_mapping.png

   Figure 37: Map Request and Response data


After completing the above steps successfully, your integration should look like below:

ics_ft_on_prem_integ_2.png

   Figure 38: Integration after configuring data transformations


Exit the Integration by clicking on the “Exit Integration” button on left top and activate the integration by clicking on the “Activate” button as shown below:

ics_activate_integration.png

     Figure 39: Activate Integration


After the integration is activated, by placing the mouse cursor on the information icon (as shown below) you will be able to find the endpoint URL of the ICS integration that you have built. You can use this endpoint URL just like any other WSDL endpoint to invoke the integration as a web service.

ics_fts_endpoint.png

Figure 40: WSDL for Integration


This concludes the Part-2 of this blog post, please refer to Part-3 where all these pieces will be brought together for invoking the ICS integration defined above from the PCS business process defined in Part-1.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

This is the Part-1 of the blog post - "Business Process Orchestration and Integration in Cloud with Oracle PaaS". Oracle PCS is a BMPM 2.0 compliant BPM offering on cloud (please refer to http://www.bpmn.org/ for more details on BPMN standard). The highlighted BPMN constructs of Oracle Process Cloud service (PCS) are used to build the Funds Transfer business process:

BPMN_pallatte_1.png

Figure 4: BPMN Palette


Create a business process


From the PCS console, select the “Develop Processes” option to define the Funds Transfer business process as depicted below:

develop_processes.png

Figure 5 : Develop Processes


The “All Spaces” page opens up displaying the existing applications (if any) as follows:

all_spaces.png

Figure 6 : Landing page showing the existing applications


In case you want to create a new application or a new space, you can do that by clicking on the “Create” button as shown below:

Create_new_space.png

Figure 7: Create new Space/Application


Business processes are created in an application which in-turn resides in a space. In this case we create the Funds Transfer process in an application called “My Application”.  Once you select the application, you will see the “Application Home” page displaying any existing business processes (if any) as shown below:

app_home.png

Figure 8: Page displaying existing business processes


As you can see, on the left menu in the above diagram, you will find various options like processes, web forms, types…etc. You can click on each of these links to get into the details.

 

Create a Business Process

Click on the “+” icon on the extreme right to create a new business process, a “Create Process” page opens up where you can give the details of the business process and select a pattern based on which you will be building the process.

As we want this business process to be triggered from an external application like a UI or from an external service we use “Message” pattern which kicks off the business process upon receiving a message.

Create_business_process.png

Figure 9: Create Process Page

 

An empty business process is created with start and end events and is opened in a canvas as shown below.

new_business_process.png

Figure 10: New process with start and end activities


Drag and drop the respective activities/tasks from the BPM palette onto the canvas and wire them appropriately so that your business process should like figure 2. For more details on how to do this, please refer to the PCS documentation.

Once the skeleton of the process is ready you can configure/ implement the activities which would require defining business types, creating connectors to make service calls and configuring human tasks that are needed to realize the Funds Transfer business process.


Define Business Types

Business types are complex data structures that are used as containers to send data from one component to the other. The following diagram depicts the business objects being used in the Funds Transfer process:

business_types.png

Figure 11: Page displaying the existing business type definitions

 

The following image shows the attributes of each of the business types. The “FundsTransferDataForm” business type is used to populate the form which is used to display the request data to a human for the manual approval activity. The “ResponseFromValidator” type is used to capture the response sent by the REST service after validating the request. The “FundsTarnsferBO” type is used for sending the request to the on-premise web service call to perform the funds transfer. More details about the REST / on-premise web services and their respective configurations can be found in subsequent sections.

funds_tsfr_data_types.png

Figure 12: Business Type attributes


Configure the “Start” activity

You can configure/implement the ‘start’ activity of the business process by clicking on the “Start” activity and then clicking on the details  icon as shown below:

start_event_impl.png

Figure 13: Configure Start Activity

 

As you can see above, we have defined an interface with five attributes and associated it with the “Start” activity, these five attributes constitute the request for the business process.


Note: Once the Funds Transfer process is deployed to PCS runtime, a WSDL endpoint is generated for this business process enabling it to be invoked as any other web service. More details about this will be provided later in the post.


Create and configure REST connector

As depicted in Figure: 2, the next activity is “Validate req” which is a service call to a REST endpoint that is deployed in Java Cloud Service (JCS). PCS provides a “REST connector” that can be configured to call a REST service. This example assumes that there is a REST web service deployed and running on JCS, the details of the REST endpoint are specified when configuring the REST connector. The following diagrams show how to create and configure this:


Note: In this example, APP Id – Basic Authentication security policy is used for authentication. You can define a new key (the diagram below shows a key created with name “JCS-SX”) and specify the username and password used for connecting to the REST service.

REST_Connector_1.png    REST_Connector_2.pngREST_Connector_Config.png

Figure 14: Create REST connector                                                                                                                                                                                                                                                                    Figure 15: Configure REST connector


As you can see in the above configuration, the request received by the Funds Transfer business process is validated by invoking a REST service deployed in JCS.

 

Note: To keep things simple, the REST service just takes the “incidentId” attribute from the request as input and returns a failure if it is NULL which means the request is invalid.

 

Once the REST connector is configured it can be used to define the “Validate req” activity (which is a service call) of the Funds Transfer process as shown below:

REST_Connector_Config_2.png

Figure 16: Implement service call activity using REST connector


Select the “Type” as ‘Service Call’ and select the REST connector that you have created in the previous step and choose the resource and the operation you want to call on the selected resource for validating the funds transfer request.


After the implementation details have been provided, you need to map the input to and output from the REST service as shown in the below diagrams. Also note that the business types defined above are being used when mapping the request/response.

REST_Connector_data_mapping_1.pngREST_Connector_data_mapping_2.png

Figure 17: Request and Response data mapping to REST service


Please refer to the Oracle PCS documentation for more information on working with REST and Web Service connectors.

Note: This post will not go into the details of implementing the “Exclusive Gateway” gateway.pngactivity which is similar to an if-then-else implementation. Please refer to PCS documentation for more details regarding this.


Create and configure Human task

The next important activity in the Funds Transfer process is the manual approval activity which needs human intervention to either approve or reject the funds transfer requests based on certain criteria. Configure the manual approval activity as depicted in the following diagram:

Human_Task_config.png

Figure 18: Configure Human task for manual approval activity

 

Select the “FundsTransferDataForm” as the web form to be used for presenting the request data to the reviewer. Specify “APPROVE” and “REJECT” as the two possible actions the approver can perform on the funds transfer request.


Note: The application users have to be mapped to roles (process owner and reviewer) so that they receive notifications and can act on the tasks assigned to them. Please refer to PCS documentation for more details.


If a funds transfer request needs a manual approval (transfer type = “inter bank”, amount > 10000) an email will be sent to the reviewer (needs to be configured as an Administration task) which looks like below:

action_required_mail.pngapproved_task_mail.png

Figure 19: Email notifications sent to reviewer


Note the link to the “Workspace Application”, when the reviewer clicks this link he/she is taken to the workspace where he can view the request details and act accordingly, the following diagram depicts this:

approval_in_workspace.png

Figure 20: Request data being presented to the reviewer in a form


In order to receive email notifications, you have to configure the notifications by accessing the settings option as shown below:

configure_settings.pngconfigure_notifications.png

Figure 21: Configure Administrative Settings                                                                                                                        Figure 22: Configure Email Notifications


Note: Please refer to Configuring Email Notifications in PCS documentation for more details.


Please refer to Part-2 of this post for creating and configuring integration and SOAP connector in ICS to invoke an on-premise web service for completing the funds transfer process


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Overview

Let us consider that an enterprise is using Oracle Sales Cloud to manage business critical information about its customer accounts and prospects. A Sales Manager has scheduled a visit to a customer and as part of his travel want to visit other nearby customers also.

Oracle Sales Cloud does not have an OOTB capability to locate nearby accounts but this capability can be built in Oracle PaaS as a:

  • Custom Java EE application embedded as a sub-tab into Sales Cloud UI
  • Deployed on Oracle Cloud Services: Java Cloud Service SaaS Extension
  • Enables Sales Representatives to query and locate other nearby accounts


PaaS-SaaS_1.png








 


Figure : Extending Sales Cloud using JCS-SX


Solution Approach

 

When the logged-in user clicks on the embedded sub tab in Sales Cloud, the java application receives the selected account’s context parameters (account id, account latitude, and account longitude) from Oracle Sales Cloud along with a authorization token( JWT, please refer to this blog for more details) in the URL. This short screen cast provides a brief functional and technical overview of this solution.


The java application builds a view criterion and calls Oracle Sales Cloud’s Account Service by passing JWT for authorization. The response would include all accounts (based on logged-in user) that are located within a specific radius of the currently selected account. Please refer to this sample on oracle cloud developer portal for detailed explanation about this extension capability.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Overview

An enterprise is using Oracle Sales Cloud to manage information about its customers and prospects. It has developed a custom web application to be used by its sales representatives to maintain a log of company-branded merchandise given away to customers, as part of standard sales process. The customer information needed to log the merchandise is accessed from Sales Cloud.

 

Using this application a sales representative is able to enter the value of merchandise, issued for a specific customer. During the process of logging merchandise, the sales representative will only be able to see accounts accessible to him/her. This short screen cast provides a brief functional and technical overview of this solution.

 

PaaS-SaaS_2.png

Figure : Secured access to Sales Cloud data

 

Solution Approach

A sales representative tries to log merchandise using the bespoke java application and starts typing an account name, accounts accessible by the logged in user will be suggested to the user. These suggestions are fetched by calling a web service provided by Sales Cloud. The pre-configured security and trust between PaaS (JCS-SX) and SaaS (Sales Cloud) enables bespoke applications to make secured web service calls and access Sales Cloud data without any additional security setup. 


Please refer to this blog for more details on securing web service interactions between Oracle Sales Cloud and JCS-SX. This ensures that the user logged into the bespoke application can only view the accounts accessible to him. Please refer to this sample on oracle cloud developer portal for detailed explanation about this capability.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Overview

An enterprise wants to assign a Credit Health Score to every account/opportunity. This score ranges from 1 to 10 and is calculated based on a complex logic involving data from several internal and external systems. The enterprise has built a bespoke web application developed and maintained by a development team within the enterprise that

  • Exposes the Credit health score calculation logic as a web service and is deployed in JCS-SX
  • Is deployed on Oracle Cloud Services: Java Cloud Service SaaS Extension
  • Is used to calculate the credit health score of every account/opportunity

  This short screen cast provides a brief functional and technical overview of this solution.

PaaS-SaaS_3.png

Figure 3: Integrate SaaS applications with external systems


Solution Approach

 

A sales manager logs into Oracle Sales Cloud to view the details of an account. When the user selects an account, on the default account view page, he finds a new custom field called “Credit Health Score”. The value of this custom field is fetched by invoking the Credit Health Score web service deployed in JCS-SX. Please refer to this sample application on oracle cloud developer portal for more detailed explanation about building this extension.

 

The pre-configured security and trust between PaaS (JCS-SX) and SaaS (Sales Cloud) enables Sales Cloud to make secure web service call to the bespoke application deployed in JCS-SX without any additional security setup. Please refer to this blog for more details on securing web service interactions between Oracle Sales Cloud and JCS-SX.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Overview

 

An enterprise is using Oracle Sales Cloud to manage information about its customers and prospects. The enterprise needs to manage the feedback received from its dealers and has built a custom web application for this purpose. This application has two user roles:

  1. ‘Dealer’ who creates his feedback using the custom web application
  2. ‘Dealer Manager’ who uses Oracle Sales Cloud and wants to check the feedback received from all dealers.

  This short screen cast discusses briefly about the functional and technical overview of this scenario.


PaaS-SaaS_4.png

Figure : Custom web application linking out to Sales Cloud


Solution Approach

 

The custom web application is deployed on JCS-SX and embedded into Sales Cloud as an external link (“Dealer Feedback” menu link) which enables the dealer manager to view and act upon the feedback received from the dealers. This sample on oracle cloud developer portal provides a detailed explanation about this capability.


Though the embedded application is protected on JCS-SX, when the dealer manager accesses the “Dealer Feedback” menu link, he/she does not need to authenticate again. This is because of the pre-established security and trust between JCS-SX and Sales cloud which enables users to single sign on.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Overview

 

An enterprise is using Oracle Sales Cloud to manage information about leads and opportunities. The enterprise has built a custom web application to capture and maintain certain pieces of information pertaining to the sales leads.  Users accessing this application are given limited access to Oracle Sales Cloud for updating lead information and do not have access to other Oracle Sales Cloud system functions. This application is deployed on JCS-SX and links out to Oracle Sales Cloud to work on sales leads.


A brief functional and technical overview of this scenario is discussed in this short screen cast.

 

PaaS-SaaS_5.png

Figure: Custom web application linking out to Sales Cloud

 

Solution Approach

 

A user logs into the custom web application and creates a new lead record and by clicking on a button in the web UI, the user will be taken to Oracle Sales Cloud where he/she can further work with the lead information.  This sample on oracle cloud developer portal provides a detailed explanation on building this extension.


Slimmed-down subsets of Oracle Sales Cloud features are made visible to the logged in user limiting the access to only specific Sales Cloud functions. This is because the user is assigned a custom role in Sales Cloud restricting his access to only leads and opportunity related functions.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Overview


An enterprise is using Oracle Sales Cloud to manage information about leads and opportunities. The sales representatives of an enterprise would want to know if there are any pending / long-standing service requests from customers before meeting them for additional sales opportunities. Additionally, the representatives would also like to be current on the latest news about their accounts such as leadership changes, recent announcements, or anything that may impact their selling ability.

 

The enterprise has built a bespoke web application which is deployed in JCS-SX that lists all open service requests related to a specific customer. This short screen cast discusses briefly about the functional and technical overview of this scenario.

 

PaaS-SaaS_6.png

Figure: Embed extended UI within Sales Cloud UI


Solution Approach

 

When the user selects an account in Sales Cloud UI, in the account widget a new sub-tab linked to the web application which is deployed in JCS-SX is displayed.  Upon clicking this tab, the sales representative will be able to view all the pending/open service requests for the selected customer along with recent changes/announcements relevant to the customer. This sample on oracle cloud developer portal provides a detailed explanation on this solution.


Though the embedded application is protected on JCS-SX, when the sales representative navigates to this sub-tab, he/she does not need to authenticate. This is because security and trust is pre configured enabling users to single sign on to JCS-SX and Sales cloud. Since the sales representative is already signed into Sales Cloud, the embedded page is directly displayed.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.

Overview

 

An enterprise is using Oracle Sales Cloud to manage information about sales opportunities and revenue estimates. The enterprise has built a custom web application to graphically compare the revenue estimate of a selected opportunity against all other opportunities for that quarter both from an actual dollar amount and a dollar amount adjusted by win probabilities. This application is deployed in JCS-SX and is embedded into Sales Cloud.


A brief functional and technical description of this scenario is presented in this short screen cast.

 

PaaS-SaaS_7.png

Figure : REST web service call to access Sales Cloud data

 

Solution Approach


A sales administrator logs into Oracle Sales Cloud to view the information pertaining to a sales opportunity. When the user selects the opportunity, in the default view, he finds a new sub-tab on the left pane. When clicked on this new sub-tab, the custom web application deployed in JCS-SX is displayed providing an integrated user experience. Upon clicking this tab, a set of two pie charts are displayed comparing the selected opportunity's revenue (both actual and adjusted by win probability) to the quarter's opportunity totals.


The web application deployed in JCS-SX makes a REST web service call to the Sales cloud using super user credentials configured in JCS-SX and retrieve opportunity details. The web application then uses this information to generate the pie charts.


The views expressed in this post are my own and do not necessarily reflect the views of Oracle.