Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Dynos (app containers)
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Command Line
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery
    • Continuous Integration
  • Language Support
    • Node.js
    • Ruby
      • Working with Bundler
      • Rails Support
    • Python
      • Background Jobs in Python
      • Working with Django
    • Java
      • Working with Maven
      • Java Database Operations
      • Working with the Play Framework
      • Working with Spring Boot
      • Java Advanced Topics
    • PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
    • Heroku Data For Redis
    • Apache Kafka on Heroku
    • Other Data Stores
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
    • Compliance
  • Heroku Enterprise
    • Private Spaces
      • Infrastructure Networking
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Single Sign-on (SSO)
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Language Support
  • Java
  • Working with the Play Framework
  • Using WebSockets on Heroku with Java and the Play Framework

Using WebSockets on Heroku with Java and the Play Framework

English — 日本語に切り替える

Last updated February 09, 2022

Table of Contents

  • Prerequisites
  • Create WebSocket app
  • Functionality
  • Deploy
  • Scaling
  • References

This tutorial demonstrates how to build a Java and Play Framework application that uses a WebSocket, deployed to Heroku.

Sample code for the demo application is available on GitHub. Edits and enhancements are welcome. Just fork the repository, make your changes and send us a pull request.

Prerequisites

  • Java, Play Framework 2.x, and the Heroku CLI (as described in the Heroku CLI setup article)
  • A Heroku user account. Signup is free and instant.

Create WebSocket app

The sample application provides a simple example of using a WebSocket with Java and Play. You can clone the sample and follow along with the code as you read. If you’d rather write the app yourself you can add the sample code to a new Play app as you go.

Option 1. Clone the sample app

If you want to get going more quickly you can just clone the sample app:

$ git clone git@github.com:heroku-examples/play-websockets-sample.git
Cloning into 'play-websockets-sample'...
remote: Counting objects: 31, done.
remote: Compressing objects: 100% (24/24), done.
remote: Total 31 (delta 0), reused 31 (delta 0)
Receiving objects: 100% (31/31), 38.33 KiB | 0 bytes/s, done.
Checking connectivity... done

Option 2. Create a new Play app

$ play new
       _
 _ __ | | __ _ _  _
| '_ \| |/ _' | || |
|  __/|_|\____|\__ /
|_|            |__/

play 2.2.0 built with Scala 2.10.2 (running Java 1.6.0_51), http://www.playframework.com

The new application will be created in /Users/jsimone/dev/supportApps/play22test
...

Choose an application name and Java as the language.

Functionality

The sample application renders a simple web page that will open a WebSocket to the backend. The server will send a payload containing the time over the WebSocket once a second. That time will be displayed on the page.

There are 3 important pieces to the interaction that takes place here: a controller method that returns a WebSocket object, a JavaScript method that opens that WebSocket, and an Akka actor that sends the payload across that WebSocket every second. Let’s explore each.

Controller

You can return a WebSocket from a Play controller method.

There is an example in /app/controllers/Application.java in the sample application:

public static WebSocket<String> pingWs() {
    return new WebSocket<String>() {
        public void onReady(WebSocket.In<String> in, WebSocket.Out<String> out) {
            final ActorRef pingActor = Akka.system().actorOf(Props.create(Pinger.class, in, out));
            final Cancellable cancellable = Akka.system().scheduler().schedule(Duration.create(1, SECONDS),
                                               Duration.create(1, SECONDS),
                                               pingActor,
                                               "Tick",
                                               Akka.system().dispatcher(),
                                               null
                                               );

            in.onClose(new Callback0() {
                @Override
                public void invoke() throws Throwable {
                    cancellable.cancel();
                }
            });
        }

    };
}

public static Result pingJs() {
    return ok(views.js.ping.render());
}

public static Result index() {
    return ok(index.render());
}

This method returns a new WebSocket object that has a String as its payload. In the WebSocket object we define the onReady() method to talk to an actor via the Akka scheduler. The work of sending data over the socket will occur in that actor. When the WebSocket is closed the callback registered on the input stream will be called.

The other methods will render our js and html templates.

We’ll also need a route to be set up for these methods in our routes file:

# Home page
GET     /                           controllers.Application.index()
GET     /pingWs                     controllers.Application.pingWs()
GET     /assets/javascripts/ping.js controllers.Application.pingJs()

Model

In the controller example you’ll notice that we pass around the in and out streams of the WebSocket. In our actor we’re able to read from and write to these streams just like any other IO stream. Here’s the code for the Pinger actor (/app/models/Pinger.java):

package models;

public class Pinger extends UntypedActor {
    WebSocket.In<String> in;
    WebSocket.Out<String> out;

    public Pinger(WebSocket.In<String> in, WebSocket.Out<String> out) {
        this.in = in;
        this.out = out;
    }

    @Override
    public void onReceive(Object message) {
        if (message.equals("Tick")) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Calendar cal = Calendar.getInstance();
            out.write(sdf.format(cal.getTime()));
        } else {
            unhandled(message);
        }
    }
}

You’ll notice that this actor counts on the schedule defined in the controller method to send it a “Tick” message every second. When that happens it sends the current date and time over the WebSocket.

Views

The final piece is the client code that will call the WebSocket. For this our sample application uses Scala templates to render JavaScript and HTML called /app/views/ping.scala.js and /app/views/index.scala.html respectively.

index.scala.html provides a div to display the data in and references the JavaScript:

@main("Welcome to Play") {

    <strong>Stats</strong><br>
    <div id="ping"></div>

   <script type="text/javascript" charset="utf-8" src="@routes.Application.pingJs()"></script>
}

ping.scala.js connects to the WebSocket and defines the receiveEvent method to populate the dates into the displayed div as they come across:

$(function() {
    var WS = window['MozWebSocket'] ? MozWebSocket : WebSocket
    var dateSocket = new WS("@routes.Application.pingWs().webSocketURL(request)")

    var receiveEvent = function(event) {
        $("#ping").html("Last ping: "+event.data);
    }

    dateSocket.onmessage = receiveEvent
})

Deploy

It’s time to deploy your app to Heroku. If you haven’t done so already put your application into a git repository:

$ git init
$ git add .
$ git commit -m "Ready to deploy"

Create the Heroku app to deploy to:

$ heroku create
Creating high-lightning-129... done, stack is heroku-18
http://high-lightning-129.herokuapp.com/ | git@heroku.com:high-lightning-129.git
Git remote heroku added

Deploy your code with git push.

$ git push heroku master
Counting objects: 31, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (24/24), done.
Writing objects: 100% (31/31), 38.33 KiB | 0 bytes/s, done.
Total 31 (delta 0), reused 0 (delta 0)

-----> Play 2.x - Java app detected
-----> Installing OpenJDK 1.6...done
-----> Building app with sbt
-----> Running: sbt clean compile stage
       Getting org.scala-sbt sbt 0.13.0 ...
       downloading http://s3pository.heroku.com/ivy-typesafe-releases/org.scala-sbt/sbt/0.13.0/jars/sbt.jar ...
  [SUCCESSFUL ] org.scala-sbt#sbt;0.13.0!sbt.jar (416ms)
...
       [info] Done packaging.
       [success] Total time: 7 s, completed Sep 29, 2013 7:51:08 PM
-----> Dropping ivy cache from the slug
-----> Discovering process types
       Procfile declares types -> web

-----> Compiled slug size: 117.3MB
-----> Launching... done, v6
       http://still-hamlet-4310.herokuapp.com deployed to Heroku

Congratulations! Your web app should now be up and running on Heroku. Visit the application to see it in action:

$ heroku open

Scaling

This app demonstrates simple usage of a WebSocket. For production use, and any app that requires more than a single web dyno, please read about building a scalable app with WebSockets.

References

  • The WebSocket documentation

Keep reading

  • Working with the Play Framework

Feedback

Log in to submit feedback.

Writing Scalable WebSocket Applications on Heroku with Java and the Play Framework Writing Scalable WebSocket Applications on Heroku with Java and the Play Framework

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences