25th March 2012

92 Morningside Ave 2nd fire.

()

9th January 2011

Embedded Jetty Configured with Guice Servlet Module

It’s often convenient to start an embedded http server within an application (to expose state of the app) or within functional tests. Obviously such a server would be configured with Guice’s ServletModule.

Following on Z’s comment on the Servlet Module wiki, I sketched out a simple way to bring up an embedded Jetty instance, configured with Guice. An interesting note is how the ServletContextListener is not necessarily required outside a struts2 environment. Nonetheless, I include it to give a full illustration.

The code is this:


class EmbeddedJettyExample {

  public static void main(String[] args) throws Exception {
    Injector injector = Guice.createInjector(new EmbeddedJettyExampleModule());
    Server server = injector.getInstance(Server.class);
    server.start();
    server.join();
  }

  static class EmbeddedJettyExampleModule extends ServletModule {
    @Override protected void configureServlets() {
      bind(Server.class)
          .toProvider(JettyServerProvider.onPort(8080))
          .in(Singleton.class);

      bind(String.class).toInstance("Fred");
      bindConstant()
          .annotatedWith(IdentifiesGreetingReceiver .class)
          .to("Fred");
      bind(HelloWorldServlet.class).in(Singleton.class);
      serve("/hello").with(HelloWorldServlet.class);
    }
  }

  static class JettyServerProvider implements Provider {
    private final int port;
    @Inject Injector injector;

    private JettyServerProvider(int port) {
      this.port = port;
    }

    static JettyServerProvider onPort(int port) {
      return new JettyServerProvider(port);
    }

    @Override public Server get() {
      Server server = new Server(port);
      ServletContextHandler servletContextHandler =
          new ServletContextHandler();
      servletContextHandler.addEventListener(new GuiceServletContextListener() {
        @Override protected Injector getInjector() {
          return injector;
        }
      });

      servletContextHandler.addFilter(GuiceFilter.class, "/*", null);
      servletContextHandler.addServlet(DefaultServlet.class, "/");
      server.setHandler(servletContextHandler);
      return server;
    }
  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.PARAMETER)
  @BindingAnnotation
  private @interface IdentifiesGreetingReceiver { }

  static class HelloWorldServlet extends HttpServlet {
    private final String name;

    @Inject HelloWorldServlet(@IdentifiesGreetingReceiver String name) {
      this.name = name;
    }

    @Override protected void doGet(HttpServletRequest req,
        HttpServletResponse resp) throws ServletException, IOException {
      resp.setStatus(HttpServletResponse.SC_OK);
      PrintWriter printWriter = resp.getWriter();
      printWriter.println("Hello World to: " + name);
      printWriter.flush();
    }
  }
}

This code is submitted at EmbeddedJettyExample.java

Tagged: guice jetty

()

10th October 2010

Flying: 1972

Flying: 1972

()

17th September 2010

A simple REST API client on top of App Engine

Below is a simple rest api client on top of App Engine. It uses basic auth, which is effectively deprecated (to a relative extent) in favor of OAuth. Next step is to integrate an OAuth lib and illustrate how to do that on App Engine.

...
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
...

public class RestApiClientServlet extends HttpServlet {

  // TODO: make these properties
  private static final String USERNAME = "";
  private static final String PASSWORD = "";

  @Override
  public void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setContentType("text/plain");

    try {
      String result = getWebResource();
      response.getWriter().println("Response was:\n" + result);
    } catch (Exception e) {
      response.getWriter().println("Encountered exception");
      e.printStackTrace(response.getWriter());
    }

    response.flushBuffer();
  }

  private String getWebResource() {
    Client client = new Client();
    WebResource webResource = client
        .resource("http://api.foursquare.com/v1/user");
    client.addFilter(new HTTPBasicAuthFilter(USERNAME, PASSWORD));
    return webResource.get(String.class);
  }
}

()

17th September 2010

AdWords API on App Engine (Java) - Part 3

In last week’s part 2 post, I described a close-but-not-quite-there solution to hitting the AdWords API from an AppEngine servlet. In this post, I describe how to work around the final blocking issue, which, when resolved, clears the path for full SOAP-based AdWords API functionality on top of Java AppEngine.

The blocking issue from last week was the class blacklisting within the AppEngine deployment environment: This blacklisting precluded the instantiation of any javax.xml.soap classes. Unfortunately, this blacklisting does not exist within the local dev_appserver environment, and so this is an error detectable only upon updating an AppEngine deployment.

The solution to this problem was conceptually simple: rename the blacklisted classes using jarjar. To implement this solution, I needed a few steps:

  1. create a jar of the javax.xml.soap classes. Doing this was simple:
    1. jar -xvf /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Classes/classes.jar .
    2. jar -cvf javax-xml-soap-1.6.0.jar javax/xml/soap/
  2. add this jar, and all other jars that referenced javax.xml.soap clases, to a new jarjar Ant task within the project build.xml file. For me, all these jars lived in the /lib directory of the penumbrous source tree. They are:
    1. adwords-api-8.1.0-loner-with-issue-62-patch.jar - the loner AdWords API jar patched with the diff I attached to issue 62
    2. axis.jar - the axis 1.4 release (taken from the AdWords API lib_jars download)
    3. jaxrpc.jar - jax-rpc (taken from the AdWords API lib_jars download)
    4. javax-xml-soap-1.6.0.jar - the jar of javax.soap.xml classes I made in step 1
    5. /classes - well not a jar, but the compiled project classes. This directory is necessary to include so that the references to javax.xml.soap classes within the GaeHttpHandler class are renamed.

This jarjar task looks like:

    <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask"
             classpath="${buildlib.dir}/jarjar-1.0.jar"/>
    <jarjar jarfile="${war.dir}/WEB-INF/lib/penumbrousadsapi.jar">
      <fileset dir="${project.dir}/classes"/>
      <zipfileset src="${war.dir}/WEB-INF/lib/axis.jar"/>
      <zipfileset src="${war.dir}/WEB-INF/lib/adwords-api-8.1.0-loner-with-issue-62-patch.jar"/>
      <zipfileset src="${war.dir}/WEB-INF/lib/jaxrpc.jar"/>
      <zipfileset src="${war.dir}/WEB-INF/lib/javax-xml-soap-1.6.0.jar"/>
      <rule pattern="javax.xml.soap.**" result="com.penumbrous.soap.@1"/>
    </jarjar>

To simplify this for yourself, you could use some of the jars I’ve uploaded to the downloads section:

  1. javax-xml-soap-1.6.0.jar - the jar I created in step (1) above
  2. adwords-api-8.1.0-with-issue-62-patch.jar - the patched adwords api library bundled with all its dependent jars (obviates adding axis.jar and jaxrpc.jar to your project)

As a big caveat, be sure not to place the original compiled classes within the /WEB-INF/classes directory of your deploy directory. If you do this, then these classes will be preferred by the AppEngine runtime environment over the identically named classes that exist in the jar from the jarjar task. The difference between these sets of classes is that the classes in the jar will have had their references to javax.xml.soap classes renamed. These classes in the jar are the classes that must be used for the blacklisting solution to work.

Going forward, the patch of the adwords-api library should not be needed, as I have on good authority that the library will itself be made AppEngine friendly. In the short to medium terms, however, I believe using the patched library is the best course of action.

I send a big thank you to both the AppEngine engineers and the AdWords API developers for their assistance in this endeavor; something tells me it won’t be the last time I’ll need to lean on y’all :)

And finally, as a preview for the next exploration in calling AdWords API from the cloud. I plan next to explore a data model for the core AdWords data, as modeled either within the AppEngine Datastore, or within Google Storage.

()

16th September 2010

Using Basic Auth in a Jersey REST Client

I needed to search a bit for an obvious solution to using basic auth in a jersey client. The one-liner is:

client.addFilter(new HTTPBasicAuthFilter(USERNAME, PASSWORD));

()

10th September 2010

AdWords API on App Engine (Java) - Part 2

A while back in this post I highlighted a few links relating to using a SOAP-based client within a Java AppEngine app.

The posts on the other side of those links allude to how it might be possible to build an app with functioning SOAP client on AppEngine, but afaik, no concrete proof of concept of such an app exists (with the exception of a force.com-based app, which is unique because of the custom SOAP client available for force.com web services here). Certainly, no working prototypes of an AdWords API client, running on AppEngine, have been built.

Clearly it is time to change that.

Over the last few days I decided to do this. And with success! That is, until I uploaded the app to the production sandbox. Here, I saw the unfortunate result of two broken systems:

  1. the production environment disallows instantiation of javax.xml.* classes
  2. the dev_appserver does not emulate the production environment, as it allows such instantiation

