X

Best Practices from Oracle Development's A‑Team

Java API for Integration Cloud Service

Greg Mally
Principal Solutions Architect

Author: Ricardo Ferreira

Introduction

Oracle ICS (Integration Cloud Service) provides a set of handy REST APIs that allow users to manage and monitor related artifacts such as connections, integrations, lookups and packages. It also allow the retrieval of monitoring metrics for further analysis. More details about it can be found in the following documentation link.

The primary use case for these REST APIs is to allow command-line interactions to perform tasks such as gathering data about ICS integrations or backup a set of integrations by exporting its contents. In order to interface with these REST APIs, users may adopt command-line utilities such as cURL to invoke them. For instance, the command below shows how to retrieve information about a connection:

curl -u userName:password -H "Accept:application/json" -X GET https://your-ics-pod.integration.us2.oraclecloud.com/icsapis/v1/connections/connectionId

If the command above executes completely then the output should be something like the following JSON payload:

{
   "links":{
      "@rel":"self",
      "@href":"https:// your-ics-pod.integration.us2.oraclecloud.com:443/icsapis/v1/connections/connectionId"
   },
   "connectionproperties":{
      "displayName":"WSDL URL",
      "hasAttachment":"false",
      "length":"0",
      "propertyGroup":"CONNECTION_PROPS",
      "propertyName":"targetWSDLURL",
      "propertyType":"URL_OR_FILE",
      "required":"true"
   },
   "securityproperties":[
      {
         "displayName":"Username",
         "hasAttachment":"false",
         "length":"0",
         "propertyDescription":"A username credential",
         "propertyGroup":"CREDENTIALS",
         "propertyName":"username",
         "propertyType":"STRING",
         "required":"true"
      },
      {
         "displayName":"Password",
         "hasAttachment":"false",
         "length":"0",
         "propertyDescription":"A password credential",
         "propertyGroup":"CREDENTIALS",
         "propertyName":"password",
         "propertyType":"PASSWORD",
         "required":"true"
      }
   ],
   "adaptertype":{
      "appTypeConnProperties":{
         "displayName":"WSDL URL",
         "hasAttachment":"false",
         "length":"0",
         "propertyGroup":"CONNECTION_PROPS",
         "propertyName":"targetWSDLURL",
         "propertyType":"URL_OR_FILE",
         "required":"true"
      },
      "appTypeCredProperties":[
         {
            "displayName":"Username",
            "hasAttachment":"false",
            "length":"0",
            "propertyDescription":"A username credential",
            "propertyGroup":"CREDENTIALS",
            "propertyName":"username",
            "propertyType":"STRING",
            "required":"true"
         },
         {
            "displayName":"Password",
            "hasAttachment":"false",
            "length":"0",
            "propertyDescription":"A password credential",
            "propertyGroup":"CREDENTIALS",
            "propertyName":"password",
            "propertyType":"PASSWORD",
            "required":"true"
         }
      ],
      "appTypeLargeIconUrl":"/images/soap/wssoap_92.png",
      "appTypeMediumGrayIconUrl":"/images/soap/wssoap_g_46.png",
      "appTypeMediumIconUrl":"/images/soap/wssoap_46.png",
      "appTypeMediumWhiteIconUrl":"/images/soap/wssoap_w_46.png",
      "appTypeName":"soap",
      "appTypeSmallIconUrl":"/images/soap/wssoap_32.png",
      "displayName":"SOAP",
      "features":"",
      "source":"PREINSTALLED",
      "supportedSecurityPolicies":"Basic Authentication, Username Password Token, No Security Policy"
   },
   "code":"connectionCode",
   "imageURL":"/images/soap/wssoap_w_46.png",
   "name":"Connection Name",
   "percentageComplete":"100",
   "securityPolicy":"USERNAME_PASSWORD_TOKEN",
   "status":"CONFIGURED",
   "supportsCache":"true"
}

These APIs were designed to return JSON payloads in most cases. However, some operations allow the result to be returned in the XML format. Users can control this by specifying the "Accept" HTTP header in the request.

