Skip to Content

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:

/wp-content/uploads/2015/10/1_802530.png

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

/wp-content/uploads/2015/10/2_802531.png

 

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:

/wp-content/uploads/2015/10/3_802547.png

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.

/wp-content/uploads/2015/10/5_802548.png

 

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

 

/wp-content/uploads/2015/10/6_802549.png

 

Congratulation!! 🙂 You are done with Part 5 and with this integration of SAP HCP gamification service with JIRA is complete 🙂 🙂 .  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.

To report this post you need to login first.

3 Comments

You must be Logged on to comment or reply to a post.

  1. Derek Holley

    Hi! I realize I’m a little late to the game here. This blog references 2 additional files,

    1. GamificationProxy.txt.zip
    2. sap_gs_notifications.txt.zip

    Says they are included in the blog as additional files, but I can’t seem to find them. Do they still exist? If so, I would love to continue and finish this tutorial, but I’m a little lost as to what would be in these files. My business is very interested in this integration.

    (0) 
    1. Anuj Mehta Post author

      Hi Derek,

      Thanks for showing interest in this.

      I have attached the code of these two files in this blog.

      Best Regards,

      Anuj Mehta

      (0) 
      1. Derek Holley

        Hey Anuj,

        Thanks for the prompt response! I think the version of GamificationProxy you just posted is different from the one needed in this part of the blog.

        The version you posted notably doesn’t contain the methods getPlayerNotifications() or getServerTime(). If you have the second version around, that would be great 🙂

        Otherwise, I can probably figure those out. Thanks!

        (0) 

Leave a Reply