skip to Main Content

What are the CompetitionLabs Transformers

CompetitionLabs Transformers are a recommended way to integrate with the CompetitionLabs platform without having to make modifications to your message formats on your back-end systems. Using the CompetitionLabs Transformers, you can send a message to CompetitionLabs in your current format, transform the message into a form that can be accepted by the CompetitionLabs API, and push that message to CompetitionLabs. You can also transform messages before they are POSTed to your system via the CompetitionLabs WebHooks.

CompetitionLabs Transformers are created by writing small Scala classes that extend the CompetitionLabs Transformer classes to process messages.

Inbound events sent via RabbitMQ are transformed by extending the CLMQTransformer class. Your transformation class is run by the CompetitionLabs platform when the message is received.

Outbound events sent via WebHooks are transformed by extending the CLWebhookTransformer class. Your transformation class is run by the CompetitionLabs platform when an action occurs that would trigger a WebHook to fire.

If you want to Write a class that extends
Map your existing MQ messages to a CompetitionLabs Event CLMQTransformer
Map a CompetitionLabs WebHook message to a format your back-end systems accept CLWebhookTransformer

Common use cases for CompetitionLabs Transformers

Beyond mapping of message fields from your platform to CompetitionLabs, below are some common uses for CompetitionLabs Transformers:

  • Create a new member when CompetitionLabs receives an event from a sign-up event
  • Push a message into your platform when a new Product is created within CompetitionLabs
  • Retrieve customer segment information from your platform for a new member

List of operations available can be found inside the github project.

Transform incoming messages from a RabbitMQ Queue

CompetitionLabs MQ transformer is used to transform a message received via RabbitMQ to your CompetitionLabs space. Within the transformer, you can map the fields of an incoming message to the CompetitionLabs API, trigger addition events, or implement custom business logic.

To transform an incoming message from a RabbitMQ Queue:

1. Create a class that extends the CLMQTransformer class – Default Transformer

/***
  *  Copyright (C) Competition Labs Ltd - All Rights Reserved
  *  Unauthorized copying of this file, via any medium is strictly prohibited
  *  Proprietary and confidential
  *  Written by Competition Labs Ltd, 2017
  */
 
// Do not add additional imports from non-standard libraries
import com.competitionlabs.transformers._
import com.competitionlabs.transformers.domain.BasicEventModel
import org.joda.time.DateTime
 
class CompetitionLabsMQTransformer extends CLMQTransformer {
 
    override def apply(message: Array[Byte], competitionLabsApi: CompetitionLabsApi) = {
 
        ////////////////////////////////////////////////////
        // 1. Extract the main data from our json body
        ////////////////////////////////////////////////////
 
        val messageAsString = competitionLabsApi.convertByteArrayToString(message)
        val messageAsJson = competitionLabsApi.fromJsonString(messageAsString)
        val jsonObj = messageAsJson
 
        val memberRef = Json.getFromJValue[String](jsonObj, "memberRefId")
        val batch = Json.getFromJValue[String](jsonObj, "batchId")
        val entityRef = Json.getFromJValue[String](jsonObj, "entityRefId")
        val eventRef = Json.getFromJValue[String](jsonObj, "eventRefId")
        val action = Json.getFromJValue[String](jsonObj, "action")
        val sourceValue = Json.getFromJValue[Double](jsonObj, "sourceValue")
        val transactionTimestamp = new DateTime(Json.getFromJValue[String](jsonObj, "transactionTimestamp"))
 
        ////////////////////////////////////////////////////
        // 2. Create data points if they are missing
        ////////////////////////////////////////////////////
 
        competitionLabsApi.memberIdFromMemberRefId(memberRef).getOrElse{
            // Create a new member  ->
            competitionLabsApi.createMember(memberRef, "unknown", Seq("new"))
        }
 
        competitionLabsApi.productIdFromProductRefId(entityRef).getOrElse{
            // Create a new product
            competitionLabsApi.createProduct(entityRef, "unknown", Seq.empty, "slot", 0)
        }
 
        if(!competitionLabsApi.eventActionExists(action)) {
            // Create the action
            competitionLabsApi.createEventAction(action)
        }
 
        ////////////////////////////////////////////////////
        // 3. Lets decorate the event with our custom fields
        ////////////////////////////////////////////////////
 
        val customJson = jsonObj.\("metadata")
        val myCustomField1 = Json.getFromJValue[Int](customJson, "myCustomField1")
        val myCustomField2 = Json.getFromJValue[Int](customJson, "myCustomField2")
        val myCustomField3 = Json.getFromJValue[String](customJson, "myCustomField3")
 
        val customFields = new scala.collection.mutable.HashMap[String, Seq[Any]]()
        customFields.put("myCustomField1",Seq(myCustomField1))
        customFields.put("myCustomField2",Seq(myCustomField2))
        customFields.put("myCustomField3",Seq(myCustomField3))
 
 
        ////////////////////////////////////////////////////
        // 4. Push the data to your CompetitionLabs space
        ////////////////////////////////////////////////////
 
        val event = BasicEventModel(
            action = action,
            tags = Seq.empty,
            eventRefId = eventRef,
            memberRefId = memberRef,
            entityRefId = entityRef,
            batchId = Option(batch),
            sourceValue = sourceValue,
            metadata = customFields.toMap,
            transactionTimestamp = transactionTimestamp
        )
 
        competitionLabsApi.pushEvent(event)
    }
}

 

2. Test your class using Scala Test and theCompetitionLabsApiTestmodule – Transformer Test