Regardless of which format is chosen to work with, it is expected that users must handle the payload to read the data. This means that they will need to develop a program to retrieve the payload, parse it somehow and then work with that data. Same applies to invoking REST endpoints with path parameters or posting payloads to them. The end result is that a considerable amount of boilerplate code must be written, tested and maintained no matter which programming language is chosen.

Aiming to make things easier, the Oracle A-Team developed a Java API to abstract the technical details about how to interact with the REST APIs. The result is a simple-to-use, very small JAR file that contains all you need to rapidly create applications that interact with ICS. Because the API is written in Java, it can be reused across a wide set of programming languages that can run on a JVM including Clojure, JavaScript, Groovy, Scala, Ruby, Python, and of course Java.

The Java API for ICS is provided for free to use "AS-IS" but without any official support from Oracle. Bugs, feedback and enhancement requests are welcome but need to be performed using the comments section of this blog and the A-Team reserves the right of help in the best-effort capacity.

This blog will walk you through the steps required to use this Java API, providing code samples that demonstrate how to implement a number of common use cases.

Getting Started with the Java API for ICS

The first thing you need to do to start playing with the Java API for ICS is to download a copy of the library. You can get a free copy here. This library also depends on a few Open-Source libraries so you will need to download these as well. The necessary libraries are:

* FasterXML Jackson 2.0: The library uses this framework to handle JSON transformations back and forth to Java objects. You can download the libraries here. The necessary JAR files are: jackson-core, jackson-annotations and jackson-databind.

* Apache HTTP Components: Used to handle any HTTP interaction with the REST APIs for ICS. You can download the libraries here. The necessary JAR files are: http-core, http-client, http-mime and commons-codec and commons-logging.

It is important to remember that you must use JDK 1.6 or higher. Any JDK older version won't work. Once all the libraries are on the classpath, you will be ready to get started.

Excuse me Sir - May I Have a Token?

The Java API for ICS was designed to provide the highest level of simplicity possible. Thus, pretty much all operations can be executed by calling a single object. This object is called Token. In simpler terms, a token gives you access to execute operations against your ICS pod. However; as you may expect, tokens are not freely accessible. In order to create a token, your code needs to authenticate against ICS. The example below shows how to create a token.

import com.oracle.ateam.cloud.ics.javaapi.Token;
import com.oracle.ateam.cloud.ics.javaapi.TokenManager;
public class CreatingTokens {
   public static void main(String[] args) throws Exception {
      String serviceUrl = "https://your-ics-pod.integration.us2.oraclecloud.com";
      String userName = "yourUserName";
      String password = "yourPassword";
      Token token = TokenManager.createToken(serviceUrl, userName, password);
      System.out.println("Yeah... I was able to create a token: " + token);
   }
}

The parameters used to create a token are pretty straightforward, and you should be familiar with them for your ICS pod. When the createToken() method is executed, it tries to authenticate against the ICS pod mentioned in the service URL. If for some reason the authentication does not happen, an exception will be raised with proper details. Otherwise, the token will be created and returned to the caller.

A token is a very lightweight object that can be reused across your application. Thus, it is a good idea to cache it after its creation. Another important aspect of the token is that it is thread-safe. That means that multiple threads can simultaneously invoke its methods without concerns about locks of any kind.

Using a Token to Perform Operations against ICS

Once you have properly created a token, you can start writing code to retrieve data from ICS and/or invoke operations against it. The examples below will show various ways in which the Java API for ICS can be used.

Listing all the integrations; who created them and their status

Token token = TokenManager.createToken(serviceUrl, userName, password);
List<Integration> integrations = token.retrieveIntegrations();
for (Integration integration : integrations) {
   System.out.println(integration.getName() + ": Created by '" +
   integration.getCreatedBy() + "' and it is currently " +
   integration.getStatus());
}

Showing source and target connections of one specific integration

Token token = TokenManager.createToken(serviceUrl, userName, password);
Integration integration = token.retrieveIntegration(integrationId, integrationVersion);
System.out.println("Integration: " + integration.getName());
Connection sourceConnection = integration.getSourceConnection();
Connection targetConnection = integration.getTargetConnection();
System.out.println("   Source Connection: " + sourceConnection.getName() +
         " (" + sourceConnection.getAdapterType().getDisplayName() + ")");
