/integration-sdk-java

Java framework for interacting with Ethos Integration.

Primary LanguageJavaApache License 2.0Apache-2.0

Ellucian Ethos Integration SDK

Ethos Integration SDK (EISDK) provides utilities and libraries that make it easier for developers to quickly start building Ethos-based integrations.

The EISDK for Java allows you to easily develop Java applications that integrate with Ellucian Ethos Integration. The SDK builds and executes HTTP requests and manages the responses. This allows your application to use the Java library methods to communicate with Ethos Integration, without the need to call the REST APIs directly.

The Ethos Integration SDK for Java simplifies use of Ethos Integration by providing a set of libraries that Java developers are familiar with. The Ethos Integration SDK makes the application development process less expensive and more efficient.

Table of contents

  1. Setup
  2. Quick Start
  3. Full API Doc
  4. Examples

Setup

This SDK is available for download from the Maven Central Repository.

The following is the Maven dependency for this SDK:

<dependency>
  <groupId>com.ellucian.ethos.integration.sdk</groupId>
  <artifactId>integration-sdk-java</artifactId>
  <version>1.0.0</version> <!-- Check the version and use the latest -->
</dependency>

Before using the SDK, you will need to download and install the following required software:

  • a Java Development Kit (minimum version 11)
  • Maven

You will need an API key from an Ethos Integration application. It is expected that the application that the API key belongs to is already configured properly in Ethos Integration. Please refer to Ellucian documentation for more information about how to get an API key and configure Ethos Integration applications.

We also recommend:

In general your choice of Java IDE will work fine as long as you can manage Maven dependencies with it.

For development of this SDK, we used Amazon Coretto JDK 11. See here for reasons why this was chosen.

If your development environment is on a unix-based platform, SDKMan can be a helpful tool to facilitate the required downloads needed for the Ethos SDK prerequisites, such as Java and Maven, although SDKMan is not required.

Quick Start

To make API requests against the Ethos Integration services, you will first need to create a client object. To create a client object, use the EthosClientBuilder, found in the com.ellucian.ethos.integration.client package. The types of clients that you can create are as follows:

  • EthosConfigurationClient - make requests for getting config data, such as /appConfig and /available-resources
  • EthosErrorsClient - perform create, read, and delete operations against the EI errors service
  • EthosMessagesClient - get messages from a subscriber queue
  • EthosProxyClient - perform CRUD operations for Ethos Data Models and other resources using the EI proxy API

To use the EthosClientBuilder, you will need to create a new instance of it, passing a valid Ethos Integration API key to the constructor. The API key is used to get an access token from Ethos Integration, allowing the client to authenticate to the EI services when making requests.

Here is a quick example of creating a proxy client and making a simple GET request for the 'courses' resource. See the examples section for more detailed code examples.

import com.ellucian.ethos.integration.client.EthosClientBuilder;
import com.ellucian.ethos.integration.client.EthosResponse;
import com.ellucian.ethos.integration.client.proxy.EthosProxyClient;

// Create Proxy Client
String apiKey = "11111111-1111-1111-1111-111111111111";
EthosProxyClient ethosProxyClient = new EthosClientBuilder(apiKey).buildEthosProxyClient();
EthosResponse response = ethosProxyClient.get("courses");

The EthosResponse object is returned from many of the methods in the proxy client. It holds information about the HTTP response, such as the content (response body), response headers, and status code. It also holds a requestedUrl property that can show you the URL that was built by the client and used to make the request.

There are overloaded methods in the EthosProxyClient that let you get the response as a String or as a com.fasterxml.jackson.databind.JsonNode object. These response types contain only the content portion of the EthosResponse.

// get as String
String response = ethosProxyClient.getAsString​("courses");

// get as JsonNode
JsonNode response = ethosProxyClient.getAsJsonNode("courses");

The Jackson Library is heavily used in this SDK to manage serializing and parsing JSON objects. The JsonNode objects make it easy to read the JSON properties of the responses. It provides a way to generically manage all the Ethos Data Models and other resource types that could be returned from Ethos Integration without having to create and manage POJO's for every possible one.

Here is an example of getting properties from a 'courseJson' response object that is a JsonNode representing the 'courses' Ethos Data Model.

// get the course description
String desc = courseJson.get("description").asText();

// get the course number
int num = courseJson.get("number").asInt();

// get the titles array and iterate over it
JsonNode titles = courseJson.get("titles");
Iterator<JsonNode> it = titles.iterator();
while (it.hasNext()) {
    JsonNode title = it.next();
    String titleValue = title.get("value").asText();
    // do other processing
}

The proxy client is different than the other clients because the response objects could be in any JSON format that the authoritative applications return. This is why it is necessary to handle the responses as Strings or generic JSON nodes.

The other clients, such as EthosMessagesClient and EthosErrorsClient, return more specialized objects since the responses have defined JSON schemas. They return EthosError and ChangeNotification objects. See the full API doc for more details.

Full API Documentation

The full EISDK JavaDoc is hosted on our Github pages site.

Examples

The following are code-snippet examples of how to use the Ethos Integration SDK for Java. For more in-depth examples please refer to the integration SDK Java example project in Github.

Making Requests to the Proxy API

Get a page of 'courses' resources using a specific version.

EthosProxyClient ethosProxyClient = new EthosClientBuilder(apiKey).buildEthosProxyClient();
EthosResponse response = ethosProxyClient.get("courses", "application/vnd.hedtech.integration.v16.1.0+json");

Get a page of 'persons' resources for a major version.

// get the full version header for v12 of 'persons'
EthosConfigurationClient configClient = new EthosClientBuilder(apiKey).buildEthosConfigurationClient();
String version = configClient.getVersionHeader​("persons", 12);

EthosResponse response = ethosProxyClient.get("persons", version);

Get a single 'employees' row using an ID.

EthosResponse response = ethosProxyClient.getById("employees", "11111111-1111-1111-1111-111111111111");

Create a new record with a POST request.

EthosResponse response = ethosProxyClient.post("colors", "{ \"id\":\"00000000-0000-0000-0000-000000000000\", \"name\": \"green\" }");

Update a record with a PUT request.

EthosResponse response = ethosProxyClient.put("colors", "11111111-1111-1111-1111-111111111111", "{ \"name\": \"forest green\" }");

Delete a record with a DELETE request.

ethosProxyClient.delete("colors", "11111111-1111-1111-1111-111111111111");

Make requests that use paging. This will handle sending multiple HTTP requests to get multiple pages of data with a single operation.
Use caution when trying to get all pages of a resource in a single request. Depending on the resource, this could cause a long running operation that will cause a timeout, or it could return a huge amount of data that could cause an out of memory error.

// get all the pages of data for the 'buildings' resource using the default page size
List<EthosResponse> ethosResponseList = ethosProxyClient.getAllPages( "buildings" );

// get the max page size for the 'persons' resource
int pageSize = ethosProxyClient.getMaxPageSize( "persons" );

// get 5 pages of persons data using the maximum allowed page size
// return the data as a list of JsonNodes
List<JsonNode> jsonNodeList = ethosProxyClient.getPagesAsJsonNodes( "persons", pageSize, 5 );

// get 2 pages of courses data starting from an offset of 100
// return the data as a list of Strings
List<String> stringList = ethosProxyClient.getPagesFromOffsetAsStrings( "courses", 100, 2 );

Making Asynchronous Requests to the Proxy API

It is also possible to get the pages of data with an asychronous request. These are all detailed in JavaDoc and also the examples package. In general, all methods for paging are available asynchronously by adding Async to the method name, and using EthosProxyClientAsync.

Data is then wrapped in a CompleteableFuture object, which is Java's version of a Promise (JavaScript's term) or Future (C#'s term).

EthosProxyClientAsync ethosProxyClient = new EthosClientBuilder(apiKey).buildEthosProxyClientAsync();
CompletableFuture<List<String>> asyncResponse = ethosProxyClient.getAllPagesFromOffsetAsStringsAsync(resourceName, offset);
// While the CompletableFuture thread is running, additional operations can be performed.  For the sake of
// demonstrating this we are just running a few printlns to print out the current time.
System.out.println(LocalDateTime.now());
try {
    Thread.sleep(250);
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println(LocalDateTime.now());
// using .join here so there is no exception thrown - all exceptions will be unchecked.  This is the
// same as in C# where the default is to use the async processing without checked exceptions.
List<String> stringList = asyncResponse.join();

Note that, due to CompletableFuture's limitations, it can only throw a CompletionException. This is a runtime Exception so catching it will wrap the actual exception.

Making Criteria Filter Requests to the Proxy API

Requests using criteria filters can be made using the EthosFilterQueryClient. SimpleCriteria can be built using the SimpleCriteria.Builder, from which a CriteriaFilter is built and used by the EthosFilterQueryClient. This is covered in the Javadoc and example code. Some knowledge of the desired criteria filter syntax is needed for use with the given Ethos resource. The following is a brief example code snippet.

String resource = "persons";
String yourAPIKey = "11111111-1111-1111-1111-111111111111";  // This is a dummy value, but would be your API key value. 
EthosFilterQueryClient ethosFilterQueryClient = new EthosClientBuilder(apiKey)
                                                .buildEthosFilterQueryClient();
CriteriaFilter criteriaFilter = new SimpleCriteria.Builder()
                                .withSimpleCriteriaArray("names", "firstName", "John")
                                .buildCriteriaFilter();
EthosFilterQueryClient ethosFilterQueryClient = getEthosFilterQueryClient();
try {
    // The criteriaFilter generates the following syntax when making the request using the ethosFilterQueryClient below: 
    // ?criteria={"names":[{"firstName":"John"}]}
    EthosResponse ethosResponse = ethosFilterQueryClient.getWithCriteriaFilter( resource, criteriaFilter );
    // Handle the response as desired...
}
catch( IOException ioe ) {
    ioe.printStackTrace();
}

Examples of using a named query filter and/or filter map are also available in the example code.

Consuming Subscriber Messages

Call the consume endpoint to get the default number of new messages from your application's subscriber queue. The messages are returned as ChangeNotification objects.

EthosMessagesClient messagesClient = new EthosClientBuilder(apiKey).buildMessagesClient();
List<ChangeNotification> cnList = messagesClient.consume();

Call the consume endpoint to get available messages from your application's subscriber queue, starting after message ID of '10'.

List<ChangeNotification> cnList = messagesClient.consumeFromId(10);

The '10' parameter sent to this method is used to send the lastProcessedID query parameter in the HTTP request to the /consume endpoint. This parameter can be used to indicate the ID of the last message that was successfully processed. It can be used to retrieve messages that have already been retrieved. The messages in the queue have sequential ID's, and the lastProcessedID parameter corresponds to the ID of a message in the queue. Here is an example of how lastProcessedID can be used. If the application consuming the messages retrieves messages 1-10, but only successfully processes messages 1-5, it can set the lastProcessedID parameter to 5 in the next invocation. That will give the application messages 6-10 again.

Check to see how many messages are available in your application's subscriber queue.

int numMessages = messagesClient.getNumAvailableMessages();

Automated Polling for Subscriber Messages

Setup automated polling for subscribing to ChangeNotification messages. The SDK can automatically provide ChangeNotification messages to a client application when the client application configures a notification poll service to subscribe to a client implementation of the appropriate abstract subscriber. As an example, the following shows a client application implementation of an abstract subscriber, which then receives notifications from the SDK in an automated polling fashion:

    // Client implementation of a change notification subscriber...
    public class MyEthosChangeNotificationSubscriber extends AbstractEthosChangeNotificationSubscriber {
        public MyEthosChangeNotificationSubscriber() {
            super();
        }
        public MyEthosChangeNotificationSubscriber( Integer numNotifications ) {
            this();
            this.numNotifications = numNotifications;
        }
        @Override
        public void onChangeNotification(ChangeNotification changeNotification) {
            // Code to handle the changeNotification here...
        }
        @Override
        public void onChangeNotificationError(Throwable throwable) {
            // Code to handle the error here...
        }
    }

Example of using the client application subscriber implementation above, to have it receive notifications. This code would reside in a client application that uses the SDK.

    // Specify the number of notifications to retrieve per poll attempt.  
    int numNotifications = 10;
    
    // The number of seconds to wait between poll attempts when retrieving notification messages.
    long pollingIntervalSeconds = 5;
    
    // Setup the change notification service with an apiKey, or could also use an EthosClientBuilder instead.    
    EthosChangeNotificationService cnService = new EthosChangeNotificationService.Builder(apiKey)
                                               .build();
    
    // Instantiate the publisher with the change notification service and the polling interval.
    EthosChangeNotificationPollService ethosChangeNotificationPollService = new EthosChangeNotificationPollService( cnService, pollingIntervalSeconds );
    
    // Instantiate the subscriber with the number of notifications to use per poll request.
    MyChangeNotificationSubscriber myChangeNotificationSubscriber = new MyChangeNotificationSubscriber( numNotifications );
    
    // Subscribe the client application subscriber implementation to the change notification publisher.  This will begin
    // the subscription process and the subscriber will start receiving messages.
    ethosChangeNotificationPollService.subscribe( myChangeNotificationSubscriber );

    // When ready to stop receiving notifications, just cancel the subscription.  No further notifications will be 
    // received after the current polling operation completes.
    if( myChangeNotificationSubscriber.isSubscriptionRunning() ) {
        myChangeNotificationSubscriber.cancelSubscription();
    }

Getting Configuration Info

Get the configuration information for the application to which the API key belongs.

EthosConfigurationClient configClient = new EthosClientBuilder(apiKey).buildEthosConfigurationClient();

// get app configuration as a String
String appConfig = configClient.getAppConfig();

// get app configuration as a JsonNode
JsonNode appConfig = configClient.getAppConfigJson();

Get the list of available resources from the authoritative applications in your tenant. This calls the /available-resources endpoint of Ethos Integration, and returns that data in a String or JsonNode format.

// get as String
String availableResources = configClient.getAllAvailableResources();

// get as JsonNode
JsonNode availableResources = configClient.getAllAvailableResourcesAsJson();

There is also an option to get the available resources data that only pertains to your application. If your application has credentials configured to call one or more authoritative application API's, then it will have an ownerOverrides array defined in the app config. This ownerOverrides array determines which authoritative app will serve requests for different resources. When you get the available resource data specific to your application, the response will be limited to resources and authoritative apps in your application's ownerOverrides config.

// get as String
String availableResources = configClient.getAvailableResourcesForApp();

// get as JsonNode
JsonNode availableResources = configClient.getAvailableResourcesForAppAsJson();

Managing Ethos Errors

Create an error in the Ethos Integration errors service.

EthosErrorsClient errorsClient = new EthosClientBuilder(apiKey).buildEthosErrorsClient();

// create an EthosError object from a JSON string
String json = "{" +
              "    \"id\": \"00000000-0000-0000-0000-000000000000\"," +
              "    \"dateTime\": \"2020-10-27T03:10:44.827Z\"," +
              "    \"severity\": \"error\"," +
              "    \"responseCode\": 500," +
              "    \"description\": \"Internal Server Error\"," +
              "    \"details\": \"This is a more info on the info error\"," +
              "    \"applicationId\": \"00000000-0000-0000-0000-000000000000\"," +
              "    \"applicationName\": \"Banner\"," +
              "    \"correlationId\": \"2468UserMade3242134\"," +
              "    \"resource\": {" +
              "        \"id\": \"00000000-0000-0000-0000-000000000000\"," +
              "        \"name\": \"persons\"" +
              "     }," +
              "    \"applicationSubtype\": \"EMA\"" +
              "}";
EthosError error = ErrorFactory.createErrorFromJson(json);

// post to errors service
EthosResponse response = errorsClient.post(error);

Get a single page of errors for your tenant from the errors service.

EthosResponse response = errorsClient.get();

Get an initial page of errors for your tenant from the errors service as a list of EthosError objects.

List<EthosError> ethosErrorList = errorsClient.getAsEthosErrors();

Getting Data in a Banner MEP Tenant Environment

An overview of Banner MEP and instructions on how to configure an Ethos tenant for Banner MEP is outside of the scope of this documentation. This will outline how to use API keys
from the different applications to pull data for the different VPDI codes.

When an Ethos tenant environment is configured for a Banner MEP institution, it will have multiple Banner applications setup that point to the same
Banner implementation, but with different URI's to pull data for different VPDI codes. There will also be separate client or subscribing applications
setup to make proxy requests and receive change-notifications from the different Banner apps.

In this code example, let's assume that I am working with a tenant environment that has Banner applications setup for 3 VPDI codes representing 3 different campuses of an institution:

  • NORTH
  • SOUTH
  • MAIN

Likewise, there will be 3 client applications that are used to get data from the 3 different Banner campuses.

// API keys for my 3 client apps  
String northKey = "11111111-1111-1111-1111-111111111111";  
String southKey = "22222222-2222-2222-2222-222222222222";  
String mainKey  = "33333333-3333-3333-3333-333333333333";  
  
// get 'students' data through the proxy api for NORTH campus  
EthosProxyClient northProxyClient = new EthosClientBuilder(northKey).buildEthosProxyClient();  
EthosResponse response = northProxyClient.get("students");  
  
// get change-notifications from the messages service for SOUTH campus  
EthosMessagesClient southMessagesClient = new EthosClientBuilder(southKey).buildMessagesClient();  
List<ChangeNotification> cnList = southMessagesClient.consume();  
  
// get data through the proxy and get change-notifications for the MAIN campus  
EthosClientBuilder mainClientBuilder = new EthosClientBuilder(mainKey);  
// proxy  
EthosProxyClient mainProxyClient = mainClientBuilder.buildEthosProxyClient();  
EthosResponse response = mainProxyClient.get("students");  
// messages  
EthosMessagesClient mainMessagesClient = mainClientBuilder.buildMessagesClient();  
List<ChangeNotification> cnList = mainMessagesClient.consume();  

Using the EISDK Generated Strongly Typed Object Library

The EISDK Java object library provides request/response objects that can be used with the EISDK when making requests. This enables developers to work with Java objects rather than JSON data or JsonNode.

Use the EISDK Java object library to get an API resource:

String guid = "11111111-1111-1111-1111-111111111111";
EthosResponse<StudentCohorts> ethosResponse = ethosProxyClient.getById("student-cohorts", guid, StudentCohorts.class);
StudentCohorts studentCohorts = ethosResponse.getContentAsType();
// Use getter methods to access properties on studentCohorts...
System.out.println( "Title: " + studenCohorts.getTitle() );
System.out.println( "Code: " + studenCohorts.getCode() );

Get a page of data using the EISDK Java object library:

// Specify the JavaBean class for the resource
EthosResponse<List<StudentCohorts>> ethosResponse = ethosProxyClient.get( "student-cohorts", StudentCohorts.class );
// Get a list of StudentCohorts JavaBeans from the response.
List<StudentCohorts> studentCohortsList = ethosResponse.getContentAsType();
System.out.println( "******* doGetResourceAsJavaBeanExample() *******" );
System.out.println(String.format("Get data for resource: %s", resourceName));
System.out.println("getAsJavaBean() PAGE SIZE: " + studentCohortsList.size());
for( StudentCohorts studentCohorts : studentCohortsList ) {
    // We can more easily access the properties with getter methods on the StudentCohorts JavaBean, but to
    // see the content just output toString().
    System.out.println("getAsJavaBean() RESPONSE: " + studentCohorts.toString() );
}

See the EISDK Java object library for more info.

See the EISDK Java object library Javadoc to access the Javadoc pages.

QAPI Support in the EISDK for Java

Executing queries by QAPI requests is also supported.

// Use a generated object for the QAPI request body.
Persons persons = new Persons();
Name name = new Name();
name.setFirstName( "John" );
name.setLastName( "Smith" );
List<Name> nameList = new ArrayList<>();
nameList.add( name );
persons.setNames( nameList );
// Make the QAPI request through the ethosFilterQueryClient.
EthosResponse ethosResponse = ethosFilterQueryClient.getWithQAPI( resource, persons );
JsonNode responseNode = ethosResponseConverter.toJsonNode( ethosResponse );
System.out.println( "Number of resources returned: " + responseNode.size() );

Examples Project

More examples can be found in the EISDK Java examples project.