2010-02-27

Simple Google Gadget on GAE

I've just found how easy it is to create Google Gadgets and host them on App Engine. All you need to do is create a simple page in your App Engine application to be the content of the gadget and then host a URL content type gadget specification that points to that page.

Your Gadget specification will look something like this:
<?xml version="1.0" encoding="UTF-8"?>
<Module> 
      <ModulePrefs 
            height="100" 
            title="My Simple Gadget" 
            description="Test gadget" 
            author="Anonymous" 
            author_email="anonymous+gg@gmail.com"/> 
      <Content 
            type="url" 
            href="http://yourappid.appspot.com/gadget.html" /> 
</Module>

In my case I'm using a very simple GWT application. Make sure that it looks good at 300 pixels wide. The height can vary but don't make it too tall because people are less likely to install it if it takes up too much space.

The URL content type approach allows you to make a normal web page using any tools you like and you can debug it like any normal page.

To put it all together simply save your gadget spec into the war directory of your GAE application and deploy it so it's available on a URL like this: http://yourappid.appspot.com/gadgetspec.xml

Now you can test it in the iGoogle Sandbox which (after you've signed up) allows you to test unpublished gadgets. Add this developer gadget to make life easy.

When you're happy with it submit your gadget and you're done.

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.