/***
  *  Copyright (C) Competition Labs Ltd - All Rights Reserved
  *  Unauthorized copying of this file, via any medium is strictly prohibited
  *  Proprietary and confidential
  *  Written by Competition Labs Ltd, 2017
  */
package cl.test
 
import cl.transformers
import org.scalatest._
import utils.CompetitionLabsApiTest
 
class CLRabbitMQTest extends FunSpec with Matchers with GivenWhenThen with BeforeAndAfterEach with BeforeAndAfterAll {
 
    describe("Test the CompetitionLabs message queue receiver implementation") {
         
        //  Run the test
        it("should receive a published a message and transform it into a CompetitionLabs event") {
 
            // Prepare the test
            val transformer = new transformers.CompetitionLabsMQTransformer()
            val json = CLRabbitMQTest.jsonStringFromMq.toCharArray.map(_.toByte)
            val api = new CompetitionLabsApiTest()
            api.createMember("my-custom-member-ref-1","my-custom-member-ref-1", Seq("vip"))
            api.createEventAction("wager")
            api.createProduct("fruits","Fruits", Seq("CL"),"slot", 1)
 
            When("the message is forwarded")
            transformer.apply(json, api)
 
            Then("the event should be received")
            assert(api.eventsReceivedForTest.keySet.contains("fruits"))
        }
    }
}
 
object CLRabbitMQTest {
    val jsonStringFromMq: String =
        """{
                "memberRefId": "my-custom-member-ref-1",
                "batchId": "some-batch-123456",
                "entityRefId": "fruits",
                "eventRefId": "your-system-event-id-1",
                "action": "wager",
                "sourceValue": 25,
                "transactionTimestamp": "2017-09-05T22:01:09.909+07:00",
                "metadata": {
                    "myCustomField1": 1,
                    "myCustomField2": 2.2,
                    "myCustomField3": "one"
                }
             }
           """
}

Transform outgoing WebHook messages from CompetitionLabs

You can use CompetitionLabs WebHook transformers to modify and send messages to your WebHook endpoints. You can map field in the CompetitionLabs data model to fields already implemented in your platform. You can also use the CompetitionLabs Webhook Transformer API to trigger additional actions and events.

You can create a CompetitionLabs WebHook transformer for any of the built in WebHook events. If you have a customer WebHook transformer configured, your custom transformer is used instead of the built in WebHook transformer.

To create a CompetitionLabs WebHook transformer:

1. Create a new class that extends CLWebhookTransformer – Webhook Example

package example.transformers
 
import com.competitionlabs.transformers.{CLWebhookTransformer, CompetitionLabsApiExt}
import com.competitionlabs.transformers.domain.WebhookSettings
 
class exampleWebHookTransformer extends CLWebhookTransformer {
 
/**
* Executed when a new member is registered in your CompetitionLabs space
* @param settings The user supplied settings
* @param memberId The CompetitionLabs member id
* @param competitionLabsApi The CompetitionLabs API
*/
override def onNewMember(settings: WebhookSettings, memberId: String, competitionLabsApi: CompetitionLabsApiExt): Unit = {
        // Your transformation logic
    }
}

2. Override one of the methods in CLWebhookTransformer with your implementation

The following are the built in WebHook transformers you can override with your own customer transformer:

Example of a WebHook transformer

Below is an example of a custom WebHook transformer.

import com.competitionlabs.transformers.domain.WebhookSettings
import com.competitionlabs.transformers.{CLWebhookTransformer, CompetitionLabsApiExt}
import org.joda.time.DateTime
 
class DefaultWebhookTransformer extends CLWebhookTransformer {
    override def onAchievementTriggered(settings: WebhookSettings, achievementId: String, memberId: String, competitionLabsApi: CompetitionLabsApiExt): Unit = {
 
        val body = Map[String, Any](
            "accountId" -> competitionLabsApi.accountId,
            "achievementId" -> achievementId,
            "memberId" -> memberId,
            "memberIdRefId" -> competitionLabsApi.memberRefIdFromMemberId(memberId),
            "resourcePath" -> s"/api/${competitionLabsApi.spaceName}/achievement/$achievementId",
            "timestamp" -> DateTime.now().getMillis
        )
 
        val json =  competitionLabsApi.toJsonFromMap(body)
        val headers = settings.headers ++ competitionLabsApi.HTTPDefaultHeader
 
        competitionLabsApi.httpPost(settings.url, json, headers)
    }
}

Developing and Testing Transformers

This section covers the tools needed to begin writing and testing CompetitionLabs Transformers

System Requirements

These are the tools you will need to develop CompetitionLabs Transformers

  • Scala 2.11
  • Java 1.8
  • JDK
  • JetBrains
  • IntelliJ (Optional)

CompetitionLabs Transformer API

The CompetitionLabs Transformer API is used within your transformer classes to perform various operations like looking up members, pushing events, creating actions, etc.

You can view the methods available for CLMQTransformer and CLWebhookTransformer classes here: competitionlabs-transformers/src/main/scala/com/competitionlabs/transformers/CompetitionLabsApi.scala

You can view addition methods available for CLWebhookTransformer classes here: clabs/competitionlabs-transformers/src/main/scala/com/competitionlabs/transformers/CompetitionLabsApiExt.scala

Github project is available at – competitionlabs-transformers

Once you have got your code working, get in touch with the CompetitionLabs admin team, they will provide you with a private repository to commit and deploy your custom transformers.

Back To Top