2009-12-17

Using Google Collections

I'm sure this is "Old hat" to a lot of people but I just watched these two videos on Google Collections: Part 1, Part 2. The MultiMap is definitely something I could have used many times in the past, and I will use it from now on!

I decided to convert a couple of static final maps in my App Engine project to Immutable ones instead. Previously I was using this method to create and initialise maps:
public static final Map<String, Calendar> iterations = new HashMap<String, Calendar>() {{
  put(TEAM_A, new GregorianCalendar(2009,9,5));
  put(TEAM_B, new GregorianCalendar(2009,8,15));
  put(TEAM_C, new GregorianCalendar(2009,7,21));  
 }};


Now I have this:
public static final Map<String, Calendar> ITERATIONS = 
  new ImmutableMap.Builder<String, Calendar>().
  put(TEAM_A, new GregorianCalendar(2009,9,5)).
  put(TEAM_B, new GregorianCalendar(2009,8,15)).
  put(TEAM_C, new GregorianCalendar(2009,7,21)).
  build();

2009-12-05

GAE 1.2.8 fixes Mail but not JAXB

Since 1.2.8 my work-around for decoding incoming Mail correctly is no longer required. In fact, in 1.2.8, that code now breaks! My example, which only needs a text/plain message or the first part of a multipart message, now looks like this:
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Properties props = new Properties(); 
        Session session = Session.getDefaultInstance(props, null); 
        MimeMessage message = new MimeMessage(session, request.getInputStream());

        Address[] from = message.getFrom();
        String fromAddress = "";
        if (from.length > 0) {
            fromAddress = from[0].toString();
        }
        
        Object content = message.getContent();
        String contentText = "";
        if (content instanceof String) {
            contentText = (String)content;
        } else if (content instanceof Multipart) {
            Multipart multipart = (Multipart)content;
            Part part = multipart.getBodyPart(0);
            Object partContent = part.getContent();
            if (partContent instanceof String) {
                contentText = (String)partContent;
            }
        }
        logger.info("Received email from=["+fromAddress+"] subject=["+message.getSubject()+"]");
        logger.info("Content: "+contentText);
        return null;
 }

The key to this fix is that the calls to getContent() now return the correct object type. So in my case I'm only interested in text/plain and therefore just Strings.

Sadly JAXB still doesn't work so I'll continue to use Simple XML and wait for 1.2.9.

UPDATE: JAXB support was fixed on December 10th without updating the version number.