System.out.println("   Target Connection: " + targetConnection.getName() +
         " (" + targetConnection.getAdapterType().getDisplayName() + ")");

Exporting all integrations that are currently active

final String BACKUP_FOLDER = "/home/rferreira/ics/backup/";
Token token = TokenManager.createToken(serviceUrl, userName, password);
List<Integration> integrations = token.retrieveIntegrations();
for (Integration integration : integrations) {
   if (integration.getStatus().equals("ACTIVATED")) {
      Status status = integration.export(BACKUP_FOLDER + integration.getCode());
      System.out.println(integration.getCode() + " = " + status.getStatusInfo());
   }
}

Alternatively, if you are using JDK 1.8 then you could rewrite the entire for-each code using Lambdas:

integrations.parallelStream()
   .filter(i -> i.getStatus().equals("ACTIVATED"))
   .forEach((i) -> {
      String fileName = BACKUP_FOLDER + i.getCode();
      System.out.println(i.export(fileName).getStatusInfo());
   });

Printing monitoring metrics of one specific integration

Token token = TokenManager.createToken(serviceUrl, userName, password);
MonitoringMetrics monitoringMetrics = token.retrieveMonitoringMetrics(integrationId, integrationVersion);
System.out.println("Flow Name: " + monitoringMetrics.getFlowName());
System.out.println("   Messages Received...: " + monitoringMetrics.getNoOfMsgsReceived());
System.out.println("   Messages Processed..: " + monitoringMetrics.getNoOfMsgsProcessed());
System.out.println("   Number Of Errors....: " + monitoringMetrics.getNoOfErrors());
System.out.println("   Errors in Queues....: " +
   monitoringMetrics.getErrorsInQueues().getErrorObjects().size());
System.out.println("   Success Rate........: " + monitoringMetrics.getSuccessRate());
System.out.println("   Avg Response Time...: " + monitoringMetrics.getAvgRespTime());
System.out.println("   Last Updated By.....: " + monitoringMetrics.getLastUpdatedBy());

Deleting all connections that are currently incomplete

Token token = TokenManager.createToken(serviceUrl, userName, password);
List<Connection> connections = token.retrieveConnections();
for (Connection connection : connections) {
   if (Integer.parseInt(connection.getPercentageComplete()) < 100) {
      connection.delete();
   }
}

Deactivating all integrations whose name begins with "POC_"

Token token = TokenManager.createToken(serviceUrl, userName, password);
List<Integration> integrations = token.retrieveIntegrations();
for (Integration integration : integrations) {
   if (integration.getName().startsWith("POC_")) {
      System.out.println(integration.deactivate());
   }
}

Listing all packages and its integrations (using JDK 1.8 Lambdas)

Token token = TokenManager.createToken(serviceUrl, userName, password);
List<com.oracle.ateam.cloud.ics.javaapi.types.Package> pkgs = token.retrievePackages();
pkgs.forEach((p) -> {
   System.out.println("Package Name: " + p.getPackageName());
   p.getPackageContent().forEach(pc -> System.out.println(pc.getName()));
});

Importing integrations into ICS from the previously exported archive

Token token = TokenManager.createToken(serviceUrl, userName, password);
Status status = token.importIntegration("home/rferreira/ics/backup/myInteg.iar", false);
System.out.println(status.getStatusInfo());

Tip: the boolean parameter in the importIntegration() method controls whenever the integration must be replaced or not. If that parameter is set to true, then it will override any existing integration that has the same name. Otherwise; if that parameter is set to false, then it will assume that the integration does not exist in ICS and it will create it.

Alternatively, you can import a complete set of integrations at once by importing a package:

Status status = token.importPackage("home/rferreira/ics/backup/samplePackage.par");
System.out.println(status.getStatusInfo());

Conclusion

ICS is a powerful iPaaS solution offered by Oracle that provides a robust set of management capabilities. Along with its development console, it also provides a set of REST APIs that enable the creation of custom apps that can fetch data from ICS. Although those REST APIs are useful, developers often need more productivity while writing their code. This blog introduced the Java API for ICS, a simple-to-use library that abstracts the technical details of the REST APIs. We provided details on how to download, configure, and use the library, and code samples were provided to demonstrate how to use the Java API to access a range of common ICS management functions.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha