I recently introduced the async task queue functionality of JBoss-Rails. This is where we wire up JMS queues with Ruby handlers from your app.
But what about the client side? How does code outside of the app-server communicate over the queue to the running handler?
Like this stand-alone *.rb script:
#!/usr/bin/env jruby
require RAILS_ROOT + '/client/boot'
JBoss::Client.connect( "oddthesis", "localhost", 1099 ) do |client|
MailerQueue.enqueue( :send_welcome_mail,
:user=>User.find( :first ) )
end
That's it. The JBoss-Rails Support plugin sets up RAILS_ROOT/client/ for you, which includes the handy-dandy boot.rb along with every Java jar that you need to speak JRuby-on-Rails.
So, we require the boot.rb, which sets up the Rails environment along with all the extra JBoss goodness. And then you're ready to write a client.
JBoss::Client.connect(...) is used to connect a client to a running JBoss. Ultimately, this just points to the JNDI service and includes an application name. This is because a lot of apps could be registered with the same naming context. And that context could be located on some other machinery.
The connect(...) method takes a block, which is where you do your client operations. Here, we're sending a task to the MailerQueuer, exactly the same as we would from with a Controller or other code inside the AS.
Here our client is just plucking the first User object it finds in the database, and tossing it to the send_welcome_mail task on the MailerQueue.
In 5 lines of code.
And yes, you can toss ActiveRecord objects across the queue. Let's look at a handler on the far side:
class MailerQueue < JBoss::Queues::BaseQueue
def send_welcome_mail(payload)
user = payload[:user]
deliver_email( user.email_address )
user.welcomed_at = Time.now
user.save!
end
end
The handler, running in a completely separate process (within the AS) has a live AR object it can inspect, update, or destroy.
Not too shabby for a week's work.