Monday, August 27, 2012

Dynamic queue creation with WMQ


Today's task is dynamically creating persistant queues in WMQ(IBM's Websphere MQ) from within Java code. Out of all of the message brokers that I have researched, WMQ definetely was the hardest to figure out how to create queues from code.  Although, on the positive side, at least it is possible.  

In order to invoke the broker from Java, you must use WMQ's API which they call PCF (Programming Command Format).  PCF allows you to do a wide range of admin tasks such as viewing current queues and creating new queues. In order to perform a specific action, you must create a PCFMessage and add all of the needed parameters to it (You also need to make sure that you add them in the correct order!?). A list of all of the required and optional parameters can be found here. After setting all of the parameters, all you need to do is create a PCFMessageAgent and send the parameters. Done. It seems easy now, but most of my time was spent fishing through IBM documentation looking for the correct syntax and parameter names.

If you are interested in other functionality provided by PCF, there are samples included with the installation of the WMQ client found here.  After installation, by default the samples are location at: C:\Program Files (x86)\IBM\WebSphere MQ\tools\pcf\samples
Source:
   public void createQueue(String queueName) throws Exception {
      PCFMessageAgent agent = null;

      // Create the PCF message type for the create queue.
      // NOTE: The parameters must be added in a specific order or an exception (3015) will be thrown.
      // The required order is Name, type, then all optional parameters
      PCFMessage pcfCmd = new PCFMessage(MQConstants.MQCMD_CREATE_Q);

      // Queue name - Mandatory.
      pcfCmd.addParameter(MQConstants.MQCA_Q_NAME, queueName);

      // Queue Type - Optional.
      pcfCmd.addParameter(MQConstants.MQIA_Q_TYPE, MQConstants.MQQT_LOCAL);

      // Add description.
      pcfCmd.addParameter(MQConstants.MQCA_Q_DESC, "Queue created by PCF test");
     
      //set the max queue depth
      pcfCmd.addParameter(MQConstants.MQIA_MAX_Q_DEPTH, 999999);
     
      //Make queue persistant
      pcfCmd.addParameter(MQConstants.MQIA_DEF_PERSISTENCE, MQConstants.MQPER_PERSISTENT);

      //backout queue
      pcfCmd.addParameter(MQConstants.MQCA_BACKOUT_REQ_Q_NAME, "INVALID." + queueName);
     
      //harden backout count-determines if backout count is saved after restart
      pcfCmd.addParameter(MQConstants.MQIA_HARDEN_GET_BACKOUT,MQConstants.MQQA_BACKOUT_NOT_HARDENED);
     
      try {
          agent = new PCFMessageAgent(BROKER_HOST, BROKER_PORT, DEFAULT_CHANNEL_NAME);
          //An exception will be thrown if the queue already exists
          agent.send(pcfCmd);
          System.out.println("Successfull created queue: " + queueName);
      }
      catch (PCFException pcfe) {
       System.out.println("Failed to create queue");
       if (pcfe.reasonCode == MQConstants.MQRCCF_OBJECT_ALREADY_EXISTS) {
        System.out.println("The queue " + queueName + " already exists on the queue manager.");
       }
      }
      finally{
       // Disconnect the agent.
          agent.disconnect();
      }
      return;
   }

Monday, July 16, 2012

Dynamic messaging with Qpid and Spring Integration

One of the key functions of a message broker that I would like to be able to do is to dynamically send messages to queues at runtime. This means that I don’t want to have to create queues ahead of time within the broker and then alter my application’s configuration to connect to the new queue.  What I want to do is have the application determine when it needs to create a new queue (either by customer interaction, database values, or some of arbitrary logic), and then have new messages sent to it.

With RabbitMQ, if you send a message to a queue that doesn’t exist, it creates the queue for you and then adds the message to it. Qpid, on the other hand, doesn’t work like this.  If you try to send a message to a non-existent queue, you’ll get an error.

While fishing through Qpid documentation I read that if a consumer is created for a queue that doesn’t exist, then the broker will create the queue.  This is better than nothing, but still not really what I want.

Then while testing a few different settings, I realized that from within Java, you can specify arguments (similar to the arguments you would use if you were to create a queue from the command line) when you specify the message destination.  This changes everything.  Now I can create durable queues on the fly, which is just what I wanted.

Qpid isn’t directly supported by Spring Integration in the same way that RabbitMQ is, but since it can be accessed using JMS, you can use the existing JMS classes within SI do to send and receive messages.This can be done by creating a service activator that has a DynamicJmsTemplate which will send the messages.  




