Saturday, October 26, 2013

Announcing injectahvent - a lightweight integration between CDI Events & Apache Camel exchanges

Howdy all!


I am proud to announce a new open source library I am working on, injectahvent.  Injectahvent is meant to be a light weight integration between Camel Messages and CDI Events.  It allows you to define a processor that will fire CDI events on Camel exchanges, and in turn will also allow you to register new ObserverMethods in CDI that listen for events and move them over to Apache Camel exchanges.

So what does it do so far?


Well, it's a little generic right now, but essentially you can register a new CDIEventProcessor in to your RouteBuilder and let CDI fire an Event with the body and exchange objects.

The second part it does is is to allow an application developer to create a simple CDI extension that registers new ObserverMethods for CDI events to look for and use a Camel ProducerTemplate to fire that message.

Conceptually, this is a carry on project from the JBoss SeamJMS module.  While the new fluent API for sending messages was inspired by some of the builder pattern used in Seam JMS and is now incorporated in JMS 2.0, the firing of events was not carried over.  Firing the events is more of an EIP/EAI type of tool.  As a result, I decided to leverage Apache Camel to make it more generic.

The library leverages Apache DeltaSpike, with its CDI Container Control API to start a new RequestContext for a fired message.  It's currently assumed that the basic bootstrap of a CDI container is done outside of this context.

Source Code: https://github.com/johnament/injectahvent
Issues: https://github.com/johnament/injectahvent/issues

I hope to start putting together a wiki for it soon.  As well as doing some nice code clean up.

Sunday, September 29, 2013

Testing JAAS based authentication using Arquillian + Apache DeltaSpike Servlet Module

Hey all.  Long time no post.

In today's discussion, I'm talking about testing enterprise applications again.  I recently was faced with a dilemma.  I needed to test my application in an authenticated way, where the user was logged in vs logged out to ensure that things were going right with an authenticated principal.

Of course, this assumes a few things.  First, that we've executed something to ensure our database is populated with a user that could log in.  In my case, I did this by calling internal APIs that do registration and registration completion.  You could do other things, such as using the Arquillian Persistence Extension to insert records.  My application is using the @InSequence annotation with Arquillian and JUnit to give methods an ordering.

Now that we have a little bit of setup, we're going to leverage a few newer technologies.  In Servlet 3, methods were added to the HTTPServletRequest interface that can login and logout.  These give us an easy interface to be able to authenticate an end user in to the configured JAAS realm.  The problem though is how can we access these objects from an Arquillian test?

Of course, this approach is assuming you're using the Servlet 3 protocol (or better) to execute your tests.  This ensures that you have a an active HTTP request on every test.  This request is what we'll use to login the user to the application, and logout afterwards.  You can follow the instructions here to setup the Servlet module in your application.  You'll likely also want to use the Maven resolver from ShrinkWrap to bring in the Servlet Module to your deployment WAR file.  That resolver config is as easy as:

File[] impl = Maven.resolver().resolve("org.apache.deltaspike.modules:deltaspike-servlet-module-impl").withTransitivity().asFile();

which can then be added to your WAR as library JARs.

Now, in your test case you just need to inject the request.  Then in your Before/After methods login and logout.

@Inject
@Web
private HttpServletRequest request;

...

@Before
public void loginBeforeTest() throws ServletException { // throws simply in case there is a configuration issue, bad account info, already logged in etc.
    request.login(username,password);
}


...

@After
public void logoutWhenDone() throws ServletException {
    request.logout();
}

Now, when your test executes, any injection point for Principal will be filled in with the account that was logged in.  This will correctly propogate to any security context as well, EJBContext, MessageDrivenContext, etc.  This of course assumes that your username and password are instance variables within the class, or static references that can be found (I have found that the static reference approach works best for handling client and server tests in arquillian).

Tuesday, July 16, 2013

Just an idea - programmatic registration of MDBs

Just an idea - programmatic registration of MDBs

So, I'm throwing an idea out there, soliciting feedback.  Why can't MDBs be programmatically registered in the container?

My idea is that an MDB can be a CDI object (rather than an EJB object),

I have a simple GitHub project around this idea here, if you want to check it out (still need to maven-ize it): https://github.com/johnament/jms-mdb-config

The first thing to point out is that MDBs are the main way to support message processing in JMS in a Java EE application server.  It's not possible to setup a message listener due to the container restriction around unmanaged threads.

The idea is to generally provide MDB support programmatically.  This is something very useful from both a framework standpoint and an application developer standpoint.  This allows cleaner support for lambda expressions, as well as give a way to dynamically bind MDBs based on runtime settings.  It allows you to on the fly change your bindings (of course, this is assuming that support can be added for it).

In the late days of Java EE 7, a change to MDBs was introduced to allow an MDB to be bound at a method level of an object.   While this is a great feature, it still doesn't tackle what I think most people need from an MDB - dynamic support.  I'm using a PaaS example in my setup - where we need to dynamically create a queue per tenant to do work (to physically separate their data) and then register that queue when ready to a new MDB instance.

There are a few things this doesn't seem to support as well.  The first is pooling.  No way to create many instances in the one case and the other case uses CDI rules for instantiation.  I think both are OK, since we're not talking about super heavyweight objects.  Though we may run into an issue if too many messages come on the thread.  Realistically, I haven't handled an implementation that wasn't singleton in nature, so I think this isn't a huge loss.  The second is that this doesn't give an option of doing the configuration from annotations.  I think this could be solved by introducing annotations @JMSConfigurationProvider and @JMSListenerMethod, so that the container scanned these automatically on start up.

Of course, these are all JMS specific annotations and interfaces.  I would imagine a revised MDB spec like this would indicate that a configuration object may be polled and return a typed configuration based on what it's handling, so JMSConfiguration would be that for JMS (and if we did support other types of MDBs, they would each have their own configuration).

Another thing that this helps with is in the SE world.  We now have a standard interface to program against for binding of listeners.  While this would be an MDB in SE, it could apply to a remote JMS connection.  This could remove the need for binding MessageListeners.

Saturday, June 15, 2013

What's new in JMS 2 - Part 2 - An Event based Message Sender

One of the pipe dreams we had in Seam3 was to be able to create a variable JMS event router that could send and receive messages as if they were simple CDI events. Why did we want this? For one, it was rather difficult to build a JMS sender. lots of objects and exception handling, not much to do with these errors. It was beneficial to support this as this gave an easy way to handle asynchronous event processing with CDI, leveraging JMS. It should be simple, but there were some stumbling blocks we ran across.

  1. CDI events used a global firing process, not a first match or best match algorithm. If you had an observer method that was as generic as:

    public void handleObj(@Observes Object obj) { ... }

    Then every event fired would make it to this method.

  2. Creating specific bindings breaks dynamic event processing.

    In CDI, there are two ways to fire an event. The first is to use the Event interface, the other is to use a BeanManager.

    We got close. With a fairly convoluted way we could support static binding of events to JMS messages. However, we had no way to support the additional qualifiers that may accompany a message. Let's say we had the following qualifiers on our event:

    @SendTo("someQueue") @From(customer=1) @ReplyTo("someOtherQueue")

    We could use the SendTo to map the message to a Destination, however the extra annotations were not able to come along for the ride. This is because CDI didn't give access to these qualifiers, so any observer method was blind to its input.

  3. In bound message processing breaks Java EE specification requirements. Technically, you cannot start a message listener in Java EE; you instead need to setup an MDB. You could create a message listener implementation and allow developers to extend it for custom processing, or have it mapped in ejb-jar.xml but it doesn't allow this solution to be turn key.




To help fix the problems introduced in 1 and 2, along came the EventMetadata object, which helps out our observer methods. This class acts like an InjectionPoint but is specific to event observers.

Issue 3 remains an issue. Thankfully, one of the late additions in Java EE 7 was support for a Resource Adapter that was more dynamic in nature. We'll have to see if something can be

Now, with CDI 1.1 and JMS 2 we can easily build this outbound message sender with just about 25 lines of code. Behold

 public class SendToObserver {  
   @Inject  
   private JMSContext jmsContext;  
   @Resource  
   private Context context;  
   public void sendViaJms(@Observes @SendTo("") Serializable obj, EventMetadata metadata) {  
     SendTo st = getSendTo(metadata);  
     try {  
       Destination d = (Destination) context.lookup(st.value());  
       jmsContext.createProducer().setProperty("qualifiers", metadata.getQualifiers()).send(d, obj);  
     } catch (NamingException e) {  
       // TODO log something here please  
     }  
   }  
   public SendTo getSendTo(EventMetadata metadata) {  
     Set<Annotation> qualifiers = metadata.getQualifiers();  
     for (Annotation a : qualifiers) {  
       if (a instanceof SendTo) {  
         return (SendTo) a;  
       }  
     }  
     return null;  
   }  
 }  


Assuming that we have a SendTo qualifier defined as

 @Qualifier  
 @Target({ TYPE, METHOD, PARAMETER, FIELD })  
 @Retention(RUNTIME)  
 @Documented  
 public @interface SendTo {  
      @Nonbinding String value();  
 }  


So what happens in this observer? Simple. First, we're observing any Serializable object. So an injection point for this observer could be

 @Inject  
 @SendTo("someQueue")  
 @Important  
 private Event<Serializable> serializableEvent;  


Now, in CDI 1.1 the qualifiers (@SendTo("someQueue") and @Important) will be forwarded and found in the annotation set, returned in getQualifiers(). We can iterate through them to find the SendTo to identify where to send the message to. We can also take all of these qualifiers and send them as an attribute of the message; making them available for use on the receiver side. getSendTo processes the values to read in this destination.

Next, we use JMS2's JMSContext to simplify sending. Behind the scenes, this is using a JMSProducer via a builder pattern to set properties on the message and then send it to the destination. We don't need to create a message, it happens within the sender for us. The injection here can be Request scoped or Transaction scoped, whichever is appropriate here will be activated.

What was easily 1000 lines + in Seam JMS is now just about 25 lines (30 lines if you count the qualifier). This is a huge amount of code improvement. And now, sending JMS messages is really as easy as firing a CDI event.

Sunday, March 10, 2013

What's New in JMS 2 (Part 1)

This post is the first of many parts around the new features of JMS 2.

In this post we talk about some of the new features in the original APIs.  The biggest changes here are around the AutoCloseable interface and RuntimeExceptions.

Let's say we want to read some messages from a Queue, but maybe can't use an MDB or MessageListener to do the work.


public List readMessageContent() {
List messageBodies = new ArrayList<>();
try (Connection conn = connFactory.createConnection();
Session sess = conn.createSession();
MessageConsumer cons = sess.createConsumer(queue)) {
Message m = null;
while ((m = cons.receiveNoWait()) != null) {
if (m instanceof TextMessage) {
TextMessage tm = (TextMessage) m;
messageBodies.add(tm.getText());
m.acknowledge();
}
}
} catch (JMSException | JMSRuntimeException e) {

}
return messageBodies;
}

In our try area we can create a Connection, Session and Message Consumer in an AutoCloseable fashion.  We only want TextMessages so use an if to check the type.  We don't have to deal with any of the closing methods in the code and handle only the exception.  We also have a new JMSRuntimeException that can be caught, or you can let it throw further into the stack.

Digging through the JMS 2.0 javadocs, you'll notice a lot of use in AutoCloseable.  All of the Session interfaces have it now, all of the Connection interfaces as well.  All of the MessageConsumer equivalents (TopicSubscriber, QueueReceiver) and the MessageProducers (TopicPublisher, QueueSender) have it as well.  The new APIs (JMSContext and related) all have it too.  Whenever you create these objects in a try with resources statement they will automatically close for you when done.  This is a pretty powerful feature that matches standard use cases from today.

At this point, all you have to do is finish out your REST resource, and you can easily read all given messages in a single request.  Here's what it looks like:


@Path("/jms")
@Stateless
public class WhatsNewReader {

@Resource(mappedName = "jms/__defaultConnectionFactory")
private ConnectionFactory connFactory;

@Resource(mappedName = "jms/SomeQueue")
private Queue queue;

private Logger logger = Logger.getLogger(WhatsNewReader.class
.getCanonicalName());

public List readMessageContent() {
List messageBodies = new ArrayList<>();
logger.info("Reading.");
try (Connection conn = connFactory.createConnection();
Session sess = conn.createSession();
MessageConsumer cons = sess.createConsumer(queue)) {
logger.info("In the try.");
Message m = null;
while ((m = cons.receiveNoWait()) != null) {
logger.info("In the while.");
if (m instanceof TextMessage) {
TextMessage tm = (TextMessage) m;
messageBodies.add(tm.getText());
m.acknowledge();
}
logger.info("leaving iteration.");
}
} catch (JMSException | JMSRuntimeException e) {

}
return messageBodies;
}

@GET
@Produces("text/plain")
public String getMessages() {
List msgs = readMessageContent();
StringBuilder sb = new StringBuilder("Hello,");
for (String m : msgs) {
sb.append(m).append("\n");
}
return sb.toString();
}
}

Note that I have to use mappedName in my resources.  As far as I can remember, mappedName is supposed to be the product specific JNDI, however I was not able to use name to look these up.  Hopefully this gets corrected in a latest GF4 Build.



You can pull the code from this example, and the next few, from here on my github account: https://github.com/johnament/whats-new-jms2

Edit:

- Fixed JNDI look up issue/at least it's working in b80/b81
- Fixed my typo of receive vs receiveNoWait.

Sunday, January 20, 2013

The book has a cover image

Good news everyone!

I now have a cover image selected for the book, Arquillian Testing Guide.  It's going to be the 1964 World's Fair, home of the climactic battle from Men In Black.

Going with the photographer next weekend to take the pictures.  One step closer to getting a pre-order up.

Sunday, January 13, 2013

And then I wrote a book

I started writing a similar blog post to this around New Year's but after reading it a few times it didn't quite convey what I was hoping for.

If you've been living under a rock, I wrote a book.  Yes, I can finally say I wrote it.  First draft is completely in the publisher's hands and reviews going on.  So far I've done one chapter's final draft but have plenty more to do over the next six weeks or so.  Hopefully nothing major comes up.

The book's subject is Arquillian, the leading deployment automation and extension framework for java testing.  It pushed me to learn more about the tools and even question what I knew about how they worked. Overall, I think readers who are new to Arquillian or even automated testing will find it very useful.  It's being published by Packt, and it fits into their "Getting Started" area of books so it's not meant for more advanced users, but generally novices.

One thing I should point out is that I am being paid to write the book.  If you're not aware, I lost my mother about seven years ago to pancreatic cancer.  The Pancreas Multidisciplinary Cancer Team at Johns Hopkins takes donations so I've decided to donate a portion of the proceeds in my mother's name to the team.