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!

Thursday, August 8, 2013

Groovy moonlighter mistake: Spock requires JUnit to run inside Eclispe

Setup

I was rushing a bit the other day to get a new project setup in Eclipse.   The project is for some RESTful API work we are doing.  Naturally, I started looking for a way to inject Groovy into the process (regardless of how much resistance I continue to encounter from my colleagues).  :-)    Why not include the Spock testing framework I thought.  Great, if the team doesn't want to use Groovy, they can still write their test cases the old way, but I am going to inject Spock to the project!

Now I am off and running:
  • Eclipse project created: check
  • Added Groovy Nature to the Eclipse project: check
  • Included the Spock jar in the build path: check
  • First test case written using Spock and it compiles: check
  • Run my test case from within Eclipse: WTF, Eclipse where's the JUnit menu option (screenshot below)

Resolution:
Spock requires JUnit to run inside Eclipse (duh!).   So I added the JUnit jar to my build path and now as you can see in the screenshot below - all is better with my world - now I can run my Spock tests within Eclipse!


I have to thank danveloper for the tagline "Groovy moonlighter".  We were exchanging emails about one of his projects when I complained that my Groovy practice is limited to nights and weekends.  At that point he called me a 'Groovy Moonlighter".   Thanks Dan!

Hope this helps!



Monday, July 8, 2013

Book Review: Making Java Groovy

Overview
This review might be considered 'jumping the gun' a bit since this book has not been officially released yet.   Only the last chapter (Chapter 11) remains but honestly, even if that last chapter said "This chapter intentionally left blank", it would not adversely affect my review.   I signed up for the MEAP program for this book after hearing Ken Kousen present some of this material at my local Java Users Group.

Contents
The book is broken into 3 parts:

  1. Part 1 - Up to speed with Groovy includes 3 chapters that discuss why adding Groovy to Java, Groovy examples and Code-level integration.
  2. Part 2 - Groovy Tools covers Build processes and Test Groovy and Java projects.   These chapters in very handy and timely.  While reading these chapters I was introducing Groovy into our Java project and the discussion on how to handle builds mixed with Java and Groovy resolved one of my outstanding questions.   The next chapter helped answer other questions about how to handle testing in this 'mixed' environment.
  3. Part 3 - Groovy in the Real World covers integration with Spring, databases, SOAP and REST 
This is also an Appendix that does a very high-level overview of the Groovy for the folks new to Groovy, without stepping on the toes of "Groovy In Action"


Pros:

  • Great reference that hits all the high points like builds, testing, web services, Spring and databases
  • Covers most of the scenarios that you will encounter when including Groovy to your Java projects
Cons:

  • Footnotes have a different context when reading Ken's book.  For the most part, the footnotes in the book are there to:
    • apologize for a bad joke or pun or
    • explain a joke or reference from the earlier in the text
Summary
This is an excellent book for Java developers wanting to get started with Groovy.  This books helps answer some of the possible nagging questions like "How do I handle the builds/compiles?" or "How do I test Java and Groovy code together?".

This book is a definite BUY, and I am still waiting on Chapter 11 - The Future.


Monday, May 27, 2013

Book Review: Getting Started with NoSQL

Overview
Unless you've been living under a rock, you have at the very least,  heard of NoSQL.  You may not know much about it, what types of NoSQL databases exists, what the functionalities they provide or even know the names of some NoSQL databases.  If this is true, then Getting Started with NoSQL is for you.  The book will help guide you thru an evaluation process of NoSQL databases, considering a set of requirements and use cases with which to help evaluate each type of database.

Contents
  • Overview of NoSQL
  • Characteristics of NoSQL
  • NoSQL storage types
  • Advantages and Drawbacks
  • Comparative Study of NoSQL products
  • Case Study
Pros:
  • Quick read, only 142 pages
  • Provides a good comparison of the NoSQL database types vs the RDBMS, and what NoSQL is and is NOT.
Cons:
  • Lots of hyperlinks within the text - this was my first time reading an e-book on a Kindle so I don't know if that is typical of not.  I expect that is not the case.
  • Comparatively light coverage of Graph databases vs more popular types, for example Document store
  • Described as appropriate for "technology decision makers - be it architect, product manager or CTO".   I would agree this book is appropriate for developers, architects and possibly product managers.      

Conclusion
The book takes an analytic approach to comparing different NoSQL database types based on a specified set of criteria.   It walks you thru the comparisons, evaluating how each database type rates in terms of the criteria and merely suggests which database type they feel would be most appropriate for the use cases being evaluated.

Tuesday, April 30, 2013

Book Review: Gradle Effective Implementation Guide

Overview
The choice of build tools in the Java space has basically been Ant or Maven since the early days of Java.   Ant was the first tool to arrive and then Maven was created to help provide standardization, assuming you drank the Maven Kool-Aid, meaning that you could live with the standards set out by Maven.

Now a new build tool has arrived, Gradle.  Gradle adoption started slowly at first, but has definitely been picking up momentum as more and more projects migrate from either Ant or Maven over to Gradle. Gradle can't be ignored!

Gradle is built on top of the Groovy.  The tool provides a rich Domain Specific Language (DSL) based on Groovy. The DSL is the key component of Gradle.

Contents
  • Starting with Gradle, creating and working with build scripts 
  • Gradle for Java projects
  • Dependency management
  • Testing building and publishing artifacts
  • Multi-project builds
  • Gradle with Groovy and Scala
  • Maintaining code quality with tools like Checkstyle, PMD, FindBugs, JDepend, CodeNarc and the Sonar plugin - one of my favorite chapters since I recommend using code static analysis tools for improving code quality
  • Using Gradle with Continuous Integration - covers Jenkins, TeamCity and Bamboo
  • IDE support - provides excellent coverage of Eclipse and IntelliJ IDEA support
Pros
  • Very good reference guide
  • Sample source filled with a lot of complete examples
  • It's by Mr. Haki, creator of Groovy Goodness, Grails Goodness and of course, Gradle Goodness blog postings!
Cons
  • I started out running and verifying every example, but after submitting 6-7 errata for just the first chapter, I stopped running all of the examples and dropped back to just executing examples that peaked my interest.
  • The book contains only a single reference to Ant and no discussion on Gradle's integration with Ant.  In all fairness, Ant integration is not listed in the bullet points on the back of the book that shows "What you will learn", but I think that is a mistake.  Readers are going to be coming from either Ant or Maven and will be looking for help in migrating to Gradle or for help on how to do things in Gradle that they are already doing in Ant or Maven.
  • The book is 356 pages but a lot of pages are 'eaten up' by showing the output of all the example build scripts,  and screen shots from Chapter 11, Using Gradle with Continuous Integration and Chapter 12 IDE support.
Summary
The book is a very good reference for using Gradle and I would definitely recommend it for anyone interested in learning more about Gradle.

Gradle thoughts (not specific to the book)
This the second book I have read on Gradle.  I have read the User's Guide a couple times over the last two years in an attempt to get a firm grip on Gradle.  One of my challenges is that I don't get to use Gradle in my day job, just at night and on weekends.   This limited use seems to extend the learning curve, which I think for Gradle is larger/longer than other tools.

"Convention over configuration" is great for reducing the amount of code in projects, BUT somewhere the user needs to know where the conventions are defined.   I think one of the keys to learning Gradle is to get a firm grasp on the Gradle DSL.  Without a grasp on the DSL,  a new Gradle user just keeps wondering "Where are these properties/methods coming from?"

Monday, February 18, 2013

Minor Gotchas from migration to Java 7

After several years of pushing, we are finally starting to pull our application out of the dark ages  in terms of software levels and one of those steps is upgrading our Java version to Java 7. For the most part, this has been fairly painless, but there have been a couple surprises:
  • Test cases that had been running successfully for years started failing when we switched to Java 7.  It turns out that we had some test cases that depended on previous test cases within the same class.  This is bad on two fronts, 1) the test cases should each be independent and 2) the execution order of test cases within a test class is not guaranteed, although, up to now(before Java 7), the order was the order found in the source code.  I found this link that helped explain the inconsistent ordering I was seeing within Eclipse.  This is not a problem with Java 7 but rather with our test cases.   Just  something that cropped up when we started running with Java 7

  • Our Swing clients began throwing ClassCastExceptions, and this is code that has been in place for over 10 years, dating back to Java 1.4   Reading the javadocs helped explain the problem, but I decided to research a bit more to find out exactly why this was happening now.   We were adding entries to a TreeSet to hold forward and backward traversal keys for the FocusManager, putting KeyStroke objects into the TreeSet.   The javadoc clearly states that the objects put in the TreeSet (or TreeMap underneath) must be Comparable or you need to create the TreeSet with a Comparator for ordering the objects. We were doing neither,  and not getting exceptions.  Digging into the java source code,  I found that starting in Java 7, the TreeMap class has starting enforcing this 'requirement', where the earlier versions of the class had that code commented out, thus not really requiring the comparator.    The fix was easy, I created a KeyStrokeComparator and passed that to the TreeSet constructor.

  • I also noticed that our java jar signing had started logging a warning about the certificate not being valid.   Wanting to keep the build clean and not have these warnings, I did some searches and found several postings related to Java 7 and the removal of the MD2withRSA algorithm from the code signing certificates.   I worked with support from Verisign to help with the removal of that algorithm from our certificate chain and the warning went away!  Unfortunately, that was not the end of the code signing problems.   

  • Next, our web start clients would no longer start successfully, instead throwing an exception with the all-too-familiar  'not all jars signed with the same certificate' error message frequently encountered by web start programs, at least during development!  I've written another blog post about how to help debug through this and figured it was just 'one of the usual suspect jars' that we have problems with, but nope, that wasn't it.   Knowing that all this happened since the certificate was updated caused me to review all of our signed jars to look for clues.   All the jars had been signed with the same certificate, but the 3rd party jars were signed BEFORE the chain entry was remove, whereas our application code was signed as part of the build process, AFTER the certificate was changed.   This led me to believe that even though the jars were signed with the same certificate, that there must be some difference between the jars signed before and after the change to the certificate.   

  • When jars are signed,  entries are generated in the MANIFEST.MF file inside the jar, one entry for each class in the jar.  These entries contain the name of the class along with some signing algorithm information and after reviewing the MANIFEST.MF files,  I found the difference.  The 3rd party jars signed before the change included a SHA1-Digest entry for each class but our jars signed from the current build contained entries with SHA-256-Digest.   Re-signing all of our 3rd party jars with the updated certificate resolved most of the problems.   We had a minor problem in our re-signing process, where we over-wrote the existing MANIFEST.MF with our own generated version and this caused problems for a couple of jars that contained additional service provider information in the manifest file.
All in a days work!  Just Happy to be current on the Java level.  Next up, migrating to EJB3 and Hibernate 3 or 4.

Hope this helps!