Getting Started with WebSockets and Node & React

WebSockets are an efficient way to deliver content to your web application. With the typical HTTP protocol data is requested from your web client application from your web server and it will then reply with the content. With WebSockets a continuous two-way interactive session is created between the client application and the server. Once a connection is established between the client and the server though web sockets, data can be transferred to both the client and the server in a continuous event-driven manner without the client to repeatedly poll for the data.

Here we will build a simple application that will echo the messages from a web client application. We will use Node.js and the express middleware to build the server. The frontend will be a simple React application. I will use socket.io framework here for adding the WebSockets functionality.

Backend

Setup

Let’s get our project set up for the backend:

mkdir -p websockets_testdrive/backend

Init the NPM project – simply use the default values suggested

cd websockets_testdrive/backend
npm init

Now let’s add the dependencies for express and socket.io libraries

npm install -s express socket.io

Code

We will implement the server in a file named server.js (double check that the entry for "main" in package.json is pointing to it).

First step is to import our libraries and have the server listening to the port 3000 – you will see code here for enabling it for CORS:

var app = require('express')()
var http = require('http').createServer(app)
var io = require('socket.io')(http, {
    cors: {
      origin: "*",
      methods: ["GET", "POST"]
    }
  })
const cors = require('cors')

app.use(cors())

http.listen(port=3000, () => {
    console.log('Listening on *:%i', port)
})

Running a simple npm run start will simple let the server listen on port 3000. With the following lines added to the server.js file we will implement a simple protocol. Whenever the server receives a message-event event through the web socket, the server will log out the contents of the event and reply to everyone on web socket with the same content as well. This is wrapped, however, in a message-response-event:

io.on('connection', (socket) => {
    socket.on('message-event:', (msg) => {
        console.log('Received a message-event: %s', msg)
        io.emit('message-response-event', msg)
    })
})

Our code is done on the server now. We run it with npm run start and can focus our efforts now to the frontend.

Enable CORS on socket.io

In the code above you will find the settings to be made to enable CORS on the server for HTTP and WebSocket traffic. For the socket.io library, this needs to be set explicitly as in:

var io = require('socket.io')(http, {
    cors: {
      origin: "*",
      methods: ["GET", "POST"]
    }
  })

Frontend

We will use the create-react-app script to get our React frontend project setup done here:

cd websockets_testdrive
npx create-react-app frontend

This will take a while for the files to be created and the dependencies resolved. Now add the socket.io-client library and give the initial app a try:

cd frontend
npm install socket.io-client -s
npm run start

Messenger Component

We will implement the WebSocket client in a Messenger React component. The component will list all the messages sent over by the client above and a textbox allows the user to send a message using the WebSocket connection:

import React, { useEffect, useState } from 'react'
import io from 'socket.io-client'

function Messenger() {
    const [receivedMessages, setReceivedMessages] = useState([])
    const [message, setMessage] = useState('Hello')

    const handleSubmit = (e) => {
        e.preventDefault()
        setMessage('')
    }
    return (
        <div>
            <div>
                <ul>
                    {
                        receivedMessages.map( (item, index) => (
                            <li key={index}>{item}</li>
                        ))
                    }
                </ul>
            </div>

            <form onSubmit={handleSubmit}>
                <label htmlFor="txtMessage">
                    Your message:
                </label>
                <input
                    id="txtMessage"
                    value={message}
                    onChange={e => setMessage(e.target.value)}
                />
                <button>
                    Send
                </button>
            </form>


        </div>
    )
}

export default Messenger

There is nothing too special in the component above. It is a React function based component with some React Hooks for showing all the receivedMessages and keeping track of the inputbox’ content in the message hook.

Now let’s integrate the component into the React starter component in the App.js file:

import './App.css'
import Messenger from './Messenger'

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <Messenger/>
      </header>
    </div>
  );
}

export default App

We can now start the frontend with

npm run start

and continue our development on the WebSocket functionality in the Messenger.js file. We will need to keep track of the WebSocket with a useRef()hook.

const socket = useRef()

The useRef hook will hold an instance of the WebSocket over the complete lifetime of the socket.

Using the useEffect() hook, we initialise the WebSocket connection to the server and register a subscriber whenever a message-response-event is triggered by the server:

useEffect(() => {
        if (!socket.current) {
            socket.current = io.connect('localhost:3000')
            socket.current.on('message-response-event', msg => {
                console.log('received message-response-event: %s', msg)
                setReceivedMessages(receivedMessages => [...receivedMessages, msg])
            })
        }
        
    }, [])

Finally we extend the handleSubmit code by sending a message-event with the contents of message through the WebSocket:

    const handleSubmit = (e) => {
        e.preventDefault()
        let s = socket.current
        s.emit("message-event", message)
        setMessage('')
    }

That’ll be it in the frontend and the backend. Now you can test the application on the web browser. Open up a second browser tab and see how the changes from the one session are shown in both browser tabs.

