Monday, July 30, 2007

Utilizing Installation Descriptor Extensions in JBI

JBI provides a means to add extensions to your Installation Descriptor (jbi.xml). These extensions can be used for a variety of different things, like configuration for your component. Working examples of components utilizing this feature check out the OpenESB HTTP Binding Component or ServiceMix HTTP Binding Component . Recently I needed to use this feature to add some configuration type attributes to the component we were developing. The first thing you will need to do is add the extensions to your installation descriptor. As noted in the API, the Installation Descriptor Extensions are located at the end of the <component> element of the installation descriptor, something like the following:


<component>
....
The rest of the jbi.xml
....
<config:Configuration>
<config:Port>8888</config:Port>
<config:Location>localhost</config:Location>
</config:Configuration>
</component>


During bootstrap init() the InstallationContext is passed in, this object gives you access to the Installation Descriptor Extensions, via installationContext.getInstallationDescriptorExtensions (Which returns a DocumentFramgment containing all Extensions). At this time you need to store the values in an object so that you can access them during the Components init(). The best way to achieve this is to use JMX. So the first thing you will need to do is Create an Interface that defines your MBean, and then create your class that will implement that interface. Something like the following:

public interface ConfigExtensionsMBean {
public void parseConfigExtensions(DocumentFragment documentFragment);
public String getLocation();
public int getPort();
}
Now we need to write our concrete class that implements this interface, something like the following:

public class ConfigExtensions implements ConfigExtensionsMBean {

private int port;
private String location;

public enum Attributes {Location, Port};

public String getLocation() {
return location;
}

private void setLocation(String location) {
this.location = location;
}

public int getPort() {
return port;
}

private void setPort(String port) {
this.port = new Integer(port);
}

public void parseConfigExtensions(DocumentFragment frag) {
//Parse the DocFrag here and call the setters for the port and location.
}
}
So now we have the Interface and the Concrete class, we just have to use it now. So the first thing we need to do is in your Bootstrap classes init() method we need to get the Installations Service Description Extensions and create our MBean and register that MBean in our MBean server, this should look something like the following:

public void init(InstallationContext context) {
ConfigExtensionsMBean mBean = new ConfigExtensions();
DocumentFragment doc = context.getInstallationDescriptorExtension();
mBean.parseConfigExtensions(doc);

MBeanServer mBeanServer = context.getContext().getMBeanServer();
ObjectName mBeanName = context.getContext().getMBeanNames().createCustomComponentMBeanName("MyMBean");
try {
if (!mBeanServer.isRegistered(mBeanName) {
ObjectInstance oi = mBeanServer.registerMBean(mBean, mBeanName);
}
} catch (Exception e) {
e.printStackTrace();
}
}
So what we just did was read the extensions, parse them and call the setters, and registered the mBean for future use. So now our new component is ready to be initialized and needs access to that mBean. The following is how you can access them during ComponentLifeCycle.init(ComponentContext context):

public void init(ComponentContext context) {
MBeanServer mBeanServer = context.getMBeanServer();
ObjectName mBeanName = context.getMBeanNames()
.createCustomComponentMBeanName("MyMBean");

try {
host = (String) mBeanServer.getAttribute(mBeanName,
ConfigExtensions.Attributes.Location.toString());
port = (Integer) mBeanServer.getAttribute(mBeanName,
ConfigExtensions.Attributes.Port.toString());
} catch (Exception e) {
log.warning("Exception getting mBean Attributes: " + e);
e.printStackTrace();
}
}
So, there you have it, an example of how to utilize the Installation Descriptor Extensions from your jbi.xml.

Tuesday, July 24, 2007

Patterns and Matchers - java.util.regex Package

Recently I got the oppurtunity to utilize the java.util.regex package, which I had never used before, and found it very simple and handy to work with. As I look to do on my blog, I will share a simple example of how to match character sequences against patterns specified by regular expressions utilizing the Java API. So, as TDD goes we will write the test first and then develop our code against our unit test. If your not familiar with unit testing, you will need to download JUnit. Ok, we will start by creating our new test class.


import junit.framework.TestCase;
import java.util.List;

public class ProcessorTest extends TestCase {
String testData =
<test><name>Chad</name>Bob<name></name></test>;

public void testProcessor() {
Processor processor = new Processor();
List list = processor.processMessage(testData);
assertEquals("List was not correct size", 2, list.size());
assertEquals("Name did not match", "Chad", list.get(0));
assertEquals("Name did not match", "Bob", list.get(1));
}
}


This will obviously fail since we haven't created our Processor class yet, so lets go ahead and create our new Class, and then we can run our unit test to verify that our code is doing what we want it to do.

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.List;
import java.util.ArrayList;

public class Processor {

public List processMessage(String text) {
String pattern1 = <\\w*?name>>;
String pattern2 = </\\w*?name>;
List result = new ArrayList();
Pattern p1 = Pattern.compile(pattern1);
Pattern p2 = Pattern.compile(pattern2);
Matcher m1 = p1.matcher(text);
Matcher m2 = p2.matcher(text);
while ((m1.find()) && (m2.find())) {
result.add(text.substring(m1.end(), m2.start()));
}
return result;
}
}


Now we can run our unit test again and our test will pass. So this is just a simple example of how to use the Matcher and Pattern class provided as part of the JDK, and how to utilize Unit Testing to test your code.

Monday, July 23, 2007

Using Grizzly to read TCP Packets

Recently I had the need to be able to listen on a port and read TCP packets that were sent from a logger (java.util.SocketHandler), and I wanted to utilize the Grizzly framework to do this. With some help from the Grizzly team I was able to accomplish this and thought I would share what I did. The first thing I had to do was write a main that could connect to a port and receive TCP packets, it looked something like the following:

public class TCPProcessor {
public static void main(String[] args) throws Exception {
int port = Integer.getInteger(args[0]);

Controller controller = new Controller();
TCPSelectorHandler tcpHandler = new TCPSelectorHandler();
final MyProtocolFilter filter = new MyProtocolFilter();

tcpHandler.setPort(port);
controller.setProtocolChainInstanceHandler(new DefaultProtocolChainInstanceHandler() {
public ProtocolChain poll() {
ProtocolChain protocolChain = protocolChains.poll();

if (protocolChain == null) {
protocolChain = new DefaultProtocolChain();
protocolChain.addFilter(new ReadFilter());
protocolChain.addFilter(filter);
}

return protocolChain;
}
});
controller.addSelectorHandler(tcpHandler);
controller.start();
}
}
Now that I have my main listening, I need to write the Filter that will handle the processing of the data packet. With the ProtocolChain, the ReadFilter will read the TCP packets and pass it to the next filter in the chain, which is were I need to process my data. My filter will look something like the following:
public class MyProtocolFilter implements ProtocolFilter {
public boolean execute(Context context) {
final WorkerThread workerThread = ((WorkerThread)Thread.currentThread());
String message = "";
ByteBuffer buffer = workerThread.getByteBuffer();
buffer.flip();

if(buffer.hasRemaining()) {
byte[] data = new byte[buffer.remaining()];
int position = buffer.position();
buffer.get(data);
buffer.position(position);
message = new String(data);
}
System.out.println("New message being read, message is: " + message);
buffer.clear();
return false;
}

public boolean postExecute(Context context) throws IOException {
return true;
}
}

So now you could whip up a test to send some data over TCP and the Processor will read the packets and print the message out.

Thursday, July 19, 2007

Fun in the Sun!!!!


I am currently in Mexico on vacation with my wife and daughter and thought I would share some photos. This is the first vacation we have had a chance to take with our daughter, and she has had just a great time. You can tell by the picture that she has thoroughly enjoyed the tropical drinks, I think she likes eating the pineapple more than drinking the drink though.
I have to admit, she has been quite good the entire trip, we drove from Missouri (a 24 hour drive) and I was worried about her ridding in the car that long, thank goodness for portable DVD players. In the meantime, we have just had a great time relaxing in the sun and playing in the ocean. Back to the real world next week.

Thursday, July 5, 2007

New Enhancements for the RSS Binding Component

We have recently added some new enhancements to the RSS Binding Component. We now provide support for subscribing and receiving notifications from secure feeds that use Basic Authentication, and the ability to subscribe to multiple feeds at the same time during runtime. Be sure to check out the RSS WSDL Extensiblity elements for definitions on how to create the WSDL. If you have any questions feel free to contact me or use the mailing list from the project site.