For (1), there is no immediate solution. I’ll continue to follow-up with the good folks building out AppEngine to see what could be done.

For (2), this is unfortunately a known issue for some ~corner cases. Sure, tools aren’t perfect all the time, and that’s to be expected. But I think these discrepancies need to be made more obviously highlighted within the tool, or as a better alternative, they need to be outright eliminated.

For the record, the code that enables use of the AdWords API Java library on AppEngine is described here.

And here is the more general issue that describes the lack of SOAP support within AppEngine.

I am planning a Part 3 in this mini series of posts that will describe how the blacklisting issue was resolved, and how it will be possible to run AdWords API on top of AppEngine.

-Fred

()

28th August 2010

Running Impact Study

Earlier in the year I banged up my knee a touch. It was nothing big, but it did make for slightly painful running. Because of this I started paying more attention to the periodic vertical displacement of my body when running. In other words, instead of UP, DOWN, UP, DOWN, I was trying to make it more of an up, down, up, down.

A few weeks back I volunteered for an experiment to measure exactly this vertical impact (and also horizontal impact). The experiment setup was simple: I had (what I assume to have been) an accelerometer attached to my left ankle, and I ran on a treadmill for about 12 minutes. Each ~20 seconds the speed was increased by about 0.3mph.

There were about 5 other participants (all regular runners). The results of the experiment are plotted anonymously on the graph below (I am the magenta-ish dot).

I was glad to see that paying attention to body control seems to have paid off.

The next trick is to get outside and actually run more regularly.

()

1st August 2010

Why work harder than you should…

Thanks to netflix, I have a constant supply of streaming Office episodes. Lately I’ve been watching season 5. This includes the episode where Michael starts his own company, aptly named, “The Michael Scott Paper Company” (wikipedia episode link).

There’s a dialog in the episode wherein Michael’s replacement, Stringer Charles, asks Jim how he’s progressing on the “rundown” Charles asked him to do earlier in the day. The dialog is this:

Charles: You started on that rundown yet? [Looks at Jim’s screen.]
Jim: Oh, this is just something I’m taking a break with.
Charles: Oh.
Jim: I will get back to the rundown, uh, right now.
Charles: Okay, great.
Jim: Hey you know what? Do you have a rundown that I could take a look at, just so I know what type of rundown you’re looking for ?
Charles: Just keep it simple.
Jim: Keeping it simple -that’s what I’m doing. But I am working hard on this one. Real hard.
Charles: You’re working hard? On this?
Jim: No. Not too hard. Not harder than I should.
Charles: Right. I mean why work harder than you should.
Jim: No, I….

Charles’ final question is “why work harder than you should.” I was hoping for Jim to drop a bit of program management theory on Charles at this point, but you know, The Office not being an online PMP class, that didn’t happen.

Specifically, what I’m talking about is how Jim certainly should not have been working any harder than he needed to work on the rundown. This would have been an inefficient allocation of his limited resources (among which are energy and time). For example, imagine if Jim completed the rundown, and then spent 10 more minutes proof reading it a third time. Consider that Jim may have landed another client within these 10 minutes, the worth of which would have been tangibly greater than a perfectly proofread rundown.

This fundamental optimization is applicable when there is a limited resource and multiple potential allocations for that resource. As a quick read on the subject, I highlight the wikipedia entry on Pareto efficiency.

Also, it’s strange that Charles didn’t realize this himself. After all, he did take economic courses at Baltimore City Community College. Perhaps he was too caught up in worrying about branding his elastic product than thinking about global production management.

Tagged: theoffice thewire economics projectmanagement

()

1st August 2010

Tarring up iTunes Purchases

Found while cleaning out an old reference blog:

#!/usr/bin/python

import tarfile

itunes_dir = '/Users/<username>/Music/iTunes/iTunes Music'
tar_file_name = '%s/purchased.iTunes.20070714.tar' % itunes_dir
backup_file_name = '/tmp/purchasedFiles'

backup_files = open(backup_file_name, 'r')

tar = tarfile.open(tar_file_name, 'w')
for backup_file in backup_files:
  backup_file_name = '%s/%s' % (itunes_dir, backup_file)
  tar.add('%s/%s' % (itunes_dir,backup_file.strip()))
tar.close()

Tagged: dev

()