Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Anuj07
Employee
Employee

In the Part 4 of this blog series you showed user’s achievements in the profile page. In this blog post you will show notifications from the game.



It is important to provide immediate feedback on achievements to the users. Here you will use pop-up messages to notify the users about Experience Points assigned to him for creating issues.



In order to implement this, first you will retrieve notifications using gamification service API and then you will show the relevant notification by creating a pop-up message.

 

1) Retrieve notifications:

 

1. Replace the code in the file GamificationProxy.java located at package com.sap.gamification.plugins.servlet with code GamificationProxy.txt .
package com.sap.gamification.plugins;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.HttpClients;

/**
* This is the proxy class for calling Gamification Service APIs.
*
*/
public class GamificationProxy {
private static String SCHEME = "https";
private static String PATH = "/gamification/api/tech/JsonRPC";
public static final String GAMIFICATION_SERVICE_APPNAME = "JIRA";

/**
* This is used for sending gamification event to the Gamification Service.
*
* @param playerId
* @param priority
* @return
* @throws URISyntaxException
* @throws ClientProtocolException
* @throws IOException
*/

public Integer sendEvent(String playerId, String priority,
String eventName) throws URISyntaxException,
ClientProtocolException, IOException {
URIBuilder builder = new URIBuilder();
String value = "{" + "\"method\":\"" + "handleEvent" + "\","
+ "\"params\":[" + "{" + "\"type\":\"" + eventName
+ "\"," + "\"playerid\":\"" + playerId
+ "\"," + "\"data\":{" + "\"relevance\":\""
+ priority + "\"" + "}" + "}" + "]" + "}";
builder.setScheme(SCHEME)
.setHost(EnvironmentUtility.host)
.setPath(PATH)
.setParameter(
"json",
value)
.setParameter("app", GAMIFICATION_SERVICE_APPNAME);
URI url = builder.build();
HttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost(url);
post.setHeader(
"Authorization",
getBase64Auth(EnvironmentUtility.technicalUserName,
EnvironmentUtility.technicalUserPassword));
// If you are running this behind behind some corporate network fire
// wall the you need to set the proxy
if (EnvironmentUtility.proxy != null
&& !EnvironmentUtility.proxy.equalsIgnoreCase("")) {
setHttpHostProxy(post);
}
HttpResponse doPostResponse = client.execute(post);
return Integer.valueOf(doPostResponse.getStatusLine().getStatusCode());
}

private static void setHttpHostProxy(HttpRequestBase request) {
HttpHost httpProxy = new HttpHost(EnvironmentUtility.proxy,
Integer.parseInt(EnvironmentUtility.port), "http");
RequestConfig config = RequestConfig.custom().setProxy(httpProxy)
.build();
request.setConfig(config);
}

private static String getBase64Auth(String login, String pass) {
String source = login + ":" + pass;
String ret = "Basic " + Base64.encodeBase64String(source.getBytes());
return ret;
}

public static void main(String arg[]) throws Exception{
// arg[0] - player Id
// arg[1] – priority of the issue created
EnvironmentUtility.readEnvironmentValues();
GamificationProxy gamificationProxy=new GamificationProxy();
String eventName="issueCreated";
gamificationProxy.sendEvent(arg[0], arg[1], eventName);
}

}

 

 

 Copy-and-paste the contents to the file GamificationProxy.java.


The class GamificationProxy


The class GamificationProxy has a method getPlayerNotifications() which uses Technical Endpoint to retrieve notifications by invoking gamification service method getNotificationsForPlayer(). The HTTP POST request will look like the following:


 


https://<gamification service host>/gamification/api/tech/JsonRPC?json={"method":"getNotificationsForPlayer",params":["JIRA_USER@mail.com",1442061177178]}&app=JIRA


 

 
















Query parameter



Value



json



method getNotificationsForPlayer() and parameters (retrieves notifications for given player which have been created after the provided timestamp)



app



JIRA (name of the app which contains the game mechanics as defined in the gamification workbench)



 
















Input parameter



Description



JIRA_USER



Player name/Player email id



1442061177178



Timestamp (to retrieve notifications created just after this)



 

The class Gamification Proxy has another method getServerTime() which uses Technical Endpoint to retrieve current server time by invoking gamification method getCurrentServerTime(). The HTTP POST request will look like the following:



https://<gamification service host>/gamification/api/tech/JsonRPC?


json= {"method":"getCurrentServerTime","params":[ ]} &app=JIRA





















Query parameter



Value



json



method getCurrentServerTime() and parameters (retrieves the current server time )



app



JIRA (name of the app which contains the game mechanics as defined in the gamification workbench)



 

Test the class GamificationProxy: 


 

The class GamificationProxy defines a method main() to test retrieving notifications using gamification service API.



public static void main(String arg[]) throws Exception{


   // arg[0] - player id


   //reading Environments values


   EnvironmentUtility.readEnvironmentValues();


   GamificationProxy gamificationProxy= new GamificationProxy();


   // Step 1: Getting the server time


   String serverTimeResp=gamificationProxy.getSeverTime();


   String serverTime = serverTimeResp.split(",")[0].split(":")[1];


   System.out.println("Server Time "+ serverTime);


   // Step 2: Sending ‘issueCreated’ event to the gamification service    


   String eventName="issueCreated";


   gamificationProxy.sendEvent(arg[0], "Major", eventName);


   //Step 3: Retrieving notifications created after the provided server time


   String notifications = gamificationProxy. getPlayerNotifications (


   arg[0],serverTime);


   System.out.print(notifications);


}



1. Run the configuration (which you created in the previous blog) to execute the class GamificationProxy. As a result following output will be displayed in console

 

Server Time 1442061177178


{"result":[{"id":672384,"message":"Ticket created","category":"POINT","type":"ADD","subject":"Experience Points","detail":"2","dateCreated":1442061178360}],"error":null,"type":null}


 

Now let’s see how this was achieved. In step 1 server time is calculated and in step 2 gamification relevant event issueCreated is sent. Step 3 retrieves the notifications created after the provided server time and in the current case only one event is sent which means only one notification is created.


 

 

Create Rest service for notifications


 

1. Add the following lines of code to the method doGet() of class UserAchievementsServlet.


if (request.getPathInfo().equalsIgnoreCase("/servertime")) {


      String serverTime = null;


      try {


              serverTime = gamificationProxy.getSeverTime();


      }  catch (Exception e) {


                log.error(" Error during accessing server time", e.getMessage());


      }


      log.info("Server time response", serverTime);


      response.getWriter().println(serverTime);


}


else if (request.getPathInfo().equalsIgnoreCase("/notifications")) {


      String serverTime = request.getParameter("serverTime");


      String playerNotifications = null;


        try {


                  playerNotifications=gamificationProxy.getPlayerNotifications(playerName,serverTime);


          } catch (Exception e) {


                  log.error(" Error during accessing player notifications",e.getMessage());


        }


      log.info("Player's notification response", playerNotifications);


      response.getWriter().println(playerNotifications);


}



The doGet() method should look like the following:



2.) Show notification:

To show notification, you need to create a JavaScript file and embed it in JIRA pages.

 

1. Create a folder with name widgets in folder /src/main/resources as shown in the screenshot below



 

2. Create a file with name sap_gs_notifications.js and place it at folder location /src/main/resources/widgets. Substitute the code from sap_gs_notifications.txt. 
var GSNotifications = (function() {
var _interval; // holds the interval
var _config = { // configurations at runtime
gamificationServerTimePath : "/jira/plugins/servlet/gamification/servertime",
gamificationNotificationsPath : "/jira/plugins/servlet/gamification/notifications",
interval : 2000,
currentServerTime : "",
};
var _notifications = {
toBeDisplayed : [],
};
function _init() {
_getCurrentServerTime();
clearInterval(_interval);
_interval = setInterval(_poll, _config.interval);
console.log("[GamificationService] Notification module loaded");
}
function _poll() {
_getNotificationsForPlayer(function(data) {
if (data !== null) {
if (data.result.length > 0) {
for (var i = 0; i < data.result.length; i++) {
_notifications.toBeDisplayed.push(data.result[i]);
}
_prepareAndInjectNotifications();
} else {
console.log("[GamificationService] No new notifications available.");
}

} else {
console.log("[GamificationService] Server Error: "+ data.error);
}
});
_getCurrentServerTime();
}
function _prepareAndInjectNotifications() {
var limit = _notifications.toBeDisplayed.length;
var message = "";
for (var i = 0; i < limit; i++) {
var n = _notifications.toBeDisplayed[i];
message = "";
switch (n.category) {
case "POINT":
message += "+" + n.detail + " " + n.subject;
break;
default:
break;
}
if (n !== undefined) {
JIRA.Messages.showSuccessMsg(message);
}
}
_notifications.toBeDisplayed.length = 0;
}
function _getCurrentServerTime() {
AJS.$.get(_config.gamificationServerTimePath,
function(response, status) {
if (status === "success") {
var serverTimeRespose = JSON.parse(response);
_config.currentServerTime = serverTimeRespose.result;
console.log("[Gamification Service] Current server time: "+ _config.currentServerTime);
}
});
}
function _getNotificationsForPlayer(fnSuccessCallback) {
AJS.$.get(_config.gamificationNotificationsPath, {
"serverTime" : _config.currentServerTime
}, function(response, status) {
if (status === "success") {
console.log("[GamificationService Notifications]" + response);
var data = JSON.parse(response);
fnSuccessCallback(data);
} else {
console.log("[GamificationService] Server Error on request.");
}

});
}
return {
init : _init, // setup for first start
};
}());
AJS.toInit(function() {
if (AJS.params.loggedInUser !== '') {
GSNotifications.init();
}
});

Copy-and-paste the contents to the file sap_gs_notifications.js.


The web resource Plugin Module:


 


The web resource Plugin Module allows JIRA plugins to define downloadable resources. If your plugin requires the application to serve additional static Javascript or CSS files, you will need to use downloadable web resources to make them available.


 


In the current case, JavaScript file sap_gs_notifications.js will be used as downloadable web resource to shows notification exactly the time when an issue is created in the JIRA. Now let’s understand how it works?


 


The file sap_gs_notifications.js has functions _getNotificationsForPlayer() and _getCurrentServerTime() which retrieves notifications and server time by making Ajax calls to the REST service.


The function _poll() schedule the repeating execution of these functions to continually check whether any gamification relevant event has occurred for which there is a notification to the user. If there are notifications they will be shown on the screen using the function _prepareAndInjectNotifications().


 


_prepareAndInjectNotifications() uses following JIRA API to show notification message


  JIRA.Messages.showSuccessMsg(message);




Embed the JavaScript file in JIRA pages

 

1. Add the following web-resource Plugin module in the atlassian-plugin element of jira-gamification-plugin/atlassian-plugin.xml.


<web-resource name="Resources" key="resources">


  <resource name="sap_gs_notifications.js" type="download" location="widgets/sap_gs_notifications.js"/>


    <context>atl.general</context>


</web-resource>


 


Note:


Here, web resource context is atl.general which means the widget sap_gs_notifications.js will be included on all screens of JIRA except administration screens.



The atlassian-plugin.xml should look like:





Test Integration with JIRA:



1. Open a command prompt and run the following set of commands to set environment variables.


set user_name=<HANA Cloud Platform user name>


set user_password=<HANA Cloud Platform password>


set host = < gamification service host>



If you are running this application behind the firewall you also need to set http_proxy_host and http_proxy_port by using following commands.



set http_proxy_host= <Http proxy name> 


set http_proxy_port= <Http port number>



2. Change directory to the folder jira-gamification-plugin and run the following command

 

atlas-run



3. Once JIRA has started successfully, open the URL printed in the message.



 

4. Log in with username JIRA_USER@mail.com and create an issue as described in the previous blog and notification would be visible as shown in the snapshot below

 


 

Congratulation!! :smile: You are done with Part 5 and with this integration of SAP HCP gamification service with JIRA is complete :smile: :smile: .  Next blog post Part 6 you will introduce the advance game mechanics like levels, badges, leaderboard and these elements will be visible in the User profile page.

3 Comments