Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Sign Up
Dashboard
Groovy
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<p>This docs is for v0.2+</p> <h1>Changes</h1> <h3>v0.2</h3> <ol> <li>It is no longer a mandatory to provide a JMS ConnectionFactory. For a single JVM simple usage, you may use the default in-memory, non-persistent ActiveMQ connection factory, or you could configure your JMSProvider in several ways.</li> <li>The library is no longer used as a Groovy Category. The Groovy Category are hidden. There are a few different ways to use: <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> // 1 jms{ //require static import of groovy.jms.JMS.jms // your jms code } // 2 def jms = new JMS(){ // your jms code } // and for further execution jms.run{ // more jms code } // 3 def jms = new JMS() jms.xxx ; // this is for using the Groovy Messaging Service API jms.close() //must be closed manually if JMS code are not executed in the JMS Context♠ </pre></td></tr></table></li> <li>The base Category API are slightly modified and are refactored to the JMSCoreCategory. Two sets of new APIs: GroovyJMS API and Groovy Messaging Service API are provided. The latter are designed base on the Groovy Sql.</li> </ol> <h1>Usage</h1> <h3>Concepts</h3> <ul> <li><strong>GroovyJMS Execution Context</strong> <ul> <li>GroovyJMS mainly provide an execution context that you can use enhanced JMS API and convenient methods, and access to implicit variables <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> new JMS(){ // inside the execution context, where magics occur } import static groovy.jms.JMS.jms; jms{ // inside the execution context, where magics occur } </pre></td></tr></table></li> <li>GroovyJMS is based on JMS and preserve any JMS concepts and keywords. You could mix the usage of GroovyJMS API and JMS API in the execution context.</li> </ul> </li> <li><strong>GroovyJMS Core API</strong> <ul> <li>GroovyJMS Core API is based on the JMSCoreCategory, and shall be used in Execution Context. APIs are provided for JMS Resource and Destination</li> <li><strong>JMS Resource - ConnectionFactory, Connection and Session</strong>. You could create any of them outside the execution context and pass to the constructor of GroovyJMS, or you could use the implicitly created instances. <ul> <li>Refer to the next section about JMS ConnectionFactory</li> <li>Inside the execution context, getConnection() and getSession() methods are attached to any class, so you could "connection" and "session" like an pre-declared variable. The connection and session are attached to a threadlocal JMS instance <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> new JMS(){ println connection; // by default: ActiveMQConnection {id=ID:hostname-1212-1223775533432-2:0,clientId=ID:hostname-1212-1223775533432-3:0,started=false} println session; // by default: ActiveMQSession {id=ID:hostname-1212-1223775533432-2:0:1,started=false} } </pre></td></tr></table></li> <li>JMS Resources are used interchangeably when creating lower level JMS Resource <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def factory; //injected JMS ConnectionFactory new JMS(){ def conn0 = factory.connect(), conn1 = connection def session0 = factory.session(), session1 = connection.session() } </pre></td></tr></table></li> <li>GroovyJMS provides high level API that use a single connection and session per thread. Unless you want a fine-grained control over the re-use of Connection and Session, it is not necessary to care about these resources.</li> </ul> </li> <li><strong>JMS Destination - Queue, Topic</strong> <ul> <li>There are two types of JMS destination. GroovyJMS provides high level API to operate on any Queue or Topic, unless you need to get a reference for JMS Destination, you don't need to care about JMS Destinations.</li> <li>Short API are provided for creating JMS Destinations. Similar to JMS Resource, calling subject is interchangable. <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def factory; //injected JMS ConnectionFactory new JMS(){ def topic0 = factory.topic(), topic1 = connection.topic(), topic2 = session.topic() def queue0 = factory.queue(), topic1 = connection.queue(), topic2 = session.queue() } </pre></td></tr></table></li> <li>The return value of topic() and queue() are JMS Topic and Queue respectively. However, in GroovyJMS Execution Context, you could use some operation APIs such as send(), receive() etc. directly on JMS Destination.</li> <li>APIs <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> topic.subscribe( subscriptionName:'x', messageSelector:'y', noLocal:true, durable:false) ; //by default, durable is true, subscriptionName is generated unique name, messageSelector is null, noLocal is false, durable is true </pre></td></tr></table></li> </ul> </li> <li>Message - MapMessage <ul> <li>mapMessage.toMap()</li> </ul> </li> </ul> </li> <li><strong>GroovyJMS API</strong> <ul> <li>GroovyJMS API is based on the JMSCoreCategory, and shall be used in Execution Context</li> <li>For simple usage, it is the only thing you need to learn. GroovyJMS API uses keywords from JMS API. <ul> <li>"send" and "receive" for Queue messages</li> <li>"publish" and "subscribe" for Topic messages</li> </ul> </li> <li>You could call the API in two style <ul> <li>Message as subject, and sendTo <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> "Hello world".publishTo "topics/test" [hello:'world'].publishTo "topics/test" "Hello world".sendTo "queue/test" [hello:'world'].sendTo "queue/test" Ideas: "abc".send() // send to the last used queue/topic ? allow user to configure a boolean to reverse the use of send() ? </pre></td></tr></table></li> <li>Or use the destination/Message as subject <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> "topics/test".publish "Hello world" "topics/test".publish [hello:'world'] "queue/test".send "Hello world" "queue/test".send [hello:'world'] "queue/test".send( "Hello world", [replyTo:'queue/replyQueue']) "topic/test".subscribe(){ println it.text } "topic/test".subscribe( //"topics/test".subscribe().with{ println it.text } // "topic".subscribe() [w/o closure] is a synonym of connection.topic() "queue/test".receive() //to be implemented "queue/test".receiveAll() //to be implemented "queue/test".receiveAll( within:200.ms) //to be implemented Message receivedMessage = "queue/test".recieve() receivedMessage.reply "this is my answer" </pre></td></tr></table></li> <li>For certain operations, you don't even need a subject <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> subscribe("topics/test"){ println it.text } //subscribe("topics/test").with{ println it.text } //synonym def message = receive("queue/test") def messages = receiveAll("queue/text") //subscribeTo("topics/test").with{ println it.text } //subscribeTo is a synonym of connection.topic() //receive("queue/test").with{} //receiveFrom is a synonym of connection.queue() , with is the default with{} in Groovy, it is optional //def messages = receiveAllFrom("queue/test").with{ it } //receiveFrom is a synonym of connection.queue().receiveAll() //receiveAllFrom("queue/test").each{ } //directly use the iterator //other Ideas, using map send 'toTopic':'topic/test', 'message',[key:'value'], 'from':'fromclient' </pre></td></tr></table></li> <li>API in a spreadsheet [<a href="http://www.editgrid.com/publish/html/user/mingfai/24976908/A2:M24">http://www.editgrid.com/publish/html/user/mingfai/24976908/A2:M24</a>]</li> </ul> </li> </ul> </li> <li><strong>Groovy Messaging Service API</strong> <ul> <li>Groovy Messaging Service API do not need to run in the Execution Context.</li> <li>Groovy Messaging Service API is designed base on the Groovy core Sql API. <table class="confluenceTable"><tbody> <tr> <th class="confluenceTh"><p> Groovy SQL <br class="atl-forced-newline" /> </p></th> <th class="confluenceTh"><p> Possible JMS Usage <br class="atl-forced-newline" /> </p></th> <th class="confluenceTh"><p> Remarks/Comment <br class="atl-forced-newline" /> </p></th> </tr> <tr> <td class="confluenceTd"><p> Sql.newInstance() </p></td> <td class="confluenceTd"><p> JMS.newInstance(jmsConnectionFactory) </p></td> <td class="confluenceTd"><p> or just use new JMS() <br class="atl-forced-newline" /> </p></td> </tr> <tr> <td class="confluenceTd"><p> sql.eachRow </p></td> <td class="confluenceTd"><p> jms.eachMessage("myQueue"){m-> } <br class="atl-forced-newline" /> jms.eachMessage("myQueue", [within:100]){} <br class="atl-forced-newline" /> <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> jms.reply() could be used inside the closure <br class="atl-forced-newline" /> <br class="atl-forced-newline" /> <strong>reply is not implemented</strong> <br class="atl-forced-newline" /> </p></td> </tr> <tr> <td class="confluenceTd"><p> sql.firstRow </p></td> <td class="confluenceTd"><p> jms.firstMessage("myQueue") { println it.text <br class="atl-forced-newline" /> } <br class="atl-forced-newline" /> <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> jms.onMessage(topic:"mytopic"){ m -> } <br class="atl-forced-newline" /> jms.onMessage(topic: "mytopic",durable:false){m -> } <br class="atl-forced-newline" /> jms.onMessage(queue:"myQueue"){ m -> } <br class="atl-forced-newline" /> jms.onMessage(queue:"myQueue",topic: "mytopic"){ m -> } //subscribe queue and topic at the same time <br class="atl-forced-newline" /> <br class="atl-forced-newline" /> //onMessage supports only one listener per session; if you need multiple subscription, use core API subscribe method and specific different subscriptionName <br class="atl-forced-newline" /> <br class="atl-forced-newline" /> jms.onMessage( topic: ['topic0', 'topic1']{ m -> } <br class="atl-forced-newline" /> jms.onMessage( queue: ['queue0', 'qeueu1']{ m -> } <br class="atl-forced-newline" /> jms.onMessage( topic:'mytopic', queue: ['queue0', 'qeueu1']{ m -> } <br class="atl-forced-newline" /> <br class="atl-forced-newline" /> jms.stopMessage( topic:"myTopic") // unsubscribe the listener <br class="atl-forced-newline" /> jms.stopMessage( topic:['myTopic','myTopic2']) <strong>//TODO not implemented</strong> </p></td> </tr> <tr> <td class="confluenceTd"><p> sql.execute() </p></td> <td class="confluenceTd"><p> def result = jms.receive( fromQueue:'myQueue', within:1000) <br class="atl-forced-newline" /> jms.receive( fromQueue: 'myQueue', within:1000) <br class="atl-forced-newline" /> { println it } <br class="atl-forced-newline" /> jms.receive( fromQueue:['queue0','queue1'], within:1000, with: <br class="atl-forced-newline" /> { println it}) </p></td> <td class="confluenceTd"><p> fromTopic and fromQueue could be used together <br class="atl-forced-newline" /> fromQueue always call receiveAll (to be enhanced to take a parameter to return only 1 message) <br class="atl-forced-newline" /> if fromQueue has more than one queue, it return all messages of all queues <br class="atl-forced-newline" /> fromTopic is asynchronous durable subscription, if both fromQueue and fromTopic are used together, any immediately available messages in any fromQueue will return first, and new message will be delivered to the same with closure in a later time <br class="atl-forced-newline" /> either use jms.receive([:]){ } or jms.receive([xxx:yyy, with:{}]) ; the former override the later <br class="atl-forced-newline" /> within is a per queue timeout interval, not total; if there are more than one queue, each are retrieved in sequence <br class="atl-forced-newline" /> </p></td> </tr> <tr> <td class="confluenceTd"><p> sql.executeUpdate() </p></td> <td class="confluenceTd"><p> jms.send( toTopic:'myTopic', message:[key:value], replyTo:'') <br class="atl-forced-newline" /> <br class="atl-forced-newline" /> </p></td> <td class="confluenceTd"><p> toTopic and toQueue could be used together <br class="atl-forced-newline" /> toTopic and toQueue support collection <br class="atl-forced-newline" /> <br class="atl-forced-newline" /> </p></td> </tr> </tbody></table> </li> <li>All return value or closure handler result are JMS Message. It might be changed to String, Map, Byte[], Stream and Object in the future.</li> <li>Similar to Sql, fine-grained control over connection/session could be done by passing in a JMS Connection or Session in the JMS.newInstance(), and user has to close the session/connection themselves</li> </ul> </li> </ul> <h2>JMS Connection Factory</h2> <p>To use GroovyJMS, you need to decide which JMS implementation you'll use. There are several options:</p> <ol> <li>use the default in-memory, not-persistent ActiveMQ broker and connection factory, this is created by the ActiveMQJMSProvider class. Notice that the ActiveMQJMSProvider will start a ActiveMQ broker if it is not existed already, and will add a "vm://localhost" transport connector URL if not existed. In this case, the syntax is as simple as: <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> new JMS(){ // your jms code } </pre></td></tr></table></li> <li>Provide a JMSProvider by <ol> <li>specific a "groovy.jms.provider" system property that point to a class that implements groovy.jms.provider.JMSProvider</li> <li>set a JMSProvider to the JMS.provider static variable, e.g. <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> JMS.provider = { return new ActiveMQConnectionFactory("vm://localhost") } as JMSProvider </pre></td></tr></table></li> </ol> </li> <li>Provide Connection Factory or Connection in runtime. it is the most recommended approach. You may utilize your JEE container or dependency injection framework to inject the required JMS resources to your class, and support the connection or factory to GroovyJMS. <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def myConnection; //injected new JMS( myConnection ){ // your jms code } // OR def myConnectionFactory; //injected new JMS( myConnectionFactory){ // your jms code } </pre></td></tr></table></li> </ol> <h3>So how cool is GroovyJMS in compare to JMS?</h3> <ul> <li>simplified api</li> <li>subscribe to multiple topics and queues at the same time</li> <li>simple listener implementation by using Closure</li> <li>Groovish API , e.g. jms.eachMessage{}, jms.onMessage{}</li> <li>English language style api: jms.send toQueue:'myQueue',message:'hello world'</li> <li>etc.</li> </ul> <h1>Other important information</h1> <ul> <li><strong>autoClose</strong> <ul> <li>by default, all connection are closed at the end of an execution context, or after any operation for Groovy Messaging Service API.</li> <li>For Groovy Messaging Service API, if you need to do more than one operation, you have to set autoClose to false, and call close() explicitly <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def jms = JMS.newInstance() jms.setAutoClose(false) JMS.close() </pre></td></tr></table></li> <li>When using in execution context, it's unommon to disable autoClose. As one of the purpose of the execution context is to autoClose resource for you. If you need to use execution context and want to disable autoClose, one of the ways is: <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def jms = new JMS(){ jms.setAutoClose(false) // your jms code } </pre></td></tr></table> <br class="atl-forced-newline" /></li> <li>Or you'd better directly use the JMS Category without setting up an execution context. <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> use(JMSCategory){ jms.session() ; // notice that you need to establish a session before doing anything with JMSCategory "queue".send("message") assertNotNull("queue".receive(waitTime:100)) } </pre></td></tr></table></li> </ul> </li> </ul> <h1>Unsupported Features or Limitation</h1> <ul> <li>nested usage is not supported yet. you may still use the lib in nested manner but you have manage the Connection and Session carefully. <ul> <li>For example: <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def connFactory, conn new JMS(conn){ // outer JMS code new JMS(conn){ // inner JMS code } //exception may be thrown at the end as the connection is closed } </pre></td></tr></table></li> <li>you are recommended to avoid nestled usage. If you use it, try to use a multiple connection.</li> </ul> </li> <li>There is no support for transaction. all messages are auto-committed</li> </ul>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced