Wednesday, December 21, 2011

A Message Routing Groovy DSL

The other day I was discussing system integration with a friend and he mentioned something about creating a DSL (Domain Specific Language) for the many aspects of enterprise integration. I have limited experience with writing DSL's but I figured I would give it a shot. Inspired by this post on the Canoo blog and my friend's idea, I started hacking on GroovyConsole. Groovy is a great language for writing DSL's because of the language's features like closures and map based interface implementation. Plus, Groovy has the benefit of being fully compatible with Java and other Java based tools. What I want to do is create a DSL for writing rules for a hypothetical message routing engine. Here is my Message domain class and System enum:
import groovy.transform.TupleConstructor

enum System {
    bus, db2, iSeries, mySQL, oracle, postgre
}

@TupleConstructor
class Message {
    String payload
    System origination
    System destination
    
    String toString() {
        "${payload} from:${origination} to:${destination}"
    }
}
Here is what I think the DSL might look like:
route message to oracle, mySQL when origination eq db2
What I am saying is, route a message to oracle and mySQL systems when the message's origination is db2. I guess I really didn't need to explain that because the DSL is pretty self explanatory, right? Let's move on to see what else the DSL might look like:
route message to iSeries, oracle, mySQL when payload contains 'Hello'
Is there a need to explain what the previous statement is stating? If you have not caught on yet, it is saying route a message to the iSeries, oracle and mySQL systems when the message's payload contains the word 'Hello'. In each case, I would imagine creating a new Message for each system that will be put on a queue or sent to an endpoint to be processed. Here is the meat of the code that will implement the DSL I designed above:
import static System.*

messages = []
Above, we have the initialization of the list of messages that will be the result of our DSL statement. If the proper conditions are met, we are returned a list of new messages to send to other systems.
def payload = { Message message ->
    message.payload
}

def destination = { Message message ->
    message.destination
}

def origination = { Message message ->
    message.origination
}
The code above handles referencing each message property. The code below handles the keywords route, to, when, eq, neq and contains. It also handles each message instance and the array of System destinations, for example: iSeries, oracle, mySQL.
def route(Message message) {
    [to: { System[] destinations ->
        [when: { Closure clos ->
            [eq: { System system ->
                if(clos(message) == system)
                    destinations.each { messages << new Message(message.payload, message.origination, it) }
                messages
            },
            neq: { System system ->
                if(clos(message) != system)
                    destinations.each { messages << new Message(message.payload, message.origination, it) }
                messages
            },
            contains: { String string ->
                if(clos(message).contains(string))
                    destinations.each { messages << new Message(message.payload, message.origination, it) }
                messages
            }]
        }]
    }]
}
Below, is an example Message instance for testing the DSL.
message = new Message("Hello there!", db2, bus)
When I run my DSL statements from above, I see the list of messages created to be sent on to the other systems.
route message to oracle, mySQL when origination eq db2

Result: [Hello there! from:db2 to:oracle, Hello there! from:db2 to:mySQL]
The second example:
route message to iSeries, oracle, mySQL when payload contains 'Hello'

Result: [Hello there! from:db2 to:iSeries, Hello there! from:db2 to:oracle, Hello there! from:db2 to:mySQL]
I think this is very cool for my first attempt at a DSL with Groovy. I am sure I can clean up the code a bit (feedback is welcome) and this is really just scratching the surface of what we can do with Groovy and DSL's!

Tuesday, November 15, 2011

Issue with Dynamic Proxy in Java?

I created a simple Annotation, Report, the other day to handle some simple logging/reporting tasks. The intent is to create a simple way to annotate methods that should be logged or reported during invocation. Here is what the Annotation looks like:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
    String menu();
    String name();
    Platform system();
}
I have an interface, Menu, which all Menu implementations will implement:
public interface Menu {
 
    public void doSomething(String session);
}
Here is an example implementation of Menu, MyMenu, with a Report Annotation on the doSomething(...) method. Platform is an enum that describes whether or not to log/report to Oracle, SQL Server or both systems as in the case below:
public class MyMenu implements Menu {

    @Report(menu="AIT_MM", name="MyMenu", system=Platform.BOTH)
    public void doSomething(String session) {
        System.out.println("Doing some work!");
    }
}
Here is a block of code that creates a MyMenu implementation of Menu and a Proxy instance of Menu, and gets the "doSomething" method and checks whether or not the Report Annotation is present on the Method, m:
    Menu menu = new MyMenu();
    Menu menuProxy = 
        (Menu) Proxy.newProxyInstance(menu.getClass().getClassLoader(), menu.getClass().getInterfaces(), new MyLogger(menu));
 
    try {
        Method m = menuProxy.getClass().getMethod("doSomething", String.class);
        if(m.isAnnotationPresent(Report.class))
            System.out.println("Annotation is here!");
    } catch (Exception e) {
        e.printStackTrace();
    }
  
    try {
        Method m = menu.getClass().getMethod("doSomething", String.class);
        if(m.isAnnotationPresent(Report.class))
            System.out.println("Annotation is here!");
    } catch (Exception e) {
        e.printStackTrace();
    }
The statement
if(m.isAnnotationPresent(Report.class))
evaluates to true in the second try/catch block with the normal instance of MyMenu, menu but it evaluates to false in the first try/catch block with the proxy instance of MyMenu, menuProxy. The above code also includes a reference to a class, MyLogger, that implements InvocationHandler. This is where the evaluation of
if(m.isAnnotationPresent(Report.class))
is imperative because it completes my implementation goal. Inside the MyLogger class, I have implemented the
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
method from InvocationHandler like so:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if(method.isAnnotationPresent(Report.class)) {
        Report r = method.getAnnotation(Report.class);
        this.logMyPrompt((String) args[0], r.menu(), r.name(), r.system());
    }
    return method.invoke(delegate, args);
}
Just some strange things that I noticed when trying to do something cool with Java Annotations. Everything works if I put a Report Annotation on the Menu interface's doSomething(...) method declaration, but that solution does not allow me to have individual data related to each implementations' doSomething(...) method.

Wednesday, November 2, 2011

Scalable Internet Architectures

I just finished reading Scalable Internet Architectures by Theo Schlossnagle. Overall, it is a pretty good book if you want to get a good introduction into the problem space of building scalable Web applications. The book touches on high-availability, load balancing, reliability and the cost effectiveness of using distributed, commodity hardware. The book discusses good and bad design and there are a number of examples that are pretty easy to follow. I would definitely recommend this book for developers, architects and administrators who are ready to dive into the topic.

Wednesday, October 26, 2011

Something Else I Need to Remember About Groovy

This is something else I need to remember when writing a Groovy script.
def c = "closure"
m = "method"

def myClosure = {
    println c
}

def myMethod() {
    println m
}

myClosure()
myMethod()
The above works as I expect it to. As soon as I change line 2 to this...
def m = "method"
...I get an error. Just something that I need to keep in my head on the Groovy Console.

Tuesday, October 25, 2011

A Quick Reminder About Using a Language

Let's say I decided to do all this work...
def boolean isNumber(String s) {
    try {
        int i = Integer.parseInt(s)
        return true
    } catch (Exception e) {
        return false
    }
}
In order to do this...
println isNumber("4")
println isNumber("-4")
println isNumber("t")

To get this result...
true
true
false

When all I needed to do is use the language features...
println "4".isNumber()
println "-4".isNumber()
println "t".isNumber()​​​​​​​​​​​​​​

To get the same result with a lot less coding...
true
true
false

Monday, October 17, 2011

Focusing on Business Continuity, Scalability and High Availability

Business is 24/7 and customers want access to your product at their convenience. As a developer and designer of many public facing applications, I find this is one of the most overlooked concepts when businesses are looking to improve their existing applications. 

We are in a world where free, social networking applications perform above and beyond most "enterprise" level applications. Our business customers are experiencing this availability and performance and they are going to start looking to internal IT staff and infrastructure teams to step things up. If you are part of a company's internal IT staff, you should understand how some of the top social sites are managing PetaBytes of data and millions of concurrent online users. The actual capacity numbers may not match up to your work environment but an important quality of scalability is being able to scale up as well as scale down.

Just some thoughts of what is on the horizon for professional IT staffers who are considering on being relevant as "enterprises" embrace the lessons learned by many of the top technology companies.

Monday, October 10, 2011

Making Some Changes

I have recently been making some changes to how a lot of my current Web environment works. I have moved the content from thejavajar.com to my Blogger account, changed the title of this blog from Working IT to Entertainment for Curiosity and I have been working on moving to new hosting providers.

I will be hosting various applications on Google App Engine utilizing Gaelyk(Groovy) and I will be firing up a more permanent Amazon infrastructure to support Java/Grails/Rails development. The amazon infrastructure will also support more of my experimental and proof of concept activities. I will also be digging deeper into Cloud Foundry and Heroku.

Lately, I have been more interested in a wide variety of development technologies and I really want to focus on sharing my experiences that are truly driven by my curiosity. I really believe that as a developer I should evaluate and investigate new technologies every so often to stay relevant and to be able to make sound technological decisions.

I am extremely excited about the future of software development and all of the incredible choices developers have to write meaningful applications.