0.01
Repository is archived
No commit activity in last 3 years
No release in over 3 years
JRuby-HornetQ is a Java and Ruby library that exposes the HornetQ Java API in a ruby friendly way. For JRuby only.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

~> 1.1.1
 Project Readme

jruby-hornetq

Introduction

jruby-hornetq creates a Ruby friendly API into the HornetQ Java libraries without compromising performance. It does this by sprinkling "Ruby-goodness" into the existing HornetQ Java classes and interfaces, I.e. By adding Ruby methods to the existing classes and interfaces. Since jruby-hornetq exposes the HornetQ Java classes directly there is no performance impact that would have been introduced had the entire API been wrapped in a Ruby layer.

In this way, using regular Ruby constructs a Ruby program can easily interact with HornetQ in a highly performant way

Install

gem install jruby-hornetq

Important

jruby-hornetq exposes the HornetQ Core API, not its JMS API. There are several reasons for choosing the HornetQ Core API over its JMS API:

  • The Core API supports the use of Addresses, not just Queues
  • The Core API exposes more capabilities than the JMS API (E.g. Management APIs)
  • The HornetQ team recommend the Core API for performance
  • The HornetQ JMS API is just another wrapper on top of its Core API

To use the JMS API from JRuby see the jruby-jms project

HornetQ

For information on the HornetQ messaging and queuing system, see: http://www.jboss.org/hornetq

For more documentation on any of the classes, see: HornetQ Documentation

Concepts & Terminology

Queue

In order to read messages a consumer needs to read messages from a queue. The queue is defined prior to the message being sent and is used to hold the messages. The consumer does not have to be running in order to receive messages.

Address

In traditional messaging and queuing systems there is only a queue when both read and writing messages. With the advent of AMQP and in HornetQ we now have the concept of an Address which is different from a Queue.

An Address can be thought of the address we would put on an envelope before mailing it. We do not have to have any knowlegde of the USPS infrastructure to mail the letter. In HornetQ we Address a message and in HornetQ the Address is routed to one or more Queues.

Durable

Messages in HornetQ can be marked as durable which means they will be persisted to disk to prevent message loss in the event of a power failure or other system failure. This does however mean that every durable message does incur the overhead of a disk write every time it is read or written (produced or consumed).

Broker

HornetQ is a broker based architecture which requires the use of one or more centralized brokers. A broker is much like the "server" through which all messages pass through.

An in-vm broker can be used for passing messages around within a Java Virtual Machine (JVM) instance without making network calls. Highly recommended for passing messages between threads in the same JVM.

Consumer

Consumers read or consume messages from queues

Producer

Producers send, write, or publish messages

Asynchronous Messaging

It is recommended to keep the state of the message flow in the message itself.

Synchronous Messaging

A producer can be used to send a message that contains the address to which a reply should be sent. Then a consumer would be used to wait for a reply from target.

Use of any Queueing system should considered carefully for synchronous messaging since the immediate feedback of failures downstream is not present. The only indicator of a failure is that no response was received.

Direct TCP or HTTP communications in this case can be useful.

Overview

jruby-hornetq is primarily intended to make it easy to use the HornetQ client core API. It also supports running the HornetQ broker for scenarios such as messaging within the Java Virtual Machine.

The examples below address some of the messaging patterns that are used in messaging and queuing.

Producer-Consumer

Producer: Write messages to a queue:

require 'rubygems'
require 'hornetq'

connection = HornetQ::Client::Connection.new(:uri => 'hornetq://localhost/')
session = connection.create_session(:username=>'guest',:password=>'secret')

producer = session.create_producer('jms.queue.CMDBDataServicesQueue')
message = session.create_message(HornetQ::Client::Message::TEXT_TYPE,false)
message.body_buffer.write_string('Hello World')
producer.send(message)
session.close
connection.close

Consumer: Read message from a queue:

require 'rubygems'
require 'hornetq'

HornetQ::Client::Factory.start(:connection => {:uri => 'hornetq://localhost'}) do |session|
consumer = session.create_consumer('jms.queue.ExampleQueue')
  # Receive a single message, return immediately if no message available
  if message = consumer.receive_immediate
    puts "Received:[#{message.body}]"
    message.acknowledge
  else
    puts "No message found"
  end
end

Client-Server

Server: Receive requests and send back a reply

require 'rubygems'
require 'hornetq'

# Shutdown Server after 5 minutes of inactivity, set to 0 to wait forever
timeout = 300000

HornetQ::Client::Factory.start(:connection => {:uri => 'hornetq://localhost'}) do |session|
  server = session.create_server('jms.queue.ExampleQueue', timeout)

  puts "Waiting for Requests..."
  server.run do |request_message|
    puts "Received:[#{request_message.body}]"

    # Create Reply Message
    reply_message = session.create_message(HornetQ::Client::Message::TEXT_TYPE, false)
     reply_message.body = "Echo [#{request_message.body}]"

    # The result of the block is the message to be sent back to the client
    reply_message
  end

  # Server will stop after timeout period after no messages received
  server.close
end

Client: Send a request and wait for a reply

require 'rubygems'
require 'hornetq'

# Wait 5 seconds for a reply
timeout = 5000

HornetQ::Client::Factory.start(:connection => {:uri => 'hornetq://localhost'}) do |session|
  requestor = session.create_requestor('jms.queue.ExampleQueue')

  # Create non-durable message
  message = session.create_message(HornetQ::Client::Message::TEXT_TYPE,false)
  message.body = "Request Current Time"

  # Send message to the queue
  puts "Send request message and wait for Reply"
  if reply = requestor.request(message, timeout)
    puts "Received Response: #{reply.inspect}"
    puts "  Message: #{reply.body.inspect}"
  else
    puts "Time out, No reply received after #{timeout/1000} seconds"
  end

  requestor.close
end

Threading

A factory instance can be shared between threads, whereas a session and any artifacts created by the session should only be used by one thread at a time.

For consumers, it is recommended to create a session for each thread and leave that thread blocked on ClientConsumer::receive A timeout can be used if the thread needs to do any other work. At this time it is Not recommended to use ClientConsumer::receive_immediate across multiple threads due to known issues in HornetQ with this API.

JRuby

jruby-hornetq has been tested against JRuby 1.5.1, but should work with any current JRuby version.

HornetQ

The libraries required for the HornetQ Client and to start a simple Core API only Broker are included with the Gem.

GenePool

GenePool is used to implement session pooling

Running the Broker

Not only does jruby-hornetq make it easy to work with HornetQ from JRuby as a client, it also supports using JRuby to launch a Broker instance

Example Usage

Starting up a standalone hornetq server:

bin/hornetq_server examples/server/standalone_server.yml

Starting up a backup/live combination

bin/hornetq_server examples/server/backup_server.yml
bin/hornetq_server examples/server/live_server.yml

Development

Want to contribute to jruby-hornetq?

First clone the repo and run the tests:

git clone git://github.com/reidmorrison/jruby-hornetq.git
cd jruby-hornetq
jruby -S rake test

Feel free to ping the mailing list with any issues and we'll try to resolve it.

Contributing

Once you've made your great commits:

  1. Fork jruby-hornetq
  2. Create a topic branch - git checkout -b my_branch
  3. Push to your branch - git push origin my_branch
  4. Create an Issue with a link to your branch
  5. That's it!

Meta

This project uses Semantic Versioning.

Authors

Reid Morrison :: reidmo@gmail.com :: @reidmorrison

Brad Pardee :: bpardee@gmail.com

License

Copyright 2014 Reid Morrison, Brad Pardee

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

jruby-hornetq includes files from HornetQ, which is also licensed under the Apache License, Version 2.0: http://www.jboss.org/hornetq