Share This:

This article follows up on a previous article where we looked at setting up the API to integrate DWP Catalog with remote servers. We looked at the connector description and the various calls that need to be defined. If you followed along you hopefully ended up with a working interface.

 

But that’s all it is for now: an interface. A lot of the values we’re returning are hardcoded and it doesn’t do anything at the moment. What I want to do next is explain how to build a full integration. We’ll use the same interface, so if you haven’t already done so, make sure to read my first blog article.

 

What are we going to build? It can’t be too complicated, so what I propose building is a simple ping activity. The basic idea is that you can invoke the action to check if a server is online. It will send out a ping request and report back if the server can be reached or not. You could use this in your workflow to check if a server can be reached, and depending on the outcome you can engage a specific team or escalate it further. We’re going to output a Boolean so that will work nicely with Exclusive Gateways.

 

Just to remind ourselves, this is how the integration works:

 

 

What we are interested in is the connector logic. Our action will return a Boolean indicating if the machine is alive or not. Using the same overview, these are the relevant components:

 

 

Notice I’m not going to an external server, I’m just executing code to do the ping which is all Java. Let’s first write a simple Java class, just so we know what the code looks like and how it works. This is what I came up with:

 

package pingservicetest;

import java.io.IOException;
import java.net.InetAddress;


public class PingServiceTest {

  public static boolean isMachineAlive (String machineName, int machinePort) {
    try {
      InetAddress inet;
      inet = InetAddress.getByName(machineName);
      return inet.isReachable(500);
    } catch (java.net.UnknownHostException e) {
    } catch (IOException e) {
    }  
        
    if (machinePort == 0) {
      machinePort = 111;
    }        
        
    try (Socket s = new Socket(machineName, machinePort)) {
      return true;
    } catch (IOException ex) {
    }
    return false;
  }


  public static void main(String[] args) {
    System.out.println(isMachineAlive("clm-aus-01234"));
  }
}

 

I want to check if servers are available or not, so I need to execute some form of ping command to confirm that they're alive. There's no TCP ping command in Java, but I can just use InetAddress. If I don’t get a response I try an additional Socket call. If I can get a successful connection I return true, if not I return false. I included the example at the end of this article, which you can run if you want to. It’s nothing fancy but it’s a good example of the way you can extend Catalog’s functionality.

 

I don’t like to put everything in one big file, so to make it manageable (and mirror the original diagram) I’m splitting this in two classes:

 

  • RCFController handles the interface. Its primary role is to accept HTTP requests from Catalog and respond with the correct JSON code.
  • RCFLogic is new, this is the class containing the code which does the actual processing. In our case that’s the isMachineAlive method.

 

 

Let’s start with RCFLogic. We already wrote and tested our code so we just need to define the class:

 

package rcf;

import java.io.IOException;
import java.net.*;

public class RCFLogic {

  public static boolean isMachineAlive(String machineName, int machinePort) {
         …
  }
}

 

Nothing new there, it’s a typical Java class, no references to Spring or Catalog. All of this is separate, but needs to be referenced properly. We need to know what the service accepts, what goes out and what format this is in. The interface we used in the first article can stay largely unchanged but I need to add the Port as an input and return a Boolean instead of a String. Here’s the action part of descriptor:

 

"name": "isMachineAlive",
"displayName": "isMachineAlive",
"path": "isMachineAlive",
"inputs": [
  {
    "name": "machineName",
    "type": "String",
    "required": true
  }
  {
    "name": "tcpPort",
    "type": "Integer",
    "required": false
  }
],
"outputs": [
  {
    "name": "Result",
     "type": "Boolean"
  }
]

 

I accept machineName and tcpPort and I return a Boolean called Result. I use the same code based on org.json as last time. Based on this I know I get this HTTP request in from Catalog:

 

POST http://server:8080/jbconnectivity/pingMachine HTTP/1.1

{
  "inputs": {
    "machinePort": null,
    "machineName": "clm-test-12345"
  },
  "connectionInstanceId": "jbconnectivity-1"
}

 

The request is generated by Catalog, but it bases this on the definition which I supplied and uses the values set during workflow creation. I write my code in the controller to handle this. I also know what the HTTP response should be:

 

HTTP/1.1 200

{
  "outputs":
  {
    "result":true
  }
}

 

With some help from org.json and Spring this is the code I came up with:

 

@RequestMapping(value = "/jbconnectivity/pingMachine", method = RequestMethod.POST)
@ResponseBody
public String checkPing(@RequestBody String payload) {
  JSONObject jsonPayload = new JSONObject(payload);
  String machineName = jsonPayload.getJSONObject("inputs").getString("machineName");
  int machinePort = 0;

  try {
    machinePort = jsonPayload.getJSONObject("inputs").getInt("machinePort");
  } catch (JSONException e) {}

  JSONObject jsonInputs = new JSONObject();
  jsonInputs.put("result", RCFLogic.isMachineAlive(machineName, machinePort));
  JSONObject jsonPing = new JSONObject();
  jsonPing.put("outputs", jsonInputs);


  return jsonPing.toString();
}

 

I first accept the payload from the POST request which I convert into a JSON object (jsonPayload). I then extract the machine name and the port (the try/catch clause is just to deal with the null value). Once I have all the values I create the JSON I want to respond with (jsonPing and jsonInputs). The point where I call my method in RCFLogic is line 13.

 

That’s all I’m going to do. Because I don’t connect to an external system, I don’t have to do any health checks, so I’m just going to keep the hardcoded values for checkHealth. Sure, there are things that could be improved, I’ve done some housekeeping in the actual example which I’ve attached at the end of the article, but I hope you get the principle.

Okay, let’s give it a go! I’m keeping the workflow as simple as possible, no fancy conditions, just two questions and one activity.

 

 

Curious if it’s going to work? Let’s log into DWP and create a new service request:

 

 

Because my workflow doesn’t actually create any requests in a backend system, I’m just going to have a look at the Service Requests report on the Catalog side:

And lo and behold, it works! Catalog executed the action, sent a POST request to the API as per the definition. My code picked up the POST request and called the isMachineAlive method in the RCFLogic class. And that was all passed back to DWP.

 

I know, this is fairly basic but I hope you agree that it works quite well. We’re separating Catalog from the external integration by using an API which adheres to strict standards. As long as I make sure I define the interface correctly, it’s up to me to respond to the incoming HTTP requests. It doesn’t really matter what you do in the backend to process the request. It can be as simple as extending the functionality by adding a few custom actions to calculate a week number based on a date, or it can be as complicated as integrating using SOAP-based web services. But keep in mind that this doesn't allow you to interact with DWP, you can't write a service which pushes values to DWP directly, it's all in the background. But it’s up to you and I look forward to seeing what you will come up with. Any questions or feedback? Leave a comment below.

 

Best wishes,

Justin