Build a Serverless API backend to deliver funny GIFs in Slack

Webhook backends are a popular use case for Serverless functions. FaaS (Functions-as-a-service) offerings make it relatively easy to provide an HTTP endpoint which hosts the Webhook logic which can be as simple as sending an email to something as entertaining as responding with funny GIFs!

In this tutorial, we will explore funcy – a Serverless webhook backend which is a trimmed down version of the awesome Giphy for Slack. The (original) Giphy Slack app returns a bunch of GIFs for a search term and the user can pick one of them. funcy tweaks it a bit by simply returning a (single) random image for a search keyword using the Giphy Random API.

This blog post provides a step-by-step guide to getting the application deployed to Azure Functions and hooking it up with your Slack workspace. The code is available on GitHub for you to grok.

If you are interested in learning Serverless development with Azure Functions, simply create a free Azure account and get started! I would highly recommend checking out the quickstart guides, tutorials and code samples in the documentation, make use of the guided learning path in case that’s your style or download the Serverless Computing Cookbook.

In order to keep this blog concise, the details of the code have been covered in this blog post – https://abhirockzz.wordpress.com/2019/09/07/code-walkthrough-for-funcy-a-serverless-slack-app-using-azure-functions/

Overview

funcy is built as a Slash Command within Slack. As a user, you can invoke it from your Slack workspace using /funcy. This, in turn, invokes our webhook deployed to Azure Functions – which is nothing but a bunch of Java code. It calls the Giphy Random API and returns the result back to the user.

For example, invoking it from your Slack workspace using /funcy serverless will return a random GIF.

The upcoming sections will guide you through the following:

  • Pre-requisites
  • Slack setup and configuration
  • Deploying to Azure Functions

Pre-requisites

Before you proceed, ensure that you have the following ready – it shouldn’t take too long

Please note down your GIPHY API key as you will be using it later

Configure Slack

Please note that the instructions in this section have been adapted from the Slack documentation

Create a Slack App

Sign into your Slack Workspace. Start by creating a new Slack App

Create a Slash Command

Once you’re done creating the app, head to your app’s settings page, and then click the Slash Commands feature in the navigation menu.

You’ll be presented with a button marked Create New Command, and when you click on it, you’ll see a screen where you’ll be asked to define your new Slash Command with the required information.

Enter the required information. Please note that the Request URL field is the one where you will enter the HTTP endpoint of function which will be available after you deploy it. You can use a dummy URL as a placeholder just for the time being e.g. https://temporary.com:4242

Once you’re done, hit Save to finish.

Install the app to your workspace

Once you’re done creating the Slash Command, head to your app’s settings page, click the Basic Information feature in the navigation menu, choose Install your app to your workspace and click Install App to Workspace – this will install the app to your Slack workspace to test your app and generate the tokens you need to interact with the Slack API.

As soon as you finish installing the app, the App Credentials will show up on the same page. You need to grab your Slack Signing Secret from there

Make a note of your app Signing Secret as you’ll be using it later

Deploy to Azure

Start by cloning the GitHub repository and change into the application directory

    git clone https://github.com/abhirockzz/funcy-azure-functions
    cd funcy-azure-functions

The pom.xml file contains the following attributes used by the Azure Functions Maven plugin – application name (functionAppName), region (functionAppRegion) and resource group (functionResourceGroup). It has default values for the above parameters, so you can choose to continue using them if you like.

  • functionAppName – funcyapp
  • functionAppRegion – westus
  • functionResourceGroup – java-functions-group

Please note that the app name must be unique across Azure.

If you wish to wish to change the values, please take a look at this snippet from pom.xml which highlights the properties which need to be updated

pom

The name of the function is not the same as application name (configured via pom.xml) and is specified using the @FunctionName annotation in the Java code for the function – in this case, the name is funcy.

You can now build the function and deploy it to Azure

//build
mvn clean package

//deploy
mvn azure-functions:deploy

The results from a successful deployment will look something like this

[INFO] Successfully updated the function app.funcyapp
[INFO] Trying to deploy the function app...
[INFO] Trying to deploy artifact to funcyapp...
[INFO] Successfully deployed the artifact to https://funcyapp.azurewebsites.net
[INFO] Successfully deployed the function app at https://funcyapp.azurewebsites.net
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

Use the Azure CLI to list your Functions App

az functionapp list --query "[].{hostName: defaultHostName, state: state}"

You should see a JSON output

[
    {
        "hostName": "funcyapp.azurewebsites.net",
        "state": "Running"
    }
]

You should be able to see the function (under Function App menu) in Azure Portal

Once the deployment is successful, the function should be ready to serve requests and can be accessed over HTTP(s) at the following endpoint – https://.azurewebsites.net/api/

For an application named funcyapp with a function called funcy, the endpoint would be

https://funcyapp.azurewebsites.net/api/funcy

You’re almost there!

Update your Azure Functions app

Now that the Azure Functions app is up and running, you need to update it to seed the Giphy API Key and Slack Signing Secret as environment variables.

az functionapp config appsettings set --name  --resource-group  --settings "SLACK_SIGNING_SECRET=" "GIPHY_API_KEY="

e.g.

az functionapp config appsettings set --name funcyapp --resource-group java-functions-group --settings "SLACK_SIGNING_SECRET=foobarb3062bd293b1a838276cfoobar" "GIPHY_API_KEY=foobarrOqMb5fvJdIuxTCr3WUDfoobar"

Please refer to the documentation on How to manage a function app in the Azure portal for details.

Update the Slack app

Head to your app’s settings page, and then click the Slash Commands feature in the navigation menu. Edit the command and replace the value for the Request URL field with your function HTTP(s) endpoint

funcy time!

From your workspace, invoke the command

/funcy

Since you can’t go wrong with cats, try

/funcy cat

Don’t worry if you see a Timeout error from Slack after the first invocation. This is due to the ‘cold start’ problem where the function takes a few seconds to bootstrap but Slack expects a response in 3 seconds. Just retry (a couple of times) and things should be fine.

If your application cannot afford the latency due to “idle cold starts”, you might want to check out Azure Functions Premium plan which provides “pre-warmed instances to run your app with no delay after being idle…”

Resources

The below mentioned resources were leveraged specifically for developing the demo app presented in this blog post, so you’re likely to find them useful as well!

Don’t forget to check out the second part of this blog post, where I have covered the code in detail

I really hope you enjoyed and learned something from this article! Please like and follow if you did. Happy to get feedback via @abhi_tweeter or just drop a comment.

Posted in serverless | Tagged , , , , | 1 Comment

Screencast: pushing a Java EE app to Oracle Cloud

Here is a screen cast to show case how you can easily push a Java EE application to Oracle Application Container Cloud from your command line

 

Overview

  • start with a Java EE 7 Maven archetype — mvn archetype:generate -Dfilter=com.airhacks:javaee7-essentials-archetype
  • modify the code — add a simple JAX-RS resource and build the project with mvn clean install
  • add (tiny bit of) metadata (deployment.json)

{
“instances”:1,
“memory”:”1G”
}

Further reading

Cheers!

Posted in Java EE | Tagged , , , , | Leave a comment

Session @ Oracle Code San Francisco 2017

Here are the details for my talk @ Oracle Code (a track at JavaOne 2017) – Streaming Solutions for Real time problems (Stream Processing solutions using Apache Kafka, Kafka Streams and Redis)

Code (Github) – https://github.com/abhirockzz/accs-ehcs-stream-processing

Video

Slides

Cheers!

Posted in Cloud, Java EE | Tagged , , , , , , , | Leave a comment

New release: REST assured with JAX-RS

cover_final

 

 

REST assured with JAX-RS is now updated for JAX-RS 2.1 – a new chapter has been added to cover its new features. You can read it on Gitbook or grab it via Leanpub

Cheers!

Posted in Java, Java EE | Tagged , , , , , | Leave a comment

Handling custom objects with JAX-RS SSE API

Information sent using the JAX-RS 2.1 SSE support (in Java EE 8) does not only have to be of String type – it supports Java primitives (Integer , Long etc.), JSON-B & JAX-B annotated types as well as custom objects whose encoding process (Java object to on-wire format) is defined using a MessageBodyWriter implementation

Here is simple example you can try out – no need to setup anything except Docker !

Meanwhile – here is the code snippet

To summarize

  • Multiple ​​OutboundSseEvents have been created – each differing in the data/media type (text, json, xml etc.)
  • the default SSE media type is TEXT_PLAIN, hence does not need to be explicitly specified when dealing with String data type
  • ​​​​​Employee class is a JSON-B annotated class
  • Customer is a JAX-B annotated class
  • Student has a custom MesaageBodyWriter implementation

For more details, just refer to the project

Further reading

Cheers!

Posted in Java, Java EE | Tagged , , , , , | Leave a comment

CompletionStage support in server-side JAX-RS

JAX-RS 2.1 (part of Java EE 8) now supports returning a CompletionStage to mark the request as eligible for asynchronous processing. This is in addition to the AsyncResponse API which has been available since JAX-RS 2.0 (Java EE 7)

Even the Client API has added support for reactive-style programming by providing support for CompletionStage API, but this blog will focus on the server-side support

The advantage this approach has over the AsyncResponse based API is that it is richer and allows you to create asynchronous pipelines. Let’s look at an example – available on Github. It is simple and slightly contrived, but hopefully it should help get the point across 🙂

  • It starts with a HTTP GET to /booking/cabs/<user> which invokes the getCab method
    • the method returns a CompletionStage and returns immediately
    • the thread which served the request is now freed up
  • and then its about creating the asynchronous pipeline
    • we orchestrate the tasks for user validation and driver search using thenComposeAsync – this gives a CompletableFuture i.e. the searchDriverTask
    • we then supply a Function which takes the driver (returned by the above step) and invokes the notifyUser method – this is the CompletionStage which we actually return i.e. notifyUserTask – this is obviously executed later on, all we did was compose the sequence
  • once the process is completed (delays are introduced using Thread.sleep() ), the response is sent back to the user – internally, our CompletableFuture completes

To run using Docker

Refer README

Further reading

Posted in Docker, Java, Java EE | Tagged , , , , | Leave a comment

JAX-RS 2.1 SSE Client API example using Glassfish 5 on Docker

Along with the Server API for SSE, JAX-RS 2.1 (part of Java EE 8) also has an equivalent client side API

Here is a quick peek – you can grab the project from Github

To summarize

  • we use a @Singleton EJB with @Startup
  • during initialization
    • create a single action (one time) Timer  i.e. @PostConstruct
    • and instantiate the SSEEventSource – its a public SSE source
  • when the timer expires, the @Timeout annotated method gets triggered
    • opens the SSE connection
    • prints them out – this action is registered as a callback (written as a Java 8 lamda in this case)
  • Execution thread pool(s) – notice this in the logs
    • the timer itself is triggered in the EJB thread pool
    • SSE event callbacks are executed in the ManagedExecutorService thread pool (thanks to Java EE Concurrency Utilities)

sse-client-output.jpg

To run using Docker

Refer README

Further reading

Cheers!

Posted in Java EE | Tagged , , , , , , , | Leave a comment

Try out JSON-B 1.0, JPA 2.2 using Java EE 8 on Glassfish 5 & Docker

Glassfish 5 Build 11 is now available – with support for many of the Java EE 8 specifications e.g. JAX-RS 2.1, JPA 2.2, JSON-B 1.0 etc. For more details check out the Aquarium space. This blog covers

Application

It’s a simple one – available on Github

  • Has a REST endpoint (also a @Stateless bean)
  • Interacts with an embedded (Derby) DB using JPA – we use the jdbc/__TimerPool present in Glassfish to make things easier
  • Test data is bootstrapped using standard JPA features in persistence.xml (drop + create DB along with a SQL source)

JSON-B 1.0 in action

Primarily makes use of the JSON-B annotations to customize the behavior

  • @JsonbProperty to modify the name of the JSON attribute i.e. its different as compared to the POJO field/variable name
  • @JsonbPropertyOrder to specify the lexicographical reverse (Z to A) order for JSON attributes

For more, check out Yasson which is the reference implementation

JPA 2.2 in action

The sample application uses the stream result feature added to Query and TypedQuery interfaces by which it’s possible to use JDK 8 Streams API to navigate the result set of a JPA (JPQL, native etc.) query. For other additions in JPA 2.2, please check this

Run on Docker and test…

Check the README

Cheers!

Posted in Java, Java EE | Tagged , , , , , , | 1 Comment

CDI (2.0) Async Events

Glassfish 5 builds for Java EE 8 are rolling along… here is another Docker based example on Github. This time it’s asynchronous events in CDI 2.0 (JSR 365)

Steps

Just follow the README… just a bunch of docker commands to get started..!

What’s going on

Here is a quick summary

  • A Java EE scheduler triggers asynchronous CDI events (fireAsync())
    • These CDI events are qualified (using a custom Qualifier)
    • It also uses a custom java.util.concurrent.Executor (based on the Java EE Concurrency Utility ManagedExecutorService) – thanks to the NotificationOptions supported by the CDI API
  • Two (async) CDI observers (@ObservesAsync) – a JAX-RS SSE broadcaster and a Websocket endpoint
  • SSE & Websocket endpoints cater to their respective clients – details on how to connect in the README

Notice the asynchronous events running in Managed Executor service thread

action-2.jpg

You can choose to let things run in the default (container) chosen thread

cdi-2-async-events-in-action.jpg

Further reading

Cheers!

 

 

Posted in Docker, Java, Java EE | Tagged , , , , , , , , , | Leave a comment

Java EE + Debezium

I just published a post – Debezium test drive. It uses Kafka and Java EE… check it out if this interests you

Cheers!

Posted in Java, Java EE | Tagged , , , , , , | Leave a comment