The JmsTemplate will need a connection factory.  The Qpid examples use a JNDI connection factory, but I would rather have my connection defined in my config and not have to worry about JNDI.  For this, I used the AMQConnectionFactory provided in the qpid client library.  I’m not sure if this is the best class to use, but for now it will work.


 



 
  
   
  
 

At this point all you will need to do is to implement a sendMessage method within the handler class and use the JmsTemplate to send the message.  But wait, how do we guarantee that the queue will be created if it doesn’t exist when we send the message?  The trick here is specify the create arguments with the destination.

String destinationName = queueName + "; {create: always, node:{type:queue,durable:True}}";
this.jmsTemplate.convertAndSend(destinationName, objectToSend);


And there you have it. You can now create queues on the fly without having to worry about errors.  Just make sure you create a consumer for the queue you just created, otherwise your queues will fill up pretty quick.

Message Broker Questions/Concerns

Since the last post, I have narrowed my queue search down to two brokers; Qpid and RabbitMQ.  The following is a list of questions that focus on the management aspect of each broker.  What I have found is that management doesn’t seem to be a major focus of either broker, but both do have some support built in.  RabbitMQ suggests users develop plugins to meet their specific needs, but since the plugins need to be written in Erlang, it would require learning a new language (which I’m all for, it will just take a little time).  The management console that I refer to for Qpid is the Red Hat Enterprise MRG Management Console. Ideally I would have liked to be able to control everything from a single GUI, but that doesn’t seem to be the case with either broker.
  1. How are the brokers managed?
·        [Qpid] Web UI and command line
·        [RabbitMQ] Web UI, command line, and REST API
  1. Does the broker support replaying messages in queue ‘A’ through queue ‘B’ ?
·        [QPID] Messages can be moved through the web management console (although I received errors when I tried to do it).
·        [RabbitMQ] No
  1. Does the broker support purging of queues?
·        [Qpid] Messages can be purged through the web management console (although I received errors when I tried to do it).
·        [RabbitMQ] Messages can be purged through the web management UI
  1. What type of error monitoring does the broker support? Email notifications? System alerts?
·        [Qpid] Possibly
·        [RabbitMQ] Possibly
·        If yes, how are they setup?
·        [Qpid] From the command line it is possible to use qpid-printevents. This could be used within a script and send an email if a specific problem arises, such as the server goes down. Alternatively, we could create a script/application that monitors specific queues and sends email notifications if a specific queue reasons a predefined threshold.
·        [RabbitMQ] There are a few third party plugins that could be used to monitor the system. Alternatively, we could do something similar to the Qpid approach.
  1. What happens if the queues exceed a certain threshold? Exceeds given memory?
·        [Qpid] Application connection is closed by broker.
·        [RabbitMQ] The message broker stops accepting messages.
  1. How to start/stop/restart brokers?
·        [Qpid] server command line
·        [RabbitMQ] server command line
  1. Where are the logs located?
·        [Qpid] /var/log/messages/
·        [RabbitMQ] /var/log/rabbitmq/
  1. Where are configuration files located?
·        [Qpid] /etc/qpid/qpidc.conf
·        [RabbitMQ] /etc/rabbitmq/rabbitmq.config NOTE: the file is not created by default, but can be created manually if needed.
  1. How do we add additional queues? Delete queues?
·        [Qpid] Can be done through web management UI
·        [RabbitMQ] Can be done through web management UI
  1. Are the queued messages visible?
·        [Qpid] No
·        [RabbitMQ] The first X number of messages are visible from the web UI.
  1. Does the broker provide a way to view broker/system statistics?
·        [Qpid] Provides a plug-in that allows users to view the server statistics from the web UI. The web UI also displays some statistics about messages queued/dequeued, number of messages, size of messages, and the number of consumers.
·        [RabbitMQ] The web UI provides visibility to the same information Qpid provides plus users can view IP address of the open producer/consumer connections.
  1. What kind of clients (i.e. languages/runtimes) are supported/available?
·        [Qpid] Java, C++, .NET, Python, Ruby
·        [RabbitMQ] Java, C/C++, web, .NET, Python, Ruby, and many others. Complete list can be found here.
  1. What language is the broker written in?
·        [Qpid] Two implementations, Java and C++. The RHN version is C++
·        [RabbitMQ] Erlang
  1. How do you add additional users?
·        [Qpid] server command line
·        [RabbitMQ] web UI
  1. Can queues be paused?
·        [Qpid] No
·        [RabbitMQ] No
  1. Can test messages be added from the management console?
·        [Qpid] No
·        [RabbitMQ] Yes, through the web UI
  1. How are the queue maximums set?
·        [Qpid] there are four fields that need to be set: file-count(nbr files in queue's persistence journal), file-size (file size in pages), max-queue-size, max-queue-count. The broker appears to go by the smallest value set. ex: if the max-queue-count is set to 200k messages, but the file-count is set to its default (8) and that size can't hold 200k messages, the limit is what the file-count can hold (10k messages).
·        [RabbitMQ] Maximums cannot be set. RabbitMQ states that it shouldn't be needed because if the queue depth starts to grow exceptionally large, it writes the messages to disk so they will not be lost.
  1. Can users view the maximum number of messages for a queue?
·        [Qpid] not from web UI. The queue file sizes can be viewed from the command line
·        [RabbitMQ] N/A
  1. Can messages be routed between life-cycles?
·        [Qpid] Supported by using qpid-route
·        [RabbitMQ] Supported by using the Shovel plugin.
  1. Can queues be setup to route failed messages to an invalid (dead-letter) queue?
·        [Qpid] Yes, but only from the command line
·        [RabbitMQ] Yes, from the web UI and from the command line

Tuesday, July 3, 2012

Message Broker Comparison

Recently I have been given the task to find a new message broker. I was given a large list of vague requirements such as it needs to be fast, persistant, durable, etc. Below is a list that I have put together that describes a few brokers that I have researched. As I started to research more and more, I found that these are just a few of the more popular message brokers out of a very large and growing list. I you have experiance with any of these queues, or any other queues that are not mentioned here, feel free to share your thoughts.
  1. RabbitMQ (AMQP)
    • Pros:
      1. Can setup retry logic using spring’s retry template
      2. Supports dynamic queue creation.
      3. JSON API to retrieve list and manage queues
      4. Web UI for queue management
      5. Very fast (10x ActiveMQ)
      6. Spring supported through Spring-AMQP package
      7. Large community support
      8. Can configure broker with exchanges/queues to manage performance and route messages based on content
      9. supports STOMP protocol
    • Cons:
      1. Broker is implemented using Erlang and not Java (impacts setup, config)
      2. AMQP is still new
  2. ActiveMQ (JMS)
    • Pros:
      1. Can configure connection factory to handle retry logic (delays/redelivery)
      2. Supports dynamic queue creation.
      3. Web UI for queue management
      4. Can retrieve a list of queues through JMX
      5. Spring supported with Spring-JMS
      6. Large community support
      7. Broker is configurable through XML
    • Cons:
      1. Not as fast as RabbitMQ
      2. Messages must be sent to either queues or topics
      3. Doesn’t appear to be completely stable.
  3. Qpid (AMQP)
    • Pros:
      1. Java implementation
      2. Durable queues, persistent messages using Derby DB
      3. Windows .NET SDK
    • Cons:
      1. No queue management UI, must use command line, or JMX
      2. Not completely supported by Spring. Can use Spring-AMQP, but not completely supported. NOTE: could use supported spring rabbit libraries, but would need to be using the same version of AMQP as RabbitMQ
      3. Little community support
      4. AMQP is still new
  4. HornetQ (JMS)
    • Pros:
      1. Can be installed as a standalone server or with JBoss
      2. REST api to manage queues
      3. XML configuration
    • Cons:
      1. Recommended to use Java 6, although there are special client jars for Java5 (ran into issues using Java5 library)
  5. ZeroMQ (AMQP)
    • Pros:
      1. Very fast
    • Cons:
      1. Queues are not durable
      2. Messages are not persistent
      3. Not really a message broker
  6. WMQ (JMS)
    • Pros:
      1. Spring support
      2. Can dynamically create listeners
      3. Desktop UI management
      4. Can view messages in UI
    • Cons:
      1. Does not support dynamic queue creation (out of the box).
      2. Does not support consumer backoff (retry delay)
      3. Unless using version 7 or newer, wmq libraries does not support a way to get a current list of queues. We would need to keep track of the queues ourselves.

Monday, May 28, 2012

Getting started with Appcelerator

A few days ago I started looking into Appcelerator Titanium, which enables you to develop mobile applications for a multiple platforms using Javascript.  If you already have knowledge developing in Javascript, now you can use that knowledge to create native applications for the IPhone and Android.  Appcelerator does this by taking the javascript that you write, and compiling it into code that is supported by each specific platform.  This takes out a lot of the rework usually needed when creating applications on multiple platforms, although it still enables you to add functionality that is specific to each platform.

If you jump over to the Appcelerator web site, you will find a ton of information.  I would advise reading some of the documentation to get a feel for what is actually going on.  Appcelerator provides their own IDE which you will need to use in order to develop applications, and in order to get the IDE, you will need to create an Appcelerator account.

The next step is to install each platform's SDK if you have already not done so in the past.  When you launch the IDE, the dashboard that is displayed will show you what SDK versions are required depending on the platform that you are developing for.  

I ran into a few issues here. First of all it said that I already have xcode installed (which I do) and that I am ready to develop IPhone apps.  After creating a new project and running it, I found out that I am not ready to develop IPhone apps.  It turns out that you need the newest version of xcode in order to use Appcelerator, and depending on your version of OSX, you might not be able to get it.  The newest version of xcode is version 4, which requires OSX Lion.  So, even though Appcelerator doesn't state it, you will need to update to Lion and then update xcode to version 4.  At this point you will be ready to develop IPhone apps.

If you do not plan on building IPhone apps, but instead your cup of tea is Android, you might also run into a few problems.  On Appcelerator's dashboard, the Android tab stated that I need to update to a newer version of the SDK, but when I clicked on the update SDK button, nothing happened.  It seems to have been an issue with the IDE.  I then went on a path of trying to figure out how to update the SDK.  This was a little tough since most of the Google documentation assumes you are using Eclipse.  I ended up going into Eclipse and updating the SDK from there.  Then I went back into Appcelerator and pointed it to my newly updated version of the SDK.  

After all of the setup I was finally able to develop native applications, now all I needed was a way to learn how to do that.

After a little Googling, I found a great starter tutorial on mobile tuts. I would advise you to check it out here.

The tutorial is pretty good, it walks you through how to make a simple twitter client that loads a user's tweets into a list.

The tutorial was informative, but when I was done, I wanted to be able to add a 'refresh' button in order to refresh the tweets.  In order to accomplish this, I added a button to the top of the tabView and then added a click event to it so that when the user clicked on it, I could refresh the list.
var refreshBtn = Titanium.UI.createButton({
 title: "refresh",
 top:0,
 height:40
});

refreshBtn.addEventListener('click', function(){
 Titanium.API.log('user clicked refresh');
 loadTweets();
});
As you can see, I set the top to 0 and the height to 40.  This puts it at the top of the tab.  I then changed the top in the TabView to be 40 so that it starts right after the button.

If you run the application and click the refresh button, it will update the list and everything appears to be working.  If you try to scroll down the list though, you will start to see the text duplicate on each row.  This is  because you are creating a new tableView and adding it to the window each time you hit refresh.  In order to get around this, you need to move the creation of the TableView outside of the loadTweets function.  Then inside of the function, use tableview.setData(rowData); to update the table with the new data.

var tableView = Titanium.UI.createTableView({
   top:40
  });
...

function loadTweets(){
...
      tableview.setData(rowData);
...
}


Now when you run the application and hit the refresh button, the rows are updated and not created on top of each other.

The documentation on the Appcelerator web site is not the greatest when it comes to starting out for the first time.  Their site recommends that you download their sample project 'kitchenSink' which contains a ton of examples.  It is overwhelming at first, but if you know what you are looking for, it can be very helpful.  I used the 'button.js' example to determine out to create buttons and add events to them, and then used the 'table_refresh.js' example to determine how to refresh the list.

Getting started with Appcelerator might be a rocky road, but it definitely looks promising.

Friday, April 13, 2012

Bouncy Castle Decryption - Illegal Key Size


Recently I was asked to implement a solution that decrypts a PGP encrypted ZIP file.  I had never worked with encryption/decryption in Java before, but the task seemed simple enough. I found Bouncy Castle, fished though the API, which us loaded with examples, and poof, I was ready to test.

This is where I ran into a problem.  I received an 'Illegal Key Size' error. I turned to Google and found an answer on StackOverflow 

It turns out that the decryption provider I was using, JCA, cannot handle secret keys greater than 128 bits. The solution is to download updated JAR files from oracle and add them to our JRE.  This isn't really the best solution since I would rather not touch my installation of Java.

At this point I turned back to the API to look for a better solution. This is where I found a better solution. The trick is to remove the dependency on JCA altogether by replacing the decryptor factory as below.
Replace:

InputStream clear = pbe.getDataStream(new JcePublicKeyDataDecryptorFactoryBuilder().setProvider(SECURITY_PROVIDER).build(sKey));

with:

InputStream clear = pbe.getDataStream(new BcPublicKeyDataDecryptorFactory(sKey));

Success. No need to tweek your Java installation.

References:
http://www.javamex.com/tutorials/cryptography/unrestricted_policy_files.shtml
http://stackoverflow.com/questions/6481627/java-security-illegal-key-size-or-default-parameters