Tuesday, December 4, 2012

Spring, Autowire and EasyMock

I've been stalling on writing a number of tests I needed because I was caught up on how easily inject a Mock  into a Service that I wanted to test. The problem  was that I didn't want to go to the trouble of cooking up a separate spring context just for tests not to mention I couldn't rely on data in the DB for the DAO to utilize      after all the point of EasyMock is... EASY!  Well that avoiding writing that test that needed a mock finally bit me when some fast refactoring caused something fail because of the lacking test. That's what ya get, right?

After a good deal of hunting I come across a simple solution that I am surprised was so hard to find...

ReflectionTestUtils.setField(serviceYourTesting, "autowireBeanName", yourMock);

That's it! No, really.  OK OK, that's not all you have to do. You are messing with the Service Beans properties so if you have other tests elsewhere that expect that mock object to not be a mock object you'll have to undo what you did.  This isn't such a hassle though. simply call the following and stash that object to restore after you done with the mock.

Object saveBean = ReflectionTestUtils.getField(serviceYourTesting, "autowireBeanName");

I would suggest wrapping your test in a try/finally so you can make sure that the original bean value is set back before the tests concludes. If you don't do this other tests that expect the original bean may fail.

Happy Spring Mocking!

Wednesday, October 10, 2012

java.lang.reflect.MalformedParameterizedTypeException or (WTH is wrong with my deployment now?)

So the fun part of the MalformedParameterizedTypeException error is that it seems to be caused by many different things at least that is the impression that I get from the Google searches I conducted and the various suggestions for a fix offered on StackOverflow. I think it really comes down to a simple incompatible jar file hanging out on your web server.

I'n my case I am using WebLogic and the local version of WL that I have running right now is 10.3.6, the version on my Dev server is 10.3.5; you wouldn't expects that a version that close together would be such trouble but I cost me a day to figure out what's up. First off I still don't know the name and version of whatever jar is causing the trouble in Dev. I don't have the access to sort it out and now that I know the cause... I just wont do it, problem avoided though not solved. Good enough under a tight deadline.

So on to the point!  Lets say your using Spring as I am and you have a DAO that doesn't require a dataSource because it's just not that kind of DAO. So you don't have to inject anything into the object. Well when you define this DAO and you deploy only to get our friend MalformedParameterizedTypeException  popping up, the cause is defining the bean in an abbreviated xml node such as the following:


<bean class="com.myco.webservices.dao.impl.MyDaoImpl" id="myDao"/>

The fix is so simple:  (Note the ending tag)

<bean class="com.myco.webservices.dao.impl.MyDaoImpl" id="myDao"></bean>


Of course finding that issue in a dozen files with multi-line changes, imports of new packages and implementation of new functionality is um... not so easy.

Wednesday, June 20, 2012

The In and Outs of MongoDB and Jackson


MongoDB has been a great NoSQL solution to work with so far but, there are a few gotchas that I found needed some exploring to get sorted out properly for a Mongo noob.

I have been working with RESTful services for the past couple years but to date, my NoSQL solution has primarily been Membase. Membase is good at what it does but, it is a bit sparse on features compared to the RDBMs that I am accustomed to working with. No, don't worry I am not about to jump into a debate of NoSQL vs RDBMs, I use my soldering iron to solder and my multi-meter to measure volts, each tool for its job! On the matter of Membase vs MongoDB though I have to say that I have quicky developed a strong preference for Mongo. This new appreciation comes from the field indexing and the ability to use regex to search for specific data. Perhaps this is just me finding some similarities between RDBM and Mongo? Sure that and living with out those features in the past has simply resulted in writing code for things that are usually standard issue.

In my current project I am using MongoDB with Java JAX-RS and Jackson. So far things have fit together quite nicely though I did come across a few issues that I had a hard time tracking down detailed information about. I had to just puzzle out these issues and thought someone might find the info useful, not to mention I can look them up when I inevitably forget them in 6 months once all that information is replaced with whatever comes next.

One of those things I love about a MySQL db driver is that it thoughtfully returns the ID for a newly created record so you can easily access it for further use or abuse. MongoDB also does this but, it wasn't at all obvious how the Java driver was returning this value. At first I was doing a query back to the collection to grab the new _id but, this method left me just feeling less then confident that things would always turn out right. What I didn't realize was the Java driver was thoughtfully returning the value by inserting it in the BasicDBObject used to create the insert. I felt a little silly not thinking to look there first but.. well it just wasn't what I was expecting. Here's the code to illustrate.


BasicDBObject dbObject = MongoModelFactory.buildDBObject(model);
DBCollection dbColl = getCollection(collectionName.getValue());
WriteResult result = dbColl.insert(dbObject);

//The _id values is populated in the dbObject after the insert.
dbObject.get("_id");

Related to getting the id comes a Jackson issue. Because the _id is not stored as a String, but as an ObjectId which makes deserializing the value with the Jackson ObjectMapper a bit on the complicated side. The trick here is to create a MongoID object which contains a JsonCreator that knows how to construct the _id.$oid value from the JSON. This was by far the simplest way to use Jackson to get this information out and the object is reusable across all of my DataObjects.  Here's the code:

public class MongoID {
  private String $oid;

  public MongoID(){  
  }
 
  public String get$oid() {
    return $oid;
  }
 
  public void set$oid(String $oid) {
    this.$oid = $oid;
  }
 
  @JsonCreator
  public static String fromJSON(String val) 
      throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();
    MongoID a = mapper.readValue(val,MongoID.class);
    return a.get$oid();
  }
}

The above class is utilized in my BaseModel abstract object to provide a hint to the Jackson ObjectMapper as to what field this is basically by providing a fromJSON method for Mongo's ObjectId . 

The last challenge I ran into was also a Jackson related issue, specifically in serializing an object to JSON and back again. Jackson doesn't like really complicated JSON lists and due to class erasure it has a hard time figuring out what sort of objects are contained in a list. Such a case is simular to the following JSON:

{
    "_id": "4fc151c9ebb11be7d1ae4905",
    "mapPreferences": {
        "bgColor": "#fff",
        "gridColor": "#000"
    },
    "maps": [
        {
            "cols": 30,
            "title": "TestMap",
            "rows": 30
        },
        {
            "cols": 32,
            "title": "TestMap2",
            "rows": 32
        }
    ]
}

Jackson doesn't really have issues with a list of strings but try a list of objects or a multi-dimensional array and Jackson is stumped as to what to do because of  alack of information.  The JsonCreator again provides a solution to this issue! In the above example we have a field called "maps" which contains an array of MapData Objects, with out providing a JsonCreator, Jackson won't know what object is contained in the list and can't instantiate a list with objects of that type. To solve this List of unknown objects issue I have written the folloing code in the MapData Object :

@JsonCreator
  public AdventureData(@JsonProperty("adventureId") String advId, 
          @JsonProperty("mapPreferences") MapPreferences mapPrefs,
       @JsonProperty("maps") Object maps) 
         throws JsonParseException, JsonMappingException, 
                IOException
  {
    this.adventureId = advId;
    this.mapPreferences = mapPrefs;
   
    ObjectMapper mapper = new ObjectMapper();
    String mapsString = mapper.writeValueAsString(maps);
    this.maps = mapper.readValue(mapsString, 
        TypeFactory.collectionType(List.class, MapData.class));
  }

In the constructor above the parameters define the objects but in the case of the "maps" field  it is left to be an Object because it will be deseralized separately since casting to a List is obfuscated by Type Erasure. To construct the List of MapData objects I then used the ObjectMapper to convert the list back to a JSON String then deserialize it! To make it clear to the ObjectMapper what sort of object is in the List I use the TypeFactory to indicate that we have a Collection of the List type here and it contains MapData.  That's about all there is too that. You will need to give the MapData object it's own JsonCreator similar to the one above but that's all you have to do. If only it had been that easy to find a sample on how this is done! I will say that if you know of another way to make this happen please let me know because the Object to string conversion feels a little bit like a Hack though it works perfectly.

I hope this helps you out when your working with Mongo and Jackson for the first time! (After reviewing this post I have come to realize that I will need to describe my generics based DAO that I am using for MongoDB to better explain what I'm doing with the _id value. Look for it in the future!)