Skip to content

Ruby Style Reflection in Java with Boon

RichardHightower edited this page Feb 26, 2014 · 2 revisions

Boon Home | Boon Source | If you are new to boon, you might want to start here. Simple opinionated Java for the novice to expert level Java Programmer. Low Ceremony. High Productivity. A real boon to Java to developers!

Java Boon - Ruby Style reflection for Java with Boon

Many languages have easy to use Reflection libs (Ruby, Groovy and Python). Boon adds this to Java.####

Added Ruby style respondsTo to Java (Duck typing in Java) QUACK

We can invoke methods if they are supported. Unlike Ruby, the respondsTo can be strongly typed (you can pass args). I've used this on projects where I wanted to do dispatch operations for REST and WebSocket.

        FileObject file = new FileObject();
        StringReaderThing reader = new StringReaderThing(lines("Hi mom", "how are you?"));
        List<Object> list = list(file, reader);


        for (Object object : list) {
            if ( respondsTo(object, "open", String.class) ) invoke(object, "open", "hi");

            if ( respondsTo(object, "add", int.class, int.class) ) puts ("add", invoke(object, "add", 1, 2));

            if ( respondsTo(object, "readLine") ) puts ( invoke(object, "readLine") );

            if ( respondsTo(object, "readLine") ) puts ( invoke(object, "readLine") );

            if ( respondsTo(object, "close" ) ) invoke(object, "close");
        }

The above invokes open, add, readLine and close methods if they are found. Above we pass types to see if there is a match. You don't have to pass types, respondsTo can also just check to see if the method exists. The invoke operation should be fairly fast in a tight loop.

You have the option of invoking by argument type match without passing around types (classes) as follows:

        FileObject file = new FileObject();
        StringReaderThing reader = new StringReaderThing(lines("Hi mom", "how are you?"));
        List<Object> list = list(file, reader);


        for (Object object : list) {
            if (respondsTo(object, "open", "hi") ) invoke(object, "open", "hi");

            if (respondsTo(object, "add", 1, 2) ) puts ("add", invoke(object, "add", 1, 2));


            if (respondsTo(object, "readLine") ) puts ( invoke(object, "readLine") );

            if (respondsTo(object, "readLine") ) puts ( invoke(object, "readLine") );

            if (respondsTo(object, "close" ) ) invoke(object, "close");
        }

You can also invoke with a java.util.List (invoke and respondsTo take var-arg Object... by default for arguments) as follows:

        FileObject file = new FileObject();
        StringReaderThing reader = new StringReaderThing(lines("Hi mom", "how are you?"));
        List<Object> list = list(file, reader);



        List <?> openList = list("hi");
        List <?> addList = list(1, 2);

        for (Object object : list) {
            if (respondsTo(object, "open", openList) ) invoke(object, "open", openList);

            if (respondsTo(object, "add", addList) ) puts ("add", invoke(object, "add", addList));


            if (respondsTo(object, "readLine") ) puts ( invoke(object, "readLine") );

            if (respondsTo(object, "readLine") ) puts ( invoke(object, "readLine") );

            if (respondsTo(object, "close" ) ) invoke(object, "close");
        }

        boolean ok = file.closeCalled && file.readLine && file.openCalled && file.addCalled || die();

I also added Go Programming style interface support which is sort of like respondsTo but for interfaces. Please read the wiki and rational for that.

I did not add missing method support yet, but I am thinking about it. So if you call invoke on an object that does not have the method you are looking for then it calls missingMethod. I am considering renaming invoke to call since it is shorter. I started using this feature in Boon.

Lists now has an improved toList as follows (the toList converts an object to a list):

    public static List<?> toList( Object item ) {
       if ( item!= null && item.getClass().isArray() ) {
             ...
        } else if ( item instanceof Collection ) {
            return list( ( Collection ) item );
        }
         ... 
        else {
            return MapObjectConversion.toList( item );
        }
    }

The MapObjectConversion used above implements a toList method that uses respondsTo.

    public static List<Object> toList( Object object) {

        Type instanceType = Type.getInstanceType(object);

        switch (instanceType) {
            case NULL:
                return Lists.list(null);
            case ARRAY:
                return Conversions.toList(object);
            case INSTANCE:
                if (respondsTo(object, "toList")) {
                    return (List<Object>) invoke(object, "toList");
                }
                break;
        }
        return Lists.list(object);
    }

Also the JSON serializer uses it to see if you want to customize the way your serialize your objects as follows:

    public final void serializeInstance ( Object obj, CharBuf builder )  {

        if (respondsTo(obj, "serializeAs")) {
            serializeObject(invoke(obj, "serializeAs"), builder);
            return;
        }

(I need to get the above working with output views. )

Then your objects just implement the serializeAs method and they can return map, list, arrays, primitives, or just some other object that gets serialized to JSON.

Thoughts

Thoughts? Write me at richard high tower AT g mail dot c-o-m (Rick Hightower).

Further Reading:

If you are new to boon start here:

Why Boon?

Easily read in files into lines or a giant string with one method call. Works with files, URLs, class-path, etc. Boon IO support will surprise you how easy it is. Boon has Slice notation for dealing with Strings, Lists, primitive arrays, Tree Maps, etc. If you are from Groovy land, Ruby land, Python land, or whatever land, and you have to use Java then Boon might give you some relief from API bloat. If you are like me, and you like to use Java, then Boon is for you too. Boon lets Java be Java, but adds the missing productive APIs from Python, Ruby, and Groovy. Boon may not be Ruby or Groovy, but its a real Boon to Java development.

Core Boon Philosophy

Core Boon will never have any dependencies. It will always be able to run as a single jar. This is not just NIH, but it is partly. My view of what Java needs is more inline with what Python, Ruby and Groovy provide. Boon is an addition on top of the JVM to make up the difference between the harder to use APIs that come with Java and the types of utilities that are built into Ruby, Python, PHP, Groovy etc. Boon is a Java centric view of those libs. The vision of Boon and the current implementation is really far apart.

===

Contact Info

blog|[twitter](https://twitter.com/RickHigh|[infoq]http://www.infoq.com/author/Rick-Hightower|[stackoverflow](http://stackoverflow.com/users/2876739/rickhigh)|[java lobby](http://java.dzone.com/users/rhightower)|Other | richard high tower AT g mail dot c-o-m (Rick Hightower)|work|cloud|nosql

Clone this wiki locally