Further Reading

This is a simple setup for now. All the changes sent over the WebSocket are using the same channel and they broadcast the events through it. There are different communication patterns possible to support different scenarios. Read about it in the Broadcasting section in the socket.io documentation.

Open items

  • Make code available on GitHub
  • Add screenshots
  • Proof read it

Time your requests with curl

Finding out where most of a http’s request time is spent can be done with curl too:

  1. create a curl output format file named time-fmt.txt with the following content:
    time_namelookup: %{time_namelookup}\n
    time_connect: %{time_connect}\n
    time_appconnect: %{time_appconnect}\n
    time_pretransfer: %{time_pretransfer}\n
    time_redirect: %{time_redirect}\n
    time_starttransfer: %{time_starttransfer}\n
    ----------\n
    time_total: %{time_total}\n
    view raw time-fmt.txt hosted with ❤ by GitHub
  2. Call curl like this:
    curl -w "@time-fmt.txt" -s "https://google.com" -o NUL

The results of this will look like this:
curl

Get Members of Active Directory Group

So you have a AD Group and you need to find out, who are the members of this group. You could use some LDAP Browser tool. But it’s possible to use Microsoft PowerShell for that:

Here is the code:

# Define LDAP search root, the Global catalog of the domain
$sLDAPSearchRoot="LDAP://YOUR.CORP.ORG"
# The Groupname to looking for
$sGroupName="AD_GROUPNAME"
# The query string
$sSearchStr ="(&(objectCategory=group)(name="+$sGroupName+"))"
# Get the search object
$oSearch=New-Object directoryservices.DirectorySearcher($oADRoot,$sSearchStr)
# Looking for the group
$oFindResult=$oSearch.FindAll()
$oGroup=New-Object System.DirectoryServices.DirectoryEntry($oFindResult.Path)
$oGroup.member | Out-GridView

 

Connect Orionhub with Pivotal Cloud Foundry

So I want to connect my Orion instance on orionhub.org with my account at Pivotal CF. This way I can get some coding done, while on the go or boring meetings and telcos.

However somehow it wasn’t that intuitive to connect my Pivotal CF environment with orionhub. So here is an instruction on how to get it done.

    1. Log on to orionhub.com
    2. Go to Settings > Cloud Foundry
    3. Enter the following info:
    4. Create a Launch Configuration
      You will be asked to enter your credentials for pivotal.io and some Configuration. That’s it 🙂
    5. Off you go!

 

Get a formatted date in UNIX

Here are a set of quick commands on getting a formatted Date to be used in timestamping some files:

Simple Date

date +%Y-%m-%d

Results in:
2017-03-31

Simple Date and Time

date +%Y-%m-%d_%H-%M-%S

Results in:
2017-03-31_18-14-04

Timestamping a file

So if you like to timestamp a file you can just do the following:

mv someFile someFile_`date +%Y-%m-%d_%H-%M-%S`

If you ls afterwards, you have a nicely timestamped file:
someFile_2017-03-31_18-18-25

Nice!

My ZSH profile

# Lines configured by zsh-newuser-install
HISTFILE=~/.histfile
HISTSIZE=1000
SAVEHIST=1000
setopt autocd extendedglob
bindkey -v
# End of lines configured by zsh-newuser-install
# The following lines were added by compinstall
zstyle :compinstall filename '/opt/webMethods9/wm5511/.zshrc'
autoload -Uz compinit
compinit
# End of lines added by compinstall
PROMPT='[%n@%m:%~]%% '
alias ll='ls -la'
alias ls='ls --color=auto'
alias la='ls -a'
alias ..='cd ..'
view raw .zshrc hosted with ❤ by GitHub

Apache Wicket 6.19.0 PermGen OutOfMemoryException

Phew…. This one came as a surprise. The application I am busy with at one of my clients uses Apache Wicket 6. So some fine day in the winter of 2015. We did a lib upgrade on this project. And so we moved from Apache Wicket 6.19 to 6.20.

During the tests I noticed that somehow those OutOfMemoryException in the PermGen started to creep up occasionally.It happened twice during the 2month long tests, so I just hoped. That it may not occur at all in Production as these servers there have more heap and more PermGen space. 

No two weeks later, the production  management started calling me on those OutOfMemoryExceptions on their production machines. As a remedy the servers got restarted every morning. However this still kind of sucked. So I did some load tests and with the jvisualvm I could see that the PermGen usage kept on increasing. I switched back to the old code and repeated the test. Here the PermGen was stable! Now I started to go through my standard suspects and in the end I was surprised to see, that the error was in the upgrade from Apache Wicket 6.19 to 6.20.

Luckily this issue was found by the Apache Wicket team too and they have it fixed in the 6.21 release (Wicket-5978: LazyInitProxyFactory fills permgen space).