Wednesday, January 21, 2015

"I detect a disturbance in the (Groovy & Grails) Force"

As you may know by now, Pivotal recently announced that it will be withdrawing funding support for the Groovy and Grails open source projects after March 31st 2015.    For more information, you can listen to Peter Ledbrook's recent podcast with Graeme Rocher and Guillaume Laforge, the project leads for those projects.

When I first heard the news, I felt like I had been "punched in the gut".   While not an overly active member, I have considered myself part of the Groovy and Grails community for the past couple of years.   I started playing around with Groovy in 2009 and have been hooked ever since!  I know I drove folks crazy at my last job talking about all the things we could do with Groovy.

Based on a comment from Graeme in the podcast,  I have created this posting to share what I have done with Groovy and Grails in the past.  And hopefully more to come!

  • I started by reading Groovy in Action 
  • Then starting reading other Groovy and Grails books  
  • I subscribed to the GroovyMag for several years.  
  • I have attended our local Groovy and Grails user group meetings
  • I haunted Venkat Subramanian and Ken Kousen at the local NoFluffJustStuff conferences, attending all of their Groovy and Grails talks.
  • I even sneaked some Groovy code into a project at work after reading Making Java Groovy
  • My attempt at adding the Spock testing framework for our testing was unfortunately met with a lot of resistence - which I still can't understand! :-( 
  • And this blog was originally created as place for me to share all of my new Groovy and Grails knowledge with others interested in learning.
Groovy & Grails re-kindled my enthusiam for programming and for that, I would like to say "Thank You" to these teams.

The Groovy/Grails community is awesome and hopefully will to grow and prosper.  It is my hope that a large organization steps up and takes over responsibility for both projects.  The core teams for both of these projects are a set of very sharp individuals and should have no problems finding work.   Let's just hope for the sake of the Groovy & Grails community that they get the opportunity to stay together and continue their fine work, because I am guessing some of them probably felt like they got "punched in the gut" too.

Best of luck guys!




Thursday, March 20, 2014

Book Review: Programming Groovy 2 Dynamic Productivity for the Java Developer

Overview
"Programming Groovy 2 Dynamic Productivity for the Java Developer" is Dr. Venkat Subramaniam's latest book covering Groovy and important features of this dynamic language.  The book goes into detail on how to use many of the dynamic features of the language and can help make you more productive with the language.

The book is broken down into 4 parts (see below), with 19 chapters covering approximately 300 pages.  I would not suggest this book as an introduction to the Groovy language, but once you are past the intro-level, this book is a must-have!

Contents

  • Part 1 Beginning Groovy  includes Getting Started, Groovy for Java Eyes, Dynamic Typing, Closures and working with Strings and Collections
  • Part 2 Using Groovy includes Exploring the GDK  and working with XML, Databases, Scripts and Classes
  • Part 3 MOPping Groovy includes 6 chapters on working with the MOP in Groovy
  • Part 4 Using Metaprogramming includes chapters on Groovy Builders, Unit Testing and Mocking and Creating DSLs in Groovy

Pros

  • Excellent coverage on the dynamic features of the Groovy language, including the MOP and Metaprogramming.  
  • Examples are short and to-the-point!  You are not forced to read thru the creation of some sample application being created throughout the reading of the book.  Just enough code to get the point across, and as with almost all books, the code is downloadable. 

Cons

  • The book could have been shorter without a lot of the 'introductory' material from Part 1.  The problem there is, that would cut about 125 pages from the book and I would guess the publishers have some 'bare minimum number of pages' for their books.   

Conclusion
Another awesome publication from Venkat.  A "must have" for anyone wanting to improve their Groovy Kung-Fu.  Venkat covers all the cool features of Groovy in an easily understandable way.

I have bought and read a lot of technical books thru the years, but only had 1 that I carried in my briefcase every day.  Now its time to add another book to the briefcase - Groovy 2 Dynamic Productivity for the Java Developer, and I don't even get to use Groovy in my day job!

Tuesday, March 11, 2014

Parameterized JUnit tests

Sometimes you encounter a problem that just screams for using "parameterized" tests rather than copy/pasting the same method many times.   The test method is basically the same and the only thing that changes is the data passed in.  In this case, consider creating a test case that utilitizes the "Parameterized" class from JUnit.

I recently ran into a problem where our validation of an email address did not allow unicode characters.  The fix was fairly straight-forward, change the regular expression to allow those characters.  Next, it was time to test the change.  Rather than copy/paste separate methods for each set of data, I decided to learn about the Parameterized method.   Below is the result.  The data includes the expected result and the email address to be validated.

JUnit test class
package com.mycompany.client;

import static org.junit.Assert.*;

import java.util.Arrays;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import com.mycompany.test.TestServiceUtil;

/**
 * Parameterized test case for validating email addresses against a regular expression.
 * We need to allow unicode characters in the userid portion of the email address, so 
 * these test cases where created to help validate the validateEmailAddress method
 * in the FieldValidationController class.
 * 
 * @author mmiller
 *
 */
@RunWith(Parameterized.class)
public class TestFieldValiationController {

    @Parameters(name = "{index}: {1} is valid email address = {0}")
    public static Iterable data() {
        return Arrays.asList(new Object[][] { 
         { true, "john@mycomp.com" },           { true,  "john123@mycomp.com" },
         { true, "j+._%20_-brown@mycomp.com" }, { true,  "123@mycomp.com" },
         { false, "john brown@mycomp.com" },    { false, "123@mycomp" },
         { false, "john^brown@mycomp.com" },    { true , "1john@mycomp.com" },
         { false, "john#brown@mycomp.com" },    { false, "john!brown@mycomp.com" },
         { false, "john()brown@mycomp.com" },   { false, "john=brown@mycomp.com" },
         { true,  "johñ.brown@mycomp.com" },    { false, "john.brown@mycomp.coñ" },
         { true,  "johú@mycomp.com" },          { true,  "johíáó@mycomp.com" }
        });
    }
  
    private boolean expected;
    private String emailAddress;

    public TestFieldValiationController(boolean expected, String emailAddress) {
        this.expected = expected;
        this.emailAddress = emailAddress;
        TestServiceUtil.getInstance();
    }

    @Test
    public void validateEmail() {
        assertEquals(expected, FieldValidationController.getInstance().validateEmailAddress(emailAddress));
    }
}

Hope this helps!

Monday, March 10, 2014

Creating a simple JAX-RS MessageBodyWriter

JAX-RS is really cool and with the help of JAXB a lot of response data types can be converted for you simply by adding annotating the data objects with JAXB annotations.  I am fairly new at JAXB but some simple cut/paste of annotations will take you a long way.

There maybe some types of data that you can't or won't annotate for the purposes of returning that data type from a JAX-RS resource method.   One simple example is returning either a boolean (primitive) or the wrapper Boolean class.   I read a question on StackOverflow where someone asked if they could return a boolean from a resource method and since I didn't know the answer, I decided to try it!  My version only returns XML, not JSON but you should get the idea.

I started with the Jersey User's Guide HelloWorld example and starting modifying from there.  I used the pom.xml and the only change was to uncomment a block to allow using JSON.

Main class 
This the main class from the Hello World example without any changes.

package com.example;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

import java.io.IOException;
import java.net.URI;

/**
 * Main class.
 *
 */
public class Main {
    // Base URI the Grizzly HTTP server will listen on
    public static final String BASE_URI = "http://localhost:8080/myapp/";

    /**
     * Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
     * @return Grizzly HTTP server.
     */
    public static HttpServer startServer() {
        // create a resource config that scans for JAX-RS resources and providers
        // in com.example package
        final ResourceConfig rc = new ResourceConfig().packages("com.example");

        // create and start a new instance of grizzly http server
        // exposing the Jersey application at BASE_URI
        return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
    }

    /**
     * Main method.
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        final HttpServer server = startServer();
        System.out.println(String.format("Jersey app started with WADL available at "
                + "%sapplication.wadl\nHit enter to stop it...", BASE_URI));
        System.in.read();
        server.stop();
    }
}

Resource class
I created a resource class that included a GET method to return a boolean and another GET method to return the wrapper Boolean class.  Notice the getBool() and getBoolean() methods return XML as the first option.

package com.example;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 * Root resource (exposed at "myresource" path)
 */
@Path("myresource")
public class MyResource {

    /**
     * Method handling HTTP GET requests. The returned object will be sent
     * to the client as "text/plain" media type.
     *
     * @return String that will be returned as a text/plain response.
     */
    @GET
    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
    public String getIt() {
        return "Got it!";
    }

    @GET
    @Path("/bool")
    @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
    public boolean getBool() {
        return false;
    }

    @GET
    @Path("/Boolean")
    @Produces({MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
    public Boolean getBoolean() {
        return Boolean.TRUE;
    }
}


BooleanMessageBodyWriter class
Here's the interesting part, creating the MessageBodyWriter class to allow the resource method to return XML for the boolean or Boolean.

package com.example;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.WebApplicationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.DataOutputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;

@Provider
@Produces("application/xml")
public class BooleanMessageBodyWriter implements MessageBodyWriter {
 
    @Override
    public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        System.out.println("isWriteable called...");
        return type == Boolean.class;
    }
 
    @Override
    public long getSize(Boolean myBool, Class type, Type genericType,
                        Annotation[] annotations, MediaType mediaType) {
        // deprecated by JAX-RS 2.0 and ignored by Jersey runtime
        return 0;
    }
 
    @Override
    public void writeTo(Boolean myBool,
                        Class type,
                        Type genericType,
                        Annotation[] annotations,
                        MediaType mediaType,
                        MultivaluedMap httpHeaders,
                        OutputStream entityStream)
                        throws IOException, WebApplicationException {
 
        StringBuilder sb = new StringBuilder();
        sb.append("").append(myBool.toString()).append("");
        DataOutputStream dos = new DataOutputStream(entityStream);
        dos.writeUTF(sb.toString());
    }
}

I  haven't used Maven before but the following targets are all you need to compile and run the project, after installing maven (of course!).
  • mvn compile - compiles the code
  • mvn exec:java - starts the Grizzly HttpServer and deploys the restful service.
Hope this helps!

Tuesday, January 14, 2014

Book Review: Professional Node.js Building JavaScript-Based Scalable Software

Overview
As a result of the recent explosion of JavaScript's popularity, partially led by Node.js, I decided to spend some time updating my JavaScript skills. I started reading a lot of articles and posts and then came across a recommended approach to learning Node on JavascriptIsSexy.com and decided to give it try.

Contents
The book is broken up into 6 parts(listed below), with a total of 25 chapters covering 350 pages, written by Pedro Teixeira.

  1. Introduction and Setup
  2. Node Core API basics
  3. Files, Processes, Streams and Networking
  4. Building and Debugging Modules and Applications
  5. Build Web Applications
  6. Connecting to Databases
The book is not an introduction to JavaScript, nor does it spend the first couple chapters attempting to ramp up readers on the JavaScript language, which I appreciated.  Readers should already have some basic JavaScript knowledge before reading this book.

Pros
  • Well written and easy to follow along with the code examples
  • The chapters covered the material without getting too long.  Easy enough to spend about 1/2 hour reading a chapter and working through the code examples for the chapter
  • The book got me excited about the possibilities available using Node.js and started me down a new path to help build my "full stack developer" skills.
Cons
  • The code examples were good, but I think it would help early in the book to point out where to find the Node API documentation, otherwise the reader is sometimes left wondering, "How did they know what methods are available, what to call and what to pass to that API?"
  • For all the positive impact NPM has had on Node.js, the coverage of NPM in the book seems a bit light, although that could just be lack of Node knowledge showing!
Conclusion
I was very happy with the book and would recommend it for anyone with some basic JavaScript skills looking to learn about Node.js.

I usually stick to Manning or O'Reilly books but when I started my quest for Node knowledge, neither of those publishers had books covering Node.  This has since changed and I may try one of those out as well.  

Friday, September 6, 2013

Not all JSON created equal, at least from Java implementations!

Setting the stage
I have spent the majority of my career on the 'server-side' of applications. When I have worked on the client side, it has been Java Swing, so up to now I haven't worked much with JSON.   My (incorrect!) assumption was that all JSON is created equal.

We are creating a new REST API for our product at work and plan on supporting both JSON and XML for both the requests and responses.  We are using RESTEasy from JBoss and the process has been fairly straight-forward.

Below is a screen shot of two sets of JSON generated from our CustomerResource using RESTEasy with the exact same code from our perspective. The only difference is how I configured RESTEasy to generate JSON.  In one case, I used Jettison and in the other case I used Jackson.  I expected that both tools would generate exactly the same output - WRONG!  See below for some of the differences.

Results


The results above show a simple customer entry with a set of 1 phone number and a set of 1 address.

I have noticed following differences (there may be others…):

  • Jettison has a name entry for the object whereas Jackson does not (Customer,Addresses, Address,PhoneNumbers, PhoneNumber) 
  • Jettison appears to force all values to a String, using the double quotes, whereas Jackson does not for number fields, like customerId, where it does not double quote the value
  • Jackson is currently showing null fields, like addressLine2 & addressLine3 whereas Jettison is not. This may be configurable. Jackson uses JAXB annotations to assist with its marshaling/serializing and also contains some of its own annotations as well which might be used to help adjust the output.
Hope this helps!

Friday, August 9, 2013

Groovy moonlighter mistake: Not all "method chaining" does what you might think


Setup
I am using Spock to help inject Groovy into our project and currently that means testing our new RESTful API.   We need to be able to send and receive both XML and JSON.    To test our POST method, I created a default Cart object and get the JSON representation.   I decided to try to use curl to call some of the methods, so for this POST method call, I needed to save the JSON to a file.  Later, I wanted to make sure the file was created.

Problem Code
The code below gets a NullPointerException calling the exists() method.

public void "POST Creates New Cart with JSON"() {
   when:
   File f = new File("cart.json").write(getDefaultCartJSON())
   
   def response = '''curl -X POST -i -d @cart.json --header "Content-Type:application/json"
          http://localhost:7001/restservices/carts'''.execute().text
  
    then:
    f.exists()
    response.startsWith("HTTP/1.1 201 Created")
  }
}

Root Cause:
The problem wasn't obvious immediately to me (hey I wrote it!).  The problem is the write() method returns a void, not the file object.

 File f = new File("cart.json").write(getDefaultCartJSON())

Corrected Code
Below is the corrected code.  So you don't always need to assign the result of a 'new' into a variable, even though that's how many of us learned to program.

public void "POST Creates New Cart with JSON"() {
   when:
   new File("cart.json").write(getDefaultCartJSON())
   
   def response = '''curl -X POST -i -d @cart.json --header "Content-Type:application/json"
          http://localhost:7001/restservices/carts'''.execute().text
  
    then:
    new File("cart.json").exists()
    response.startsWith("HTTP/1.1 201 Created")
  }
}

Wrap-up
Obviously this was not some major problem or break-through, just something to keep in mind as you write your code.   Maybe this will help prevent others from making the same mistake(s) I made. :-)

Hope it helps!