How to develop Tomcat-based WebSocket application on Heroku
Overview
When we want to develop WebSocket application based on Java, Tomcat is a good fit because Tomcat 7 and onwards support WebSocket in default. Nevertheless, Tomcat deployed on Heroku Cloud PaaS needs slight tweaks.
There are two existing solutions:
- Embedded Tomcat: https://devcenter.heroku.com/articles/create-a-java-web-application-using-embedded-tomcat
 - Webapp Runner: https://devcenter.heroku.com/articles/java-webapp-runner
 
Unfortunately, those two solutions don't work for WebSocket applications that work under standard tomcat.
The Reason why exisiting solutions don't work
The critical part makes WebSocket up and running in Tomcat is two jars under lib directory -- websocket-api.jar and tomcat7-websocket.jar, they are the implementation of JSR 356, Java API for WebSocket, the link tells the details, http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html.
If we can find those two or stuff like that with regard to dependencies required by above solutions, they are supposed most likely to work.
If we can find those two or stuff like that with regard to dependencies required by above solutions, they are supposed most likely to work.
Let's check embedded tomcat solution at first, run following command against dependencies:
The result shows noting is related to JSR 356.
Let's run another command to see the contents inside the jars:
Again, the result shows nothing is related to JSR 356.
Let's check Webapp Runner solution secondly, there is only one dependency, which obviously are not directly related to WebSocket. Therefore, run following command against dependencies to check contents inside:
Although the result shows something like WebSocket, they are not relevant to the JSR 356. Those are not compatible to the standard Tomcat WebSocket implementation.
 find . -name *.jar | grep websocket  
The result shows noting is related to JSR 356.
Let's run another command to see the contents inside the jars:
 find . -name *.jar | xargs -L 1 jar tvf | grep websocket  
Again, the result shows nothing is related to JSR 356.
Let's check Webapp Runner solution secondly, there is only one dependency, which obviously are not directly related to WebSocket. Therefore, run following command against dependencies to check contents inside:
 jar tvf webapp-runner.jar | grep websocket  
    0 Wed Aug 22 14:35:46 NZST 2012 org/jboss/netty/handler/codec/http/websocket/  
    0 Wed Aug 22 14:35:46 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/  
  2730 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocket/DefaultWebSocketFrame.class  
   897 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocket/WebSocketFrame.class  
  3158 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocket/WebSocketFrameDecoder.class  
  2651 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocket/WebSocketFrameEncoder.class  
  1504 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/BinaryWebSocketFrame.class  
  2690 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/CloseWebSocketFrame.class  
  2718 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/ContinuationWebSocketFrame.class  
  1507 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/PingWebSocketFrame.class  
  1498 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/PongWebSocketFrame.class  
  2414 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/TextWebSocketFrame.class  
   493 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/UTF8Exception.class  
  3619 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/UTF8Output.class  
  3725 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.class  
  2774 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocket00FrameEncoder.class  
  1136 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder$1.class  
  1509 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder$State.class  
  10107 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.class  
  4684 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocket08FrameEncoder.class  
   657 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocket13FrameDecoder.class  
   473 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocket13FrameEncoder.class  
  2810 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.class  
  8647 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.class  
  7844 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.class  
  7841 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.class  
  2980 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.class  
  1117 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketFrame.class  
  1410 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketFrameType.class  
   708 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketHandshakeException.class  
  1160 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker$1.class  
  3420 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.class  
  6518 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.class  
  6352 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.class  
  6354 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.class  
  3144 Wed Aug 22 14:35:12 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.class  
  2011 Wed Aug 22 14:35:10 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketUtil.class  
  1794 Wed Aug 22 14:35:08 NZST 2012 org/jboss/netty/handler/codec/http/websocketx/WebSocketVersion.class  
Although the result shows something like WebSocket, they are not relevant to the JSR 356. Those are not compatible to the standard Tomcat WebSocket implementation.
The workaround solution
After having a close look at the embedded solution, we find embedded tomcat comprises of several sub modules. Let's check whether WebSocket is one of sub modules, if so, the rescue comes true.
The embedded WebSocket module does exist:
 <dependency>  
   <groupId>org.apache.tomcat.embed</groupId>  
   <artifactId>tomcat-embed-websocket</artifactId>  
   <version>${tomcat.version}</version>  
 </dependency>
After adding this dependency into the solution one, the WebSocket application working under standard tomcat also works by Embedded Tomcat.
A GitHub Example
You can find this github repository: https://github.com/Bo-Ye/heroku-tomcat-websocket to deploy onto Heroku. This project is a complete example to demonstrate this workable solution. Run following commands to deploy this project onto Heroku. $ heroku create heroku-tomcat-websocket  
 Creating heroku-tomcat-websocket... done, stack is cedar-14  
 https://heroku-tomcat-websocket.herokuapp.com/ | https://git.heroku.com/heroku-tomcat-websocket.git  
 Git remote heroku added  
 $ git push heroku master  
 Counting objects: 60, done.  
 Delta compression using up to 4 threads.  
 Compressing objects: 100% (41/41), done.  
 Writing objects: 100% (60/60), 6.19 KiB | 0 bytes/s, done.  
 Total 60 (delta 11), reused 0 (delta 0)  
 remote: Compressing source files... done.  
 remote: Building source:  
 remote:   
 remote: -----> Java app detected  
 remote: -----> Installing OpenJDK 1.8... done  
 remote: -----> Installing Maven 3.3.9... done  
 remote: -----> Executing: mvn -B -DskipTests clean dependency:list install  
 remote:    [INFO] Scanning for projects...  
 $ heroku open  
 Opening heroku-tomcat-websocket... done  
This example features the browser is getting random messages per second form the backend through Get Messages button and stops getting messages through Stop Messages button.
![]()  | 
| Tomcat-based WebSocket on Heroku | 
Happy coding!

You are right that tomcat-based application will not work. I wan't to propose solution using Embedded Jetty:
ReplyDeletehttp://privateblog.info/heroku-com-kak-poluchit-realizaciyu-websockets-na-java-jsr-365-podxod/