iXora Custom Software Development Blog

Read | Practice | Advance

WebHooks

Posted by on in Blog
  • Font size: Larger Smaller
  • Hits: 154
  • 0 Comments
  • Print

What are WebHooks?

  • WebHooks are event callbacks over http. 
  • The server or app calls your URL.
  • It’s not a protocol, there is no standard. Its just a design pattern.
  • When something happens, perform HTTP POST with relevant data to a URL that the user gives you.

Modern API and WebHooks

Before we see how webhooks work, lets look at how HTTP works?

b2ap3_thumbnail_How_htt_works.pngUnfortunately that's how the web is today.

  • We can talk to web apps, but they really can’t talk to us.
  • Its as if you had a telephone system where you could only make calls, but never receive them. 
  • 98.5% of polls are wasted.

b2ap3_thumbnail_Modern_API.png

So to get the updated information you may need to refresh the page by yourself. Which is unacceptable!!!! And if it takes too much time to refresh the site User may leave the site. So refresh button is an EVIL and we need to stop using it.

It’s not that they can’t talk to the caller, they just don’t. We need to start placing event hooks in them. So we should have event driven programming.

b2ap3_thumbnail_Modern_API_WebHooks.pngHow does WebHook work?

b2ap3_thumbnail_How_webhooks_work.png

Many modern applications/sites provide WebHooks for their end users. Like GitHub, Facebook etc. How to create our own webhook? Lets do it in a few moments.

Bore moving to code level implementations, lets look at pros and cons, known issues and check lists of implementing webhooks.

Pros and Cons

b2ap3_thumbnail_t_up.png b2ap3_thumbnail_t_down.png
  • Real time updates (almost).
  • Without dedicated resources.
  • Easily consumed.
  • Easily Integrated.
  • Poor user experience. You need to register and handle the callback.
  • Debugging. Though now a days there are some way of doing it.

 Known issues

Consumer API Provider
  • DDoS attack
  • Missed notification. Consumer may not get some result.
  • Deduplication. Consumer may get same result multiple times.
  • DDoS attack                                                               

A Distributed Denial of Service (DDoS) attack is an attempt to make an online service unavailable by overwhelming it with traffic from multiple sources. They target a wide variety of important resources, from banks to news websites, and present a major challenge to making sure people can publish and access important information.

Check lists

Keeping known issues in mind we can follow some checklists both on consumer and provider side to reduce the problems.

Consumer API Provider
  • One callback per webhook
  • Try to use human unreadable callback URLs.
  • Expected answer? (Like Status 200)
  • Handle request number.
  • Monitor payload size.
  • Implement authentication

Okay!! Lets do some coding now. 

Steps:

  1. Create a Dynamic Web Project. In Eclipse Go File>New>Other and choose "Dynamic Web Project" under Web.
  2. Add files shown in the following image. Content of each of the file will be discussed later.

b2ap3_thumbnail_webhooks_project_structure.png

MessageWebSocketSever.java

package com.ixora.webhooks;

import java.util.LinkedHashSet;
import java.util.Set;

import javax.enterprise.context.ApplicationScoped;
import javax.json.JsonObject;
import javax.json.spi.JsonProvider;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;


@ApplicationScoped
@ServerEndpoint("/actions")
public class MessageWebSocketServer {

	private static final Set<Session> sessions = new LinkedHashSet<Session>();

    @OnOpen
    public void onOpen(Session session) {
        sessions.add(session);
    }

    @OnClose
    public void onClose(Session session) {
        sessions.remove(session);
    }

    private static JsonObject createJsonMessage(String message) {
        return JsonProvider.provider().createObjectBuilder().add("jsonMessage", message).build();
    }

    public static void sendAll(String text) {
        synchronized (sessions) {
            String message = createJsonMessage(text).toString();

            for (Session session : sessions) {
                if (session.isOpen()) {
                    session.getAsyncRemote().sendText(message);
                }
            }
        }
    }
}

TestServlet.java

package com.ixora.webhooks;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class TestServlet
 */
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public TestServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {		
		MessageWebSocketServer.sendAll(request.toString());			
	}
	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {		
		StringBuilder builder = new StringBuilder();
	    String aux = "";

	    while ((aux = request.getReader().readLine()) != null) {
	        builder.append(aux);
	    }

	    String text = builder.toString();
	    MessageWebSocketServer.sendAll(text);		
	}
}

index.html

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <script src="/websocket.js"></script>
        <link rel="stylesheet" type="text/css" href="/style.css">
    </head>
    <body>

        <div id="wrapper">
            <h1>Java WebHook Home</h1>
            <p>Welcome to the Java WebHook Home</p>
            <br />            
            <br />
            <h3>WebHook Messages:</h3>
            <div id="content">
            </div>
        </div>

    </body>
</html>

 

style.css

body {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 80%;
    background-color: #1f1f1f;
}

#wrapper {
    width: 960px;
    margin: auto;
    text-align: left;
    color: #d9d9d9;
}

p {
    text-align: left;
}

#content {
    margin: auto;
    width: 960px;
}

.message {
    text-align: center;
    font-weight: bold;
    margin-bottom: 12px;
}

websocket.js

var socket = new WebSocket("ws://localhost:8080/WebSocket/actions");
socket.onmessage = onMessage;


function onMessage(event) {
    var message = JSON.parse(event.data);    
     printDeviceElement(message);   
}


function printDeviceElement(message) {
    var content = document.getElementById("content");  
    
    var deviceName = document.createElement("span");
    deviceName.setAttribute("class", "message");
    deviceName.innerHTML = message.jsonMessage;
    content.appendChild(deviceName);
}

So we are done with coding. 

Now run the application into the web server (Glass Fish for this case) and you will see the following screen

b2ap3_thumbnail_webhooks_output_1.png

 Now type "http://localhost:8080/WebHooks/TestServlet" in a separate browser and you will get the following screen. We just printed the request as a text.

b2ap3_thumbnail_webhooks_output_2.png 

Rate this blog entry:
1

Mohammad Shafiqul Islam has not set their biography yet

Author's recent posts

Comments

  • No comments made yet. Be the first to submit a comment

Leave your comment

Guest
Guest Wednesday, 15 August 2018