Sunday, November 3, 2024

#1031 - OIC Integration Basics - Lab3

Introduction

Lab 3 covers invoking the createOrder integration DB via its REST api. It also discusses logging/tracing and basic OIC error handling.

Let's look again at the Endpoint Metadata for the lab2 integration - 

We'll take the endpoint URL and invoke this from Postman. 

Regarding logging - we will discuss the different tracing levels available with OIC - 

Finally, we'll look at OIC error handling - both at global and scope level - 







 

Lab 3 

Let's begin with invoking the integration via its api.

Invoking App Driven Integrations

Successful call from Postman - so what did I need to configure here? Let's start with the REST connection security definition - 

OAuth is specified, so this is what we have to leverage from our client, in my case, Postman - 

As you can see, I have specified OAuth client credentials. So I need an app that provides me with such. Here I need to go to the OCI console - 






There will be an entry here for your OIC service - the name of your service is shown in the About box in the OIC Designer - 



Clicking on the link for this I entry, I see - 























This is the default OAuth configuration, auto-created for this instance. We could use this, however, it is best practice to create what's known as an Integration Application for this OIC instance -





I add a name and description and then click Next


























Now to adding resources - 

We will add the scopes for the OIC instance - select the instance and click Add


Note the scopes are added - 


Skip the next page and click Finish -

Save the client id and secret that has been generated for you - 

Back to Postman - 

I also need to enter the Access Token URL - this is in the format - https://yourIDCSURL.identity.oraclecloud.com/oauth2/v1/token

You can find your IDCS url here at Domain level -

Postman also requires the scopes - these are the 2 entries we added to the confidential app, so copy these to postman - 

Final step, before we test in Postman - 
add the confidential app to the Service Invoker role, of our OIC instance. Here we need to select the auto-created Oracle Cloud Services entry for the OIC instance - 










Finally, ensure you have activated the confidential app - 

Get a new access token in Postman - 

Use the token and test - 


OIC Logging / Tracing

Logging/tracing is expensive, so, for Production is the way to go, for your OIC Production instance. This level of trace logs all activities executed, but none of the payloads. The data is retained in OIC for 32 days, i.e. covers the calendar month.  

Audit adds a bit more - here all inbound and outbound payloads are logged, however, the payload data is only retained for 8 days.

Debug logs all activities and payloads as well as transformations. This is very useful when developing your integrations, however, it is automatically set back to Production, after 24 hours. 

Tracing can also be set globally - 








Many customers need to retain some of the data that flows thru the integrations for compliance purposes, e.g. the ability to prove when order number 2112 was processed and what the outcome was. 

OCI Logging and OCI Logging Analytics, 2 other OCI services often used in concert with OIC, can be very helpful here. More about them in a future post in this series. However, one could also use a business database (e.g. ATP) to store such data.

Integration Error Handling

Each integration comes with a pre-defined Global Fault Handler

the default behaviour is to re-throw the fault that has been thrown during the execution of the integration. Remember Lab2, where we created an integration that wrote to our Orders DB? OrderNr is the primary key, so, this error will be thrown, if I execute the integration twice with the same orderNr. 

At the outset, I apologise for the level of detail to which I go, but better to go through this once and to understand exactly what's happening. I hope you concur. 















Let's execute the integration twice for orderNr 2130 - 

Check out the error message returned - 

{
  "type" : "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1",
  "title" : "Internal Server Error",
  "detail" : "Internal server error. Please contact oracle support for details.",
  "errorCode" : "500",
  "errorDetails" : [ {
    "type" : "UnMappedFault:",
    "instance" : "NA",
    "title" : "faultName: {{http://schemas.oracle.com/bpel/extension}remoteFault} cause: {Exception while processing Invoke request for endpoint <CreateOrderDB_REQUEST>. Error Message : oracle.cloud.cpi.common.core.CpiException: oracle.tip.adapter.sa.impl.fw.ext.org.collaxa.thirdparty.apache.wsif.WSIFException: file:/C:/work/OIC/Gen3/ConnAgent/NewOIC3Dev/oic_conn_agent_installer/agenthome/agent/data/b070beaa-7c67-47b3-8ba8-e6897c68fa3d/CreateOrderDB_REQUEST.wsdl [ CreateOrderDB_REQUEST_ptt::insert(parameters) ] - WSIF JCA Execute of operation 'insert' failed due to: DBWriteInteractionSpec Execute Failed Exception.\ninsert failed. Descriptor name: [CreateOrderDB.Orders].\nCaused by java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (NIALLC.PK_ORDERNR) violated\n.\n; nested exception is: \n\tBINDING.JCA-11616\nDBWriteInteractionSpec Execute Failed Exception.\ninsert failed. Descriptor name: [CreateOrderDB.Orders].\nCaused by java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (NIALLC.PK_ORDERNR) violated\n.\nPlease see the logs for the full DBAdapter logging output prior to this exception.  This exception is considered not retriable, likely due to a modelling mistake.  To classify it as retriable instead add property nonRetriableErrorCodes with value \"-1\" to your deployment descriptor (i.e. weblogic-ra.xml).\nORA-00001: unique constraint (NIALLC.PK_ORDERNR) violated\nFault Details : \n<err:serviceInvocationError xmlns:err=\"http://xmlns.oracle.com/cloud/generic/service/fault\">\n   <err:type>DBWriteInteractionSpec Execute Failed Exception</err:type>\n   <err:title>insert failed. Descriptor name: [CreateOrderDB.Orders].</err:title>\n   <err:detail>Caused by java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (NIALLC.PK_ORDERNR) violated\n.</err:detail>\n   <err:errorCode>serviceInvocationError</err:errorCode>\n   <err:remedialAction>Please see the logs for the full DBAdapter logging output prior to this exception.</err:remedialAction>\n</err:serviceInvocationError>\n\n}",
    "errorPath" : "<![CDATA[<location xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\">orcldatabase-adapters-7cf8577557-sk7m6</location>\n]]>",
    "errorCode" : "CA-BS-001"
  } ]
}

The error is there - primary key violation, however, also a lot of noise that could confuse the client developer, calling this api.

You will also find the error logged at connectivity agent level, remember, it's the connectivity agent that does the actual DB insert - 


The OIC response error structure is as follows - 

Now to the Global Fault Handler - 

As you can see above, the Global Fault Handler has 3 fields - errorCode, reason and details. I have added 3 Log actions to log these values to the Activity Stream.


Btw. Log actions are independent of the trace level selected, i.e. I also get them logged with trace set to production.



Note the subtle difference.

We will now re-model the integration somewhat, in order to capture any DB errors. Think of a scope as a container for related OIC actions, for example, our DB invoke to insert a new order. The scope will also include the mapping action for this invoke. Scopes not only make your models more readable, they also contain an error handler, which we will use.

I drop the SCOPE after the Trigger and then cut and paste the DB Invoke and map action into it. I then give the scope and appropriate name - 

I edit the scope name then edit the Fault Handler - 

I add a Log action, just to show you the Fault structure - 


As you can see, the same structure as the Global Fault Handler. 

I add the same Log Actions and run the integration again - 

Note how the integration apparently runs successfully - 
























But let's look at the Activity Stream - 

The error has been caught at scope level, thus overriding the Global Fault Handler.

Let's now handle the error properly - I begin by doing some string manipulation to extract the salient error. I assign this to a variable, which will be used to set the response "status".

I run the integration again - 

The response looks better, but the integration is still considered as having run successfully -

So back to our Scope Fault Handler - here we will throw a new integration specific fault - 

I run the integration again - 

Here is the error in Postman - 

But notice we still have a lot of noise - 
This can be addressed by adding a Fault Return action - note the target mapping -

As you can see, I have hardcoded most of these, except for 2, which take their values from the following source - 
























I now delete the ThrowNewFault action, so my scope fault handler is as follows - 


I run the integration again with a duplicate orderNr - 


No more noise - 
Naturally, I could have done this processing also in the Global Fault Handler - 























Net, net - error handling is a MUST. A best practice may be to implement a generic error handler, that can be called by all relevant integrations, but more about such later.  

Summa Summarum

We have covered invoking your app driven OIC integrations from 3rd party clients, logging/tracing, as well as an in-depth look at error handling. The next lab will look at Scheduled Integrations.











 

 

 
























No comments: