Social Icons

twitterfacebookgoogle pluslinkedinrss feedemail

Tuesday, December 13, 2011

Using Spring and MyBatis for non-POJO Data Retrieval

This post will be part one of two dealing with data retrieval in Spring with MyBatis. This post in particular will discuss data retrieval whereby you have a situation where you do not have a DB Schema-to-POJO relationship, e.g. in a properties or settings table.

I won't get into how to set up a Spring datasource bean and will assume you already have one in your Spring config file.  In your Spring config file, per http://code.google.com/p/mybatis/wiki/Spring, add a new bean to configure your SqlSessionFactory using the datasource you defined above.

Next, the mybatis-spring library allows us to wire up things automagically (without declaring our mappers in XML) with the following:

<!-- scan for mappers and let them be autowired -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="com.foo.persistence"/>
</bean>

This tells the scanner to recursively scan the com.foo.persistence package and create Spring beans for each mapper it finds. If you're using only one datasource, you don't even need to wire that in as the scanner will take care of this for you.

Next, you'll need to create a mapper class like so:

package com.foo.persistence;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

public interface SettingsMapperInterface {

  @Select("SELECT value FROM settings WHERE name = #{name}")
  String getValue(@Param("name") String name);

  @Insert("INSERT INTO settings VALUES(#{name}, #{value})")
  void setValue(@Param("name") String name,
                @Param("value") String value);
}

This defines two methods, one for getting a value from our settings table and one for inserting a value into our settings table. Note that the package name matches what we defined as the "basePackage" for the scanner bean above. Remember that this is recursive so we could have put this in package "com.foo.persistence.settings" and it would still work. In fact, for larger systems, organizing your mappers by package is probably not a bad idea.

Next, let's define a Spring service that is responsible for interacting with the database. This is our DAO layer or business layer. We don't want to pollute our controller with business logic and vice versa - i.e., we don't want to put any UI or action logic in our business layer. Here's what the service class looks like:

package com.foo.service;

import com.foo.persistence.SettingsMapperInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class SettingService {

  public String getValue(String name) {
    return this.settingsMapper.getValue(name);
  }

  @Transactional
  public void setValue(String name, String value) {
    this.settingsMapper.setValue(name, value);
  }

  @Autowired
  private SettingsMapperInterface settingsMapper;
}

Recall how we said above that the scanner automatically creates Spring beans for each of our mappers. Here, you can see we are autowiring this bean into our service class. One note on IDEs, my IntelliJ instance complains about there not being a bean defined with the SettingsMapperInterface type. This is annoying, but it's not a problem. At the time of this writing, I could not find any MyBatis support for IntelliJ.

Finally, we can autowire our service up like any other bean as follows:

package com.foo.controller;

import com.foo.service.SettingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Controller
public class SettingController {

  @RequestMapping(value = "/foo/getSetting",
                  method = RequestMethod.GET)
  public void getSetting(HttpServletRequest request,
                         HttpServletResponse response) {

    String settingName = request.getParameter("settingName");
    String settingValue = this.settingService.getValue(settingName);

    // do something with "settingValue"
  }

  @Autowired
  private SettingService settingService;
}

Here, we pull the name of the setting we want to retrieve off of the request as a parameter (called "settingName") and pass it to the service method for retrieving a setting's value from the database. We can then take this value and do anything we want with it.

Monday, December 5, 2011

Reading Spring Controller and RequestMapping Definitions

My current, major task at work is to bring two existing web applications into one utilizing a single-signon mechanism and overhaul the UI based on my recommendations previously made.  Part of the background architecture work involved in allowing the creation of a menu structure that would ultimately be utilized to create a similar structure in the UI.

I wanted to use JAXB to unmarshall my menu XML into Java objects but I suspect the complex nature of the XML schema and some limitations of the JAXB framework combined with my lack of a complete understanding of JAXB hindered this process to such a degree that I had to stop due to the time I was spending on it.  So, instead of getting the created objects "for free" I had to resort to writing my own SAX Parser event handler to build up the menu structure in Java land.  I had tried a DOM-based approach first, but the recursive nature of the elements made me cringe a bit while writing the code and if you ever have the thought of "there's got to be an easier way to do this" while writing code, your best bet is to just flat out stop what you are doing and take some time to thoroughly think things through before spending any more time on the task.

The event handler also built up the menu item URI paths using attributes on the hierarchical menu structure in the menu XML.  This gave the menu item actions (arbitrary) name-spacing.  I say arbitrary because when using Spring MVC with only one DispatcherServlet, the URI paths are essentially meaningless.

One other thing I wanted to ensure was that we would never have a dangling menu item - that is a menu item defined (and in the UI) but not actually tied back to a Spring Controller method.  So, I created a unit test that loads my menu XML, pulls a list of all the RequestMapping annotated methods, and confirms that every menu item ties back to a server-side method.

Here's the code:

  Map<String, Object> controllers =
    this.ctx.getBeansWithAnnotation(Controller.class);
  for(Map.Entry<String, Object> entry : controllers.entrySet()) {

    Class controllerClass = entry.getValue().getClass();
    for(Method method : controllerClass.getDeclaredMethods()) {

      RequestMapping rm =
        method.getAnnotation(RequestMapping.class);
      if(rm == null) {
        continue;
      }
      else {

        String[] vals = rm.value();
        if (vals.length == 1) {
          this.mappingSet.add(vals[0]);
        }
        else {
          String msg =
            "this test assumes only one request mapping per method.  " +
            "check class: " + controllerClass + " and method: " + method;
          Assert.fail(msg);
        }
      }
    }
  }

Two notes:

  1. The reference "this.ctx" refers to a Spring ApplicationContext, in my case here an instance of the XmlWebApplicationContext class that loads my Spring configuration.
  2. The reference "this.mappingSet" is simply a class-local field (HashSet<String>) in which I simply store the RequestMapping values.
Finally, after this is complete I confirm that every menu item action URI is contained in the set of extracted RequestMapping values.

Friday, December 2, 2011

Five Weeks Post-Op

Today I'm five weeks out from knee surgery and it's doing awesome.  I started swimming again and after a hectic November travel schedule with a fifth anniversary vacation to Jamaica followed five days later by a trip to the in-laws for Thanksgiving I hope to establish more of a training routine because quite frankly I've lost my fitness and put on a little extra weight.  I'm not so much worried about the weight because it was gained from doing nothing for the first three weeks after the surgery and I gained nothing over Thanksgiving (a rare feat).  But I am disappointed about the loss of fitness because it's so damn hard to get back at first, i.e., the first week or two suck.

I remember when I took four months off after IM CDA in 2009 to let my foot fully heal that the first week or two I struggled to even run a mile.  Now that all the travelling is out of my schedule for the foreseeable future, I can start a training schedule again:  Master's swimming 2x a week and some trainer time.  I've been allowed to ride the trainer, but haven't gotten around to even setting it up yet.  This weekend for sure....along with all the other crap I have on my list.

Tuesday, September 20, 2011

Busy Summer: Injury and Fatherhood

There won't be a part II.  It's been too long and I really don't want to relive that day again.  Psychologists would say the more you talk about a thing, the less that thing holds power over you.  Yea, I can live with that for now.

My first race of the season was also my last race.  About a week prior to my first race, the Summer Open Triathlon in mid-May, I started having right knee issues.  I figured I could fix it on my own but it just never got better.  I saw Matt at Altitude for a ton of sessions and got to the point where I was able to run again pain free but it didn't last.  I've now not run since early August and now the pain manifests itself randomly after bike rides.

I've officially hung up the tri and road bikes opting for some quality mountain biking.  It was clear from the first few rides that being fearless on a road bike is easy but being fearless on a mountain bike requires cojones I don't know that I will ever possess.  That said, my bike handling skills are improving and I have been able to navigate some rough terrain with increasing ease.  I suspect this will change when I have my first wipeout, but so far, my clothes have remained clean.

This past Saturday I did an epic, 2.5 hour trail ride covering some 30 miles.  I don't have the climbing data, but I'm sure it was in the multiple thousands of feet.  That afternoon, I could barely walk because of my knee.  Sunday was a bit rough as well and I would have to randomly do some stretches to get it to stop hurting.

Recalling something Uli mentioned at Master's swim about how, possibly, bike position might aggravate the injury I made an appointment to see Mark Plaatjes to get a different take on the injury and fixing it.

Fatherhood has been fantastic.  It's really cool to see the development of a child - to see when they first start learning even the most basic of things, like smiling.  It's also a lot of work because they require nearly constant attention when awake which can be very mentally draining.  Elin is sitting up now and rolls around quite a bit.  She's starting to figure out how to pull her knees up under her and I suspect she will be crawling within a few months.

Sunday, February 13, 2011

Husband, anchor...daddy - Part I

At 12:54 PM on February 10th, 2011, Elin Hannah Gordon was born.  Until about 5 minutes before this time the pregnancy and labor was normal if not routine (I will not go so far as to say that labor is easy - given the amount of pain my wife was in during some of her contractions).  The next 3.5 days were anything but.

At around 11:30 AM, my wife was fully dilated and ready to push.  She pushed for around an hour with the baby not moving.  The baby was face out and LOC, essentially at ~10 o'clock facing my wife.  The ideal position is face in toward the spine, however no amount of rotating got her to rotate correctly.  at 12:30, we were told that the baby had not come down any and that it didn't really make a whole lot of sense to push for another several hours only to have to have a Caesarean anyway so we made the decision to go ahead and have one.  I went ahead and texted various family members thus.  What I can only imagine as hell for them, the next time I spoke to most of them was over 3 hours later with my phone going crazy during that time.

Around 12:48 or so the anesthesiologist came in and administered a Caesarean dose into my wife's epidural and an antibiotic for the operation to prevent infection.  Not long after that my wife complained of having trouble breathing and our OB said that this was perfectly normal.  The epidural medicine numbs everything downward from the insertion point which includes the diaphragm - the muscles that control breathing.  During the approximately 40 seconds it took to walk from our labor and delivery room (my wife on the labor and delivery bed) to the OR my wife continuously complained of it being very difficult to breathe to which our nurse replied that this was completely normal.  By the time we got to the doors of the OR, my wife was in a bit of a panic and this was the last thing she remembered until 2 AM on Friday.

What happened next is something I can only hope no one ever has to experience.  Ever.

They wheeled my wife's bed into the OR and I sat on a stool by the doors watching as my wife passed out and stopped breathing - her lips turning blue.  The people in the OR were busy prepping the table to transfer my wife over and didn't notice for several seconds.  Then they noticed and all hell broke lose.  Those next 60 seconds were quite a blur as several ran to the wall and there was some confusion for several seconds as to the alarm to pull and what to say.  Seconds later, the lever pulled an announcement was made (and I'm paraphrasing because I don't remember the exact words) "Code yellow, labor and delivery OR.  Code yellow, labor and deliver OR."  Within seconds there were probably 40 people in the OR.  I remember them talking, but not about what.  I was just sitting there watching.  Finally, I was kicked out by one of the anesthesiologists to go next door to what was the recovery room for women who have "routine" Caesareans performed - my wife never made it into that room and instead went straight to the ICU.

I was in that room for maybe a minute or two before someone came in and said "Congratulations, time of birth 12:54."  They then asked if I wanted to go in and [re]cut the umbilical cord (as the baby station is about 15 feet away from the operating table, the OB cuts the cord leaving enough for dad to cut it again).  Seeing the clock on the baby station, I realized (and this was confirmed later by my OB) that the baby was removed within seconds of my leaving.  Typical Caesarians take around five minutes to get the baby out.  My wife's was done in under one.  After cutting my daughter's cord and inquiring about her 2nd Apgar score I carried her next door to watch her get her vitamin K shot, the eye gook they put in to prevent infection, and some blood draw on her heel (I think for sugar?).

After that they took the baby away to do more things and I must have had ten different doctors and staff members come in to talk to me.  I don't remember anything they said.  At some point I left to go up to the  well-baby nursery (which is part of the NICU, but for healthy babies) to feed Elin for the first time.  I fed and burped her and then was taken back downstairs to wait for my wife to be rolled out of the OR.  We followed her and her entourage of doctors to the elevator where six or eight of them got on the elevator with them and myself and 4 others took the stairs one floor down.  We met them at the elevator and walked to the ICU where I was promptly not allowed in.  I suspect it was around 2 PM at this point.

I was escorted back upstairs and I realized my Dad and stepmom had been there for an hour and I'd not spoken to them since the aforementioned text I sent just prior to the Caesarean decision.  They'd heard the code yellow and managed to get some nurses to tell them that it was Rachel so they knew what to expect.  I found them in the waiting room and hugging and sobs ensued.  I had (and still do) have a lot of pent up emotion about everything that had transpired.  I went to get Elin from the nursery and by this time she'd had a bath and was fed, clean, swaddled, and content.  With my parents, I wheeled her back to the room in which they were letting me stay.  At some point someone came to say that I could finally go into the ICU to see Rachel so I dropped Elin back off at the nursery and went down with my parents. At some point during all of this, my parents forced me to eat a sandwich as I'd not eaten since around seven or eight that morning.

I had them wait outside as I went into her ICU room and words cannot describe that sight.  Rachel was hooked up to every possible machine imaginable, including a respirator, with a tube down her throat.  That's not a sight I would wish for anyone to see.  She was completely unconscious and unresponsive to my voice.

I don't remember how long I was there but eventually went back upstairs and said goodbye to my parents insisting that I didn't need anything.  Next to arrive was my friend Ashley and then her fiancé, Dov.  They helped me get my clothes and stuff from the car to bring to the room.  I don't remember if they saw Elin then or not but at some point they, too left.  My sister came down last and met her boyfriend Matt there.  By that time I had gotten Elin from the nursery and needed to do some bonding as I'd really only seen her twice since the ordeal began.  My sister held her for a while and after they left I removed my shirt and lay on the bed for some skin-to-skin contact with my daughter, which is über important for the bonding.  We lay there for 30-45 minutes and when I started to realize that I was dozing off, I brought her back to the nursery.  I returned to my room, got ready for bed and passed out.

Saturday, February 5, 2011

Different Strokes

Over the past few years I've asked my Master's swim instructor about proper stroke technique.  To his credit each time he's said the same thing.  I don't know if something just finally clicked or I actually started paying attention to my stroke and applying what he said because when your stroke is on, you really move and it seems to take less effort.

He said it makes sense because when your stroke mechanics are on, you are using more than just your arms.  Your lats, back, and core all get involved and with the added muscles, you have more power and if you're rotating your body correctly, you have less drag.  I believe this is why when he gave us a 6x[100m @1:20, 75m @1:25] I was actually able to do the 100s and still get rest when normally 1:20 is way out of my league.  This was Tuesday.  Last night we had 4x300m @4:30 with increasing blocks of 25s in between.  While the 300s were on a 1:30 base, I was getting at least 10 seconds rest after each one and it was without paddles.  In fact, I didn't need paddles the entire workout - which is a first for me in a while.

I hope the speed continues in the water and carries over to my races.