index.html 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>STOMP Over WebSocket</title>
  6. <!--[if IE]>
  7. <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  8. <![endif]-->
  9. <link rel=stylesheet href=screen.css>
  10. <link rel=alternate type=application/atom+xml href=http://github.com/feeds/jmesnil/commits/stomp-websocket/master>
  11. </head>
  12. <body>
  13. <header>
  14. <h1>STOMP Over WebSocket</h1>
  15. </header>
  16. <p id="toc">&nbsp;</p>
  17. <section>
  18. <h2 id=stomp>What is STOMP?</h2>
  19. <p><img src=i/johnny_automatic/johnny_automatic_elephant_climbing.svg></p>
  20. <p><a href=http://stomp.github.com/>STOMP</a> is a simple text-orientated messaging protocol.
  21. It defines an <a href=http://stomp.github.com/stomp-specification-1.1.html>interoperable wire format</a>
  22. so that any of the available STOMP clients can communicate with any STOMP message broker to provide easy and widespread
  23. messaging interoperability among languages and platforms (the STOMP web site has a <a href=http://stomp.github.com/implementations.html>list of STOMP client and server implementations</a>.</p>
  24. </section>
  25. <section>
  26. <h2 id=websockets>What is the WebSocket API?</h2>
  27. <p class=ss style="width:248px"><img width=248 src=i/johnny_automatic/johnny_automatic_follow_the_leader.svg><br>
  28. <span id=live-web-sockets></span></p>
  29. <p><a href=http://dev.w3.org/html5/websockets/>WebSockets</a> are "TCP for the Web".</p>
  30. <p>When Google announced the availability of
  31. <a href=http://blog.chromium.org/2009/12/web-sockets-now-available-in-google.html>WebSocket in Google Chrome</a>,
  32. it explained the idea behind WebSockets:</p>
  33. <blockquote>
  34. <p>The WebSocket API enables web applications to handle bidirectional communications
  35. with server-side process in a straightforward way. Developers have been using XMLHttpRequest
  36. ("XHR") for such purposes, but XHR makes developing web applications that communicate back
  37. and forth to the server unnecessarily complex. XHR is basically asynchronous HTTP,
  38. and because you need to use a tricky technique like long-hanging GET for sending data
  39. from the server to the browser, simple tasks rapidly become complex. As opposed to XMLHttpRequest,
  40. WebSockets provide a real bidirectional communication channel in your browser.
  41. Once you get a WebSocket connection, you can send data from browser to server by calling
  42. a send() method, and receive data from server to browser by an onmessage event handler.</p>
  43. <p>In addition to the new WebSocket API, there is also a new protocol
  44. (the "WebSocket Protocol") that the browser uses to communicate with servers.
  45. The protocol is not raw TCP because it needs to provide the browser's "same-origin"
  46. security model. It's also not HTTP because WebSocket traffic differers from HTTP's
  47. request-response model. WebSocket communications using the new WebSocket protocol
  48. should use less bandwidth because, unlike a series of XHRs and hanging GETs,
  49. no headers are exchanged once the single connection has been established. To use this new
  50. API and protocol and take advantage of the simpler programming model and more
  51. efficient network traffic, you do need a new server implementation to communicate
  52. with.</p>
  53. </blockquote>
  54. <p>The API is part of <a href=>HTML5</a> and is supported (<a href=http://en.wikipedia.org/wiki/WebSocket#Browser_support>at various degree...</a>) by most modern Web Browsers (including Google Chrome, Firefox and Safari on Mac OS X and iOS).</p>
  55. </section>
  56. <section>
  57. <h2 id=protocols>Protocol Support</h2>
  58. <p>This library supports multiple version of STOMP protocols:
  59. <ul>
  60. <li><a href=http://stomp.github.com/stomp-specification-1.0.html>STOMP 1.0</a>
  61. <li><a href=http://stomp.github.com/stomp-specification-1.1.html>STOMP 1.1<a> (including <a href=#heartbeat>heart-beating</a>)
  62. </ul>
  63. <h2 id=requirements>Server Requirements</h2>
  64. <p>This library is not a <em>pure</em> STOMP client. It is aimed to run on the WebSockets protocol which
  65. is not TCP. Basically, the WebSocket protocol requires a <em>handshake</em> between the browser's
  66. client and the server to ensure the browser's "same-origin" security model remains in effect.</p>
  67. <p>This means that this library can not connect to regular STOMP brokers since they would not understand
  68. the handshake initiated by the WebSocket which is not part of the STOMP protocol and would
  69. likely reject the connection.</p>
  70. <p>There are ongoing works to add WebSocket support to STOMP broker so that they will accept STOMP connections over
  71. the WebSocket protocol.</p>
  72. <h3 id=hornetq>HornetQ</h3>
  73. <p><a href=http://jboss.org/hornetq>HornetQ</a> is the Open Source messaging system developed
  74. by Red Hat and JBoss.</p>
  75. <p>To start HornetQ with support for STOMP Over WebSocket, <a href=http://www.jboss.org/hornetq/downloads.html>download the latest version</a> and run the following steps:</p>
  76. <pre>
  77. <samp>$ </samp><kbd>cd hornetq-x.y.z/examples/jms/stomp-websockets</kbd>
  78. <samp>$ </samp><kbd>mvn clean install</kbd>
  79. <samp>...
  80. INFO: HQ221020: Started Netty Acceptor version 3.6.2.Final-c0d783c localhost:61614 for STOMP_WS protocol
  81. Apr 15, 2013 1:15:33 PM org.hornetq.core.server.impl.HornetQServerImpl$SharedStoreLiveActivation run
  82. INFO: HQ221007: Server is now live
  83. Apr 15, 2013 1:15:33 PM org.hornetq.core.server.impl.HornetQServerImpl start
  84. INFO: HQ221001: HornetQ Server version 2.3.0.CR2 (black'n'yellow2, 123) [c9e29e45-a5bd-11e2-976a-b3fef7ceb5df]</samp>
  85. </pre>
  86. <p>HornetQ is now started and listens to STOMP over WebSocket on the port <code>61614</code>.<br>
  87. It accepts <em>WebSocket connections</em> from the URL <code>ws://localhost:61614/stomp</code></p>
  88. </section>
  89. <p>To configure and run HornetQ with STOMP Over WebSocket enabled, follow the
  90. <a href=http://docs.jboss.org/hornetq/2.3.0.CR2/docs/user-manual/html/interoperability.html#stomp.websockets>instructions</a>.</p>
  91. <h3 id=activemq>ActiveMQ</h3>
  92. <p><a href=http://activemq.apache.org>ActiveMQ</a> is the Open Source messaging system developed by Apache.
  93. Starting with 5.4 snapshots, ActiveMQ supports STOMP Over WebSocket.</p>
  94. <p>To configure and run ActiveMQ with STOMP Over WebSocket enabled, follow the
  95. <a href=http://activemq.apache.org/websockets.html>instructions</a>.</p>
  96. <h3 id=apollo>ActiveMQ Apollo</h3>
  97. <p><a href=http://activemq.apache.org/apollo/>ActiveMQ Apollo</a> is the next generation of ActiveMQ broker.
  98. From the start, Apollo supports STOMP Over WebSocket.</p>
  99. <p>To configure and run Apollo with STOMP Over WebSocket enabled, follow the
  100. <a href=http://activemq.apache.org/apollo/documentation/user-manual.html#WebSocket_Transports>instructions</a>.</p>
  101. <h3 id=rabbitmq>RabbitMQ</h3>
  102. <p><a href=http://www.rabbitmq.com/>RabbitMQ</a> is Open Source messaging system sponsored by VMware.
  103. <p>To configure and run RabbitMQ with STOMP Over WebSocket enabled, follow the instructions to install the <a href=http://www.rabbitmq.com/web-stomp.html>Web-Stomp plugin</a>.</p>
  104. <h3 id=stilts>Stilts &amp; Torquebox</h3>
  105. <p><a href=http://stilts.projectodd.org/>Stilts</a> is a STOMP-native messaging framework which aims to address treating STOMP as primary contract for messaging, and integrating around it, instead of simply applying STOMP shims to existing services.
  106. <p><a href=http://torquebox.org/>TorqueBox</a> uses the Stilts project to provide its <a href=http://torquebox.org/documentation/2.1.2/stomp.html>WebSockets and STOMP stack</a>.
  107. <section>
  108. <h2 id=download>Download stomp.js JavaScript file</h2>
  109. <p>You can download <a href="https://raw.github.com/jmesnil/stomp-websocket/master/lib/stomp.js">stomp.js</a> to use it in your Web applications</p>
  110. <p>A <a href="https://raw.github.com/jmesnil/stomp-websocket/master/lib/stomp.min.js">minified version</a> is also provided to be used in production.
  111. <p>This JavaScript file is generated from <a href=http://jashkenas.github.com/coffee-script/>CoffeeScript</a> files. See the <a href=#contribute>Contribute</a> section to download the source code or browse the <a href="stomp.html">annotated source code</a>.
  112. <h2 id=api>STOMP API</h2>
  113. <h3 id=frame>STOMP Frame</h3>
  114. <p>STOMP Over WebSocket provides a straightforward mapping from a STOMP frame to a JavaScript
  115. object.</p>
  116. <table class=st>
  117. <caption>Frame Object</caption>
  118. <tr class=ho><th>Property<th>Type<th>Notes
  119. <tr class=zebra><th><code>command</code><td>String<td>name of the frame (<code>"CONNECT"</code>, <code>"SEND"</code>, etc.)
  120. <tr><th><code>headers</code><td>JavaScript object<td>
  121. <tr class=zebra><th><code>body</code><td>String<td>
  122. </table>
  123. <p>The <code>command</code> and <code>headers</code> properties will always be defined
  124. but the <code>headers</code> can be empty if the frame has no headers.
  125. The <code>body</code> can be <code>null</code> if the frame does not have a body.</p>
  126. <h3 id=client>Create a STOMP client</h3>
  127. <h4 id=clientws>In a Web browser with regular Web Socket</h4>
  128. <p>STOMP JavaScript clients will communicate to a STOMP server using a <code>ws://</code> URL.</p>
  129. <p>To create a STOMP client JavaScript object, you need to call <code>Stomp.client(url)</code>
  130. with the URL corresponding to the server's WebSocket endpoint:
  131. <pre><code>
  132. var url = "ws://localhost:61614/stomp";
  133. var client = <mark>Stomp.client(url)</mark>;
  134. </code></pre>
  135. <p>The <code>Stomp.client(url, protocols)</code> can also be used to override the default subprotocols provided by the library: <code>['v10.stomp', 'v11.stomp]'</code> (for STOMP 1.0 &amp; 1.1 specifications). This second argument can either be a single string or an array of strings to specify multiple subprotocols.
  136. <h4 id=alternative>In the Web browser with a custom WebSocket</h3>
  137. <p>Web browsers supports different versions of the WebSocket protocol. Some older browsers does not provide the WebSocket JavaScript or expose it under another name. By default, <code>stomp.js</code> will use the Web browser native <code>WebSocket</code> class to create the WebSocket.
  138. <p>However it is possible to use other type of WebSockets by using the <code>Stomp.over(ws)</code> method.
  139. This method expects an object that conforms to the WebSocket definition.
  140. <p>For example, it is possible to use the implementation provided by the <a href=https://github.com/sockjs/sockjs-client>SockJS</a> project which falls back to a variety of browser-specific transport protocols instead:
  141. <pre><code>
  142. &lt;script src="http://cdn.sockjs.org/sockjs-0.3.min.js">&lt;/script>
  143. &lt;script>
  144. // use SockJS implementation instead of the browser's native implementation
  145. var ws = new SockJS(url);
  146. var client = <mark>Stomp.over(ws)</mark>;
  147. [...]
  148. &lt;/script>
  149. </code></pre>
  150. <p>Use <code>Stomp.client(url)</code> to use regular WebSockets or use <code>Stomp.over(ws)</code> if you required another type of WebSocket.
  151. <p>Apart from this initialization, the STOMP API remains the same in both cases.
  152. <h4 id=nodejs>In a node.js application</h3>
  153. <p>The library can also be used in <a href="http://nodejs.org">node.js</a> application by using the
  154. <a href="https://npmjs.org/package/stompjs">stompjs npm package</a>.
  155. <pre>
  156. <samp>$ </samp><kbd>npm install <mark>stompjs</mark></kbd>
  157. </pre>
  158. <p>In the node.js app, require the module with:
  159. <pre><code>
  160. var <mark>Stomp</mark> = require(<mark>'stompjs'</mark>);
  161. </code></pre>
  162. <p>To connect to a STOMP broker over a <em>TCP socket</em>, use the <code>Stomp.overTCP(host, port)</code> method:
  163. <pre><code>
  164. var client = Stomp.<mark>overTCP</mark>('localhost', 61613);
  165. </code></pre>
  166. <p>To connect to a STOMP broker over a <em>Web Socket</em>, use instead the <code>Stomp.overWS(url)</code> method:
  167. <pre><code>
  168. var client = Stomp.<mark>overWS</mark>('ws://localhost:61614/stomp');
  169. </code></pre>
  170. <p>Apart from this initialization, the STOMP API remains the same whether it is running in a Web browser or in node.js application.
  171. <h3 id=connection>Connection to the server</h3>
  172. <p>Once a STOMP client is created, it must call its <code>connect()</code> method to effectively
  173. connect and authenticate to the STOMP server. The method takes two mandatory arguments,
  174. <code>login</code> and <code>passcode</code> corresponding to the user credentials.</p>
  175. <p>Behind the scene, the client will open a connection using a WebSocket and send
  176. a <a href=http://stomp.github.com/stomp-specification-1.1.html#CONNECT_or_STOMP_Frame>CONNECT</a> frame.</p>
  177. <p>The connection is done asynchronously: you have no guarantee to be effectively connected when
  178. the call to <code>connect</code> returns. To be notified of the connection, you need to pass a
  179. <code>connect_callback</code> function to the <code>connect()</code> method:</p>
  180. <pre><code>
  181. <mark>var connect_callback</mark> = function() {
  182. // called back after the client is connected and authenticated to the STOMP server
  183. };
  184. </code></pre>
  185. <p>But what happens if the connection fails? the <code>connect()</code> method accepts an
  186. optional <code>error_callback</code> argument which will be called if the client is not able
  187. to connect to the server.
  188. The callback will be called with a single argument, an error object corresponding to STOMP
  189. <a href=http://stomp.github.com/stomp-specification-1.1.html#ERROR>ERROR</a> frame:</p>
  190. <pre><code>
  191. <mark>var error_callback</mark> = function(error) {
  192. // display the error's message header:
  193. alert(error.headers.message);
  194. };
  195. </code></pre>
  196. <p>The <code>connect()</code> method accepts different number of arguments to provide a simple API to use in most cases:
  197. <pre><code>
  198. <mark>client.connect</mark>(login, passcode, connectCallback);
  199. <mark>client.connect</mark>(login, passcode, connectCallback, errorCallback);
  200. <mark>client.connect</mark>(login, passcode, connectCallback, errorCallback, host);
  201. </code></pre>
  202. <p>where <code>login</code>, <code>passcode</code> are strings and <code>connectCallback</code> and <code>errorCallback</code> are functions
  203. (some brokers also require to pass a <a href=http://stomp.github.io/stomp-specification-1.1.html#CONNECT_or_STOMP_Frame>host</a> String).
  204. <p>The <code>connect()</code> method also accepts two other variants if you need to pass additional headers:
  205. <pre><code>
  206. <mark>client.connect</mark>(headers, connectCallback);
  207. <mark>client.connect</mark>(headers, connectCallback, errorCallback);
  208. </code></pre>
  209. <p>where <code>header</code> is a map and <code>connectCallback</code> and <code>errorCallback</code> are functions.
  210. <p>Please note that if you use these forms, you <strong>must</strong> add the <code>login</code>, <code>passcode</code> (and eventually <code>host</code>)
  211. headers yourself:
  212. <pre><code>
  213. var <mark>headers</mark> = {
  214. login: 'mylogin',
  215. passcode: 'mypasscode',
  216. // additional header
  217. 'client-id': 'my-client-id'
  218. };
  219. client.connect(<mark>headers</mark>, connectCallback);
  220. </code></pre>
  221. <p>To disconnect a client from the server, you can call its <code>disconnect()</code> method.
  222. The disconnection is asynchronous: to be notified when the disconnection is effective,
  223. the <code>disconnect</code> method takes an optional <code>callback</code> argument.</p>
  224. <pre><code>
  225. <mark>client.disconnect</mark>(function() {
  226. alert("See you next time!");
  227. };
  228. </code></pre>
  229. <p>When a client is disconnected, it can no longer send or receive messages.</p>
  230. <h3 id=heartbeat>Heart-beating</h3>
  231. <p>If the STOMP broker accepts STOMP 1.1 frames, <a href=>heart-beating</a> is enabled by default.
  232. <p>The <code>client</code> object has a <code>heartbeat</code> field which can be used to configure heart-beating by changing its <code>incoming</code> and <code>outgoing</code> integer fields (default value for both is <code>10000</code>ms):
  233. <pre><code>
  234. client.<mark>heartbeat.outgoing</mark> = 20000; // client will send heartbeats every 20000ms
  235. client.<mark>heartbeat.incoming</mark> = 0; // client does not want to receive heartbeats
  236. // from the server
  237. </code></pre>
  238. <p>The heart-beating is using <code>window.setInterval()</code> to regularly send heart-beats and/or check server heart-beats.
  239. <h3 id=send>Send messages</h3>
  240. <p>When the client is connected to the server, it can send STOMP messages using
  241. the <code>send()</code> method. The method takes a mandatory <code>destination</code>
  242. argument corresponding to the STOMP destination. It also takes two optional
  243. arguments: <code>headers</code>, a JavaScript object containing additional
  244. message headers and <code>body</code>, a String object.</p>
  245. <pre><code>
  246. <mark>client.send</mark>("/queue/test", {priority: 9}, "Hello, STOMP");
  247. </code></pre>
  248. <p>The client will send a STOMP
  249. <a href=http://stomp.github.com/stomp-specification-1.1.html#SEND>SEND</a> frame to <code>/queue/test</code> destination
  250. with a header <code>priority</code> set to <code>9</code> and a body <code>Hello, STOMP</code>.</p>
  251. <div class=advice>
  252. <img style="float:left" width=120 src="i/johnny_automatic/johnny_automatic_advise_from_the_doctor.svg">
  253. <p>If you want to send a message with a body, you <em>must</em> also pass the <code>headers</code>
  254. argument. If you have no headers to pass, use an empty JavaScript literal <code>{}</code>:</p>
  255. <pre><code>
  256. client.send(destination, <mark>{}</mark>, body);
  257. </code></pre>
  258. </div>
  259. <h3 id=subscribe>Subscribe and receive messages</h3>
  260. <p>To receive messages in the browser, the STOMP client must first subscribe to a destination.</p>
  261. <p>You can use the <code>subscribe()</code> method to subscribe to a destination. The method takes 2 mandatory
  262. arguments: <code>destination</code>, a String corresponding to the destination and
  263. <code>callback</code>, a function with one <code>message</code> argument
  264. and an <em>optional</em> argument <code>headers</code>, a JavaScript object for additional headers.
  265. <pre><code>
  266. var subscription = <mark>client.subscribe</mark>("/queue/test", callback);
  267. </code></pre>
  268. <p>The <code>subscribe()</code> methods returns a JavaScript obect with 1 attribute, <code>id</code>, that correspond to the client subscription ID
  269. and one method <code>unsubscribe()</code> that can be used later on to unsubscribe the client from this destination.</p>
  270. <p>By default, the library will generate an unique ID if there is none provided in the headers. To use your own ID, pass it using the <code>headers</code> argument:
  271. <pre><code>
  272. var mysubid = '...';
  273. var subscription = client.subscribe(destination, callback, <mark>{ id: mysubid }</mark>);
  274. </code></pre>
  275. <p>The client will send a STOMP
  276. <a href=http://stomp.github.com/stomp-specification-1.1.html#SUBSCRIBE>SUBSCRIBE</a> frame to the server
  277. and register the callback. Every time the server
  278. send a message to the client, the client will in turn call the callback with a STOMP Frame object
  279. corresponding to the message:</p>
  280. <pre><code>
  281. <mark>callback</mark> = function(message) {
  282. // called when the client receives a STOMP message from the server
  283. if (message.body) {
  284. alert("got message with body " + message.body)
  285. } else {
  286. alert("got empty message");
  287. }
  288. });
  289. </code></pre>
  290. <p>The <code>subscribe()</code> method takes an optional <code>headers</code> argument to specify
  291. additional headers when subscribing to a destination:</p>
  292. <pre><code>
  293. var headers = {ack: 'client', 'selector': "location = 'Europe'"};
  294. client.subscribe("/queue/test", message_callback, <mark>headers</mark>);
  295. </code></pre>
  296. <p>The client specifies that it will handle the message acknowledgement and is interested to receive
  297. only messages matching the selector <code>location = 'Europe'</code>.</p>
  298. <div class=advice>
  299. <img style="float:left" width=120 src="i/johnny_automatic/johnny_automatic_advise_from_the_doctor.svg">
  300. <p>If you want to subscribe the client to multiple destinations, you can use the same callback to receive all
  301. the messages:</p>
  302. <pre style="clear:left"><code>
  303. onmessage = function(message) {
  304. // called every time the client receives a message
  305. }
  306. var sub1 = client.subscribe("queue/test", <mark>onmessage</mark>);
  307. var sub2 = client.subscribe("queue/another", <mark>onmessage</mark>);
  308. </code></pre>
  309. </div>
  310. <p>To stop receiving messages, the client can use the <code>unsubscribe()</code> method on the object returned by the <code>subscribe()</code>
  311. method.</p>
  312. <pre><code>
  313. var subscription = client.subscribe(...);
  314. ...
  315. <mark>subscription.unsubscribe</mark>();
  316. </code></pre>
  317. <h3 id=json>JSON support</h3>
  318. <p>The body of a STOMP message must be a <code>String</code>. If you want to send and receive
  319. <a href=http://json.org/>JSON</a> objects, you can use <code>JSON.stringify()</code> and <code>JSON.parse()</code> to transform the JSON
  320. object to a String and vice versa.</p>
  321. <pre><code>
  322. var quote = {symbol: 'APPL', value: 195.46};
  323. client.send("/topic/stocks", {}, <mark>JSON.stringify(quote)</mark>);
  324. client.subcribe("/topic/stocks", function(message) {
  325. var quote = <mark>JSON.parse(message.body)</mark>;
  326. alert(quote.symbol + " is at " + quote.value);
  327. };
  328. </code></pre>
  329. <h3 id=ack>Acknowledgment</h3>
  330. <p>By default, STOMP messages will be automatically acknowledged by the server before the message
  331. is delivered to the client.</p>
  332. <p>The client can chose instead to handle message <a href=http://stomp.github.com/stomp-specification-1.1.html#SUBSCRIBE_ack_Header>acknowledgement</a> by subscribing to a destination and
  333. specify a <code>ack</code> header set to <code>client</code> or <code>client-individual</code>.</p>
  334. <p>In that case, the client must use the <code>message.ack()</code> method to inform the server that it has
  335. acknowledge the message.</p>
  336. <pre><code>
  337. var subscription = client.subscribe("/queue/test",
  338. function(message) {
  339. // do something with the message
  340. ...
  341. // and acknowledge it
  342. <mark>message.ack()</mark>;
  343. },
  344. <mark>{ack: 'client'}</mark>
  345. );
  346. </code></pre>
  347. <p>The <code>ack()</code> method accepts a <code>headers</code> argument for additional headers to acknowledge the message. For example, it is possible
  348. to acknowledge a message as part of a transaction and ask for a receipt when the <code>ACK</code> STOMP frame has effectively be processed by the broker:
  349. <pre><code>
  350. var tx = client.begin();
  351. message.ack(<mark>{ transaction: tx.id, receipt: 'my-receipt' }</mark>);
  352. tx.commit();
  353. </code></pre>
  354. <p>The <code>nack()</code> method can also be used to inform STOMP 1.1 brokers that the client did <em>not</em> consume the message. It takes the same arguments than the <code>ack()</code> method.
  355. <h3 id=transaction>Transactions</h3>
  356. <p>Messages can be sent and acknowledged <em>in a transaction</em>.</p>
  357. <p>A transaction is started by the client using its <code>begin()</code> method
  358. which takes an optional <code>transaction</code>, a String which uniquely identifies the
  359. transaction. If no <code>transaction</code> is passed, the library will generate one automatically.
  360. <p>This methods returns a JavaScript object with a <code>id</code> attribute corresponding to the transaction ID and two methods:
  361. <ul>
  362. <li><code>commit()</code> to commit the transaction
  363. <li><code>abort()</code> to abort the transaction
  364. </ul>
  365. The client can then send and/or acknowledge messages in the transaction by specifying a
  366. <code>transaction</code> set with the transaction <code>id</code>.</p>
  367. <pre><code>
  368. // start the transaction
  369. var tx = <mark>client.begin</mark>();
  370. // send the message in a transaction
  371. client.send("/queue/test", <mark>{transaction: tx.id}</mark>, "message in a transaction");
  372. // commit the transaction to effectively send the message
  373. <mark>tx.commit</mark>();
  374. </code></pre>
  375. <div class=advice>
  376. <img style="float:left" width=120 src="i/johnny_automatic/johnny_automatic_advise_from_the_doctor.svg">
  377. <p>If you forget to add the <code>transaction</code> header when calling <code>send()</code>
  378. the message will <em>not</em> be part of the transaction and will be sent directly without
  379. waiting for the completion of the transaction.</p>
  380. <pre style="clear:both"><code>
  381. var txid = "unique_transaction_identifier";
  382. // start the transaction
  383. var tx = <mark>client.begin</mark>();
  384. // oops! send the message outside the transaction
  385. client.send("/queue/test", <mark>{}</mark>, "I thought I was in a transaction!");
  386. <mark>tx.abort</mark>(); // Too late! the message has been sent
  387. </code></pre>
  388. </div>
  389. <h3 id=debug>Debug</h3>
  390. <p>There are few tests in the code and it is helpful to see what is sent and received
  391. from the library to debug application.</p>
  392. <p>The client can set its <code>debug</code> property to a function with takes a <code>String</code> argument
  393. to see all the debug statements of the library:</p>
  394. <pre><code>
  395. <mark>client.debug</mark> = function(str) {
  396. // append the debug log to a #debug div somewhere in the page using JQuery:
  397. $("#debug").append(str + "\n");
  398. };
  399. </code></pre>
  400. <p>By default, the debug messages are logged in the browser window's console.
  401. </section>
  402. <section>
  403. <h2 id=example>Example</h2>
  404. <p>The source code contains a chat example in <kbd>examples/chat/index.html</kbd></p>
  405. <p>You need to start a STOMP server with support for WebSocket (using for example <a href=#hornetq>HornetQ</a>).</p>
  406. <p>Click on the <kbd>Connect</kbd> button to connect to the server and subscribe to the <code>/queue/test/</code> queue.</p>
  407. <p>You can then type messages in the form at the bottom of the page to send STOMP messages to the queue.
  408. Messages received by the client will be displayed at the top of the page.</p>
  409. <p>You can also send regular STOMP messages and see them displayed in the browser. For
  410. example using directly <kbd>telnet</kbd> on STOMP default port:</p>
  411. <pre>
  412. <samp>$ </samp><kbd>telnet localhost 61613</kbd>
  413. <kbd>CONNECT
  414. login:guest
  415. passcode:guest
  416. ^@
  417. </kbd>
  418. <samp>CONNECTED
  419. session:1092296064
  420. </samp>
  421. </pre>
  422. <p><kbd>^@</kbd> is a null (<kbd>control-@</kbd> in ASCII) byte.</p>
  423. <pre>
  424. <kbd>SEND
  425. destination:/queue/test
  426. Hello from TCP!
  427. ^@
  428. </kbd>
  429. </pre>
  430. <p>You should now have received this message in your browser.</p>
  431. </section>
  432. <section>
  433. <h2 id=contribute>Contribute</h2>
  434. <p><img width=240 src=i/johnny_automatic/johnny_automatic_the_dynamometer_test.svg></p>
  435. <p> The source code is hosted on <a href=http://github/org>GitHub</a>:</p>
  436. <pre>
  437. <kbd>git clone <a href=http://github.com/jmesnil/stomp-websocket>git://github.com/jmesnil/stomp-websocket.git</a></kbd>
  438. </pre>
  439. </section>
  440. <footer>
  441. &copy; 2012 <a href="http://jmesnil.net/">Jeff Mesnil</a>
  442. </footer>
  443. <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js'></script>
  444. <script src='j/doc.js'></script>
  445. <script type="text/javascript">
  446. var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
  447. document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
  448. </script>
  449. <script type="text/javascript">
  450. var pageTracker = _gat._getTracker("UA-257783-1");
  451. pageTracker._initData();
  452. pageTracker._trackPageview();
  453. </script>
  454. </body>
  455. </html>