Microservice using PSDK

Now you need to build a Java Microservice for CTI session management using the PSDK provided by Genesys.

Starting the microservice

To start the microservice, you must have the following:
  • Java 21
  • Maven
After downloading the code, follow these steps:
  1. Open the project root folder in your terminal.
  2. Run the following commands:
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/voiceprotocol.jar -DgroupId=com.genesyslab.platform -DartifactId=voiceprotocol -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/commons.jar -DgroupId=com.genesyslab.platform -DartifactId=commons -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/protocol.jar -DgroupId=com.genesyslab.platform -DartifactId=protocol -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/connection.jar -DgroupId=com.genesyslab.platform -DartifactId=connection -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/kvlists.jar -DgroupId=com.genesyslab.platform -DartifactId=kvlists -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-transport.jar -DgroupId=io.netty -DartifactId=netty-transport -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-buffer.jar -DgroupId=io.netty -DartifactId=netty-buffer -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-codec-http.jar -DgroupId=io.netty -DartifactId=netty-codec-http -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-codec-socks.jar -DgroupId=io.netty -DartifactId=netty-codec-socks -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-codec.jar -DgroupId=io.netty -DartifactId=netty-codec -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-common.jar -DgroupId=io.netty -DartifactId=netty-common -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-handler-proxy.jar -DgroupId=io.netty -DartifactId=netty-handler-proxy -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-handler.jar -DgroupId=io.netty -DartifactId=netty-handler -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-resolver.jar -DgroupId=io.netty -DartifactId=netty-resolver -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/netty-transport-native-unix-common.jar -DgroupId=io.netty -DartifactId=netty-transport-native-unix-common -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/connection.jar -DgroupId=com.genesyslab.platform -DartifactId=connection -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/commons.jar -DgroupId=com.genesyslab.platform -DartifactId=commons -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/voiceprotocol.jar -DgroupId=com.genesyslab.platform -DartifactId=voiceprotocol -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/protocol.jar -DgroupId=com.genesyslab.platform -DartifactId=protocol -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn install:install-file -Dfile=./external/com/gensyslab/platform/kvlists.jar -DgroupId=com.genesyslab.platform -DartifactId=kvlists -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true
    mvn clean package
  3. The command will generate a jar file in the target folder.
  4. Run the jar file using the following command:
    java -jar target/genesys-service.jar

Concepts

The Java Microservice for CTI session management acts as a bridge between the Genesys service provider and your media toolbar application. Events from Genesys are listened to through the PSDK APIs and your media toolbar application is notified through a web socket. Similarly, operations from your media toolbar application are passed on to Genesys through this microservice.

Message Structure

Once your microservice receives events from your Genesys service, the microservice sends it to your media toolbar application through a web socket. The following example shows the structure of the message which is passed from the microservice to your media toolbar application:

public class EventData {
    String eventName;
    long connectionId;
    String ANI;
    String direction;
    String rep_score;
    String eventId;
    String sessionId;
}

The following table shows the description of the message properties:

SI Number Property Name Description
1 eventname Name of the event which is fired from Genesys. It can be EventRegistered, EventRinging, EventEstablished, EventReleased as shown in table which follows.
2 connectionId Connection ID of the call.
3 ANI Phone number associated with the call.
4 direction Direction of the call such as Inbound, Outbound, and so on.
5 eventId Event ID of the call.
6 sessionId ID of the current session.

See the Genesys documentation for a list of Genysys-supported events.

The following table shows the mapping between the PSDK events and the events fired from the microservice:

SI Number Event Name Description
1 EventRegistered Agent sign in has completed and the agent is ready to receive calls.
2 EventRinging Incoming call notification
3 EventEstablished Call accepted notification.
4 EventReleased Call ended notification.

Code Samples

All functions shown in the following examples are defined in src/main/java/com/oracle/genesys/handler/GenesysHandler.java in the shared project.

Initializing the Channel code sample

The following example shows how to initialize the channel of your Genesys service:

private void initChannel() {
        PropertyConfiguration options = new PropertyConfiguration();
        options.setUseAddp(true);
        options.setAddpClientTimeout(3);
        options.setAddpServerTimeout(4);
        options.setAddpTraceMode(ClientADDPOptions.AddpTraceMode.Local);
        channel = new TServerProtocol(new Endpoint("PSDK-Sample-App", "10.138.194.168", 8080, options));
        ChannelEventsListener channelListener = new ChannelEventsListener();
        channel.addChannelListener(channelListener);
        channel.setMessageHandler(new ReceivedMessageHandler(this));
        channel.setInvoker(new SwingInvoker());
        if (channel.getState() != ChannelState.Closed) {
            return;
        }
        channel.setClientName("test");
        channel.setClientPassword("");
        System.out.println("Connecting...");
    }

Request Register Address code sample

The following shows how to register your Genesys service:

private void requestRegisterAddress() {
        RequestRegisterAddress request = RequestRegisterAddress.create(this.DN,
                RegisterMode.ModeShare, ControlMode.RegisterDefault, AddressType.DN);
        try {
            channel.requestAsync(request, this, new CompletionHandler<Message, Object>() {
                public void completed(Message message, Object obj) {
                    System.out.println("Received: \n" + message.toString());
                    if (EventRegistered.ID == message.messageId()) {
                        EventRegistered eventRegistered = (EventRegistered) message;
                        System.out.println("####" + eventRegistered.getThisDN());
                        EventData data = new EventData();
                        data.eventName = message.messageName();
                        GenesysHandler.setAniAndScore(data, eventRegistered.getThisDN());
                        WebHookHandler.sendResponse(data);
                        requestAgentLogin();
                    } else {
                        System.out.println("\n Can't register.");
                    }
                }
                public void failed(Throwable arg0, Object obj) {
                    System.out.println(arg0.getMessage());
                }
            });
        } catch (ChannelClosedOnSendException closedEx) {
            System.out.println("Channel should be opened before sending request");
            System.out.println(closedEx.getMessage());
        } catch (Throwable e) {
            System.out.println(e.getMessage());
        }
    }

Request Agent Login code sample

The following shows how to request agent sign in to your Genesys service:

private void requestAgentLogin() {
        RequestAgentLogin requestAgentLogin = RequestAgentLogin.create(this.DN, AgentWorkMode.AutoIn, "1010", this.DN, null, null, null);
        try {
            channel.requestAsync(requestAgentLogin, this, new CompletionHandler<Message, Object>() {
                public void completed(Message message, Object obj) {
                    System.out.println("Received: \n" + message.toString());
                    if (EventAgentLogin.ID == message.messageId()) {
                        System.out.println("login");
                    }
                    else {
                        System.out.println("\n Can't login.");
                    }
                }
                public void failed(Throwable arg0, Object obj) {
                    arg0.printStackTrace();
                }
            });
        } catch (ChannelClosedOnSendException closedEx) {
            System.out.println("Channel should be opened before sending request");
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

Request Answer Call

The following shows how to request your Genesys service to answer a call:

public void acceptCall(String connectionId) {
        RequestAnswerCall requestAnswerCall =
                RequestAnswerCall.create(this.DN, eventRingingSaved.getConnID());
        try {
            Message response = channel.request(requestAnswerCall);
            System.out.println(response.toString());
        } catch (ProtocolException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

Request Release Call

The following shows how to request your Genesys service to disconnect a call:

public void rejectCall(String connectionId) {
        RequestReleaseCall requestReleaseCall =
                RequestReleaseCall.create(this.DN, eventRingingSaved.getConnID());
        try {
            Message response = channel.request(requestReleaseCall);
            System.out.println(response.toString());
        } catch (ProtocolException e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        }
    }

Define ReceivedMessageHandler class

While initializing the channel, you have the line : channel.setMessageHandler(new ReceivedMessageHandler(this)); added in your initChannel function. This call is responsible for handling the events fired from your Genesys service.

The ReceivedMessageHandler class is defined as follows:

package com.oracle.genesys.handler;
 
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.genesyslab.platform.commons.protocol.Message;
import com.genesyslab.platform.commons.protocol.MessageHandler;
import com.genesyslab.platform.voice.protocol.tserver.events.EventAbandoned;
import com.genesyslab.platform.voice.protocol.tserver.events.EventAgentLogin;
import com.genesyslab.platform.voice.protocol.tserver.events.EventAgentReady;
import com.genesyslab.platform.voice.protocol.tserver.events.EventDialing;
import com.genesyslab.platform.voice.protocol.tserver.events.EventEstablished;
import com.genesyslab.platform.voice.protocol.tserver.events.EventLinkConnected;
import com.genesyslab.platform.voice.protocol.tserver.events.EventNetworkReached;
import com.genesyslab.platform.voice.protocol.tserver.events.EventRegistered;
import com.genesyslab.platform.voice.protocol.tserver.events.EventReleased;
import com.genesyslab.platform.voice.protocol.tserver.events.EventRinging;
import com.oracle.genesys.SessionHanlder;
import com.oracle.genesys.model.EventData;
 
import java.io.IOException;
 
public class ReceivedMessageHandler implements MessageHandler {
    private final GenesysHandler genesysHandler;
 
    public ReceivedMessageHandler(GenesysHandler genesysHandler) {
        this.genesysHandler = genesysHandler;
    }
    public void onMessage(Message message) {
        System.out.println("Unsolicited event: \n" + message.toString());
        EventData data = new EventData();
        data.eventName = message.messageName();
        data.sessionId = this.genesysHandler.sessionId;
        String tempAni;
        switch (message.messageId()) {
            case EventLinkConnected.ID:
            case EventAgentLogin.ID:
                break;
            case EventRegistered.ID:
                break;
            case EventAgentReady.ID:
                break;
            case EventRinging.ID:
                EventRinging eventRinging = (EventRinging) message;
                data.eventId = eventRinging.getCallUuid().toLowerCase();
                tempAni = eventRinging.getANI() != null ? eventRinging.getANI() : eventRinging.getOtherDN();
                GenesysHandler.setAniAndScore(data, tempAni);
                data.direction = eventRinging.getCallType().toString();
                data.connectionId = eventRinging.getConnID().toLong();
                genesysHandler.eventRingingSaved = eventRinging;
                break;
            case EventEstablished.ID:
                EventEstablished eventEstablished = (EventEstablished) message;
                data.eventId = eventEstablished.getCallUuid().toLowerCase();
                tempAni = eventEstablished.getANI() != null ? eventEstablished.getANI() : eventEstablished.getOtherDN();
                GenesysHandler.setAniAndScore(data, tempAni);
                data.direction = eventEstablished.getCallType().toString();
                data.connectionId = eventEstablished.getConnID().toLong();
                break;
            case EventReleased.ID:
                EventReleased eventReleased = (EventReleased) message;
                data.eventId = eventReleased.getCallUuid().toLowerCase();
                tempAni = eventReleased.getANI() != null ? eventReleased.getANI() : eventReleased.getOtherDN();
                GenesysHandler.setAniAndScore(data, tempAni);
                data.direction = eventReleased.getCallType().toString();
                data.connectionId = eventReleased.getConnID().toLong();
                break;
            case EventDialing.ID:
                EventDialing eventDialing = (EventDialing) message;
                data.eventId = eventDialing.getCallUuid().toLowerCase();
                tempAni = eventDialing.getANI() != null ? eventDialing.getANI() : eventDialing.getOtherDN();
                GenesysHandler.setAniAndScore(data, tempAni);
                data.direction = eventDialing.getCallType().toString();
                data.connectionId = eventDialing.getConnID().toLong();
                break;
            case EventNetworkReached.ID:
                EventNetworkReached eventNetworkReached = (EventNetworkReached) message;
                data.eventId = eventNetworkReached.getCallUuid().toLowerCase();
                tempAni = eventNetworkReached.getANI() != null ? eventNetworkReached.getANI() : eventNetworkReached.getOtherDN();
                GenesysHandler.setAniAndScore(data, tempAni);
                data.direction = eventNetworkReached.getCallType().toString();
                data.connectionId = eventNetworkReached.getConnID().toLong();
                break;
            case EventAbandoned.ID:
                EventAbandoned eventAbandoned = (EventAbandoned) message;
                data.eventId = eventAbandoned.getCallUuid().toLowerCase();
                tempAni = eventAbandoned.getANI() != null ? eventAbandoned.getANI() : eventAbandoned.getOtherDN();
                GenesysHandler.setAniAndScore(data, tempAni);
                data.direction = eventAbandoned.getCallType().toString();
                data.connectionId = eventAbandoned.getConnID().toLong();
                break;
        }
        WebHookHandler.sendResponse(data);
    }
}

Events fired from your Genesys service are received by the onMessage function. The event payload is mapped to a common message structure as defined here and the payload is send to a web socket. From your media toolbar application you can listen to the messages from this web socket.