Recently in Java Category

I’ve been working on a Java servlet these days which for many reasons needs to determine the mime type of files so that files being rendered are correctly used by my clients. For example, I’m generating a crossdomian.xml, which if not matched with the text/xml content type, really confuses flash players.

Anyway, I fumbled around for a bit in Google and found one great solution: mime-util. It’s Apache License and works great. The documentation is even very good.

Since I can trust my file names I opted for the simple file name extension detection method. It’s a perfect fit except for one thing: I need to detect the application/json content type which is not part of the default property bundle.

It took me a few minutes of digging trough the JavaDocs to find the answer, so to save you some time, here’s my solution:

  1. Create a file named mime-types.properties and put it somewhere in your class path.
  2. Add the types you need as extension=type pairs like json=application/json
0 Votes

Basic Auth is a very simple way to secure your web application. When combined with a secure transport technology like SSL, it’s also good enough in most cases.

Here is a dirt simple example of how to access the basic authentication information from the HTTP header in your servlet.

protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    String pathInfo = request.getPathInfo();
    //will contain "Basic Ym9iOnNlY3JldA=="
    String header = request.getHeader("Authorization"); 
    //always wise to assert your assumptions
    assert header.substring(0, 6).equals("Basic "); 
    //will contain "Ym9iOnNlY3JldA=="
    String basicAuthEncoded = header.substring(6);
    //will contain "bob:secret"
    String basicAuthAsString = new String(
        new Base64().decode(basicAuthEncoded.getBytes()));
    ...
}

You can test it with this curl command:

$  curl -vv http://bob:secret@localhost:8090/blah
* About to connect() to localhost port 8090 (#0)
*   Trying ::1... connected
* Connected to localhost (::1) port 8090 (#0)
* Server auth using Basic with user 'bob'
 GET /blah HTTP/1.1
 Authorization: Basic Ym9iOnNlY3JldA==
 User-Agent: curl/7.19.4 (universal-apple-darwin10.0) libcurl/7.19.4 OpenSSL/0.9.8k zlib/1.2.3
 Host: localhost:8090
 Accept: */*
...
0 Votes

Java collections, like List and Map, are great. In fact they’re probably the most used part of the Java core APIs. They do lack one feature, though: easy to use conversion into a string representation. This is a surprisingly common task for error messages and logging. In neither of these cases is the default toString() sufficient.

Typical solutions include usage of a static utility class to convert them, iterating through them in your code, or creating a subclass of your own. None of these have ever made me happy, though. They’re either too verbose or clunky and the way I want to represent a collection as a string often varies considerably from one instantiation to another.

I had never thought about it before, but Java anonymous classes provide a great solution. You can simply specify a toString function when you create a collection by subclassing it anonymously.

Here’s a simple example. I have a class which contains a map. In logs and error messages I want to simply dump the keys.

public class MyClass {
  private Map map;

  public MyClass() {
      map = new HashMap<String, Stuff>() {
          public String toString() {
              String stringForm = new String();
              for(String key : this.keySet()) {
                  stringForm += key + ", ";
              }
              //remove the trailing ", "
              stringForm.substring(0, stringForm.length()-2);
              return stringForm;
          }
      };
  }
}

Later in my code I can simply run map.toString() to see a comma separated list of the keys in my map.

Of course, this pattern only helps when you need a flexible way to represent each collection as a String and when that collection is only created in one place. If you’re creating the collection in many methods a non-anonymous inner class may be a better fit.

0 Votes

Somehow I had survived in the Java wold until now without ever having the pleasure of writing an MBean. MBeans and JMX in general are really cool, but like those full coverage integration tests, they’re one of those things that often slips through the cracks until you have your first major production incident.

This time I’m trying to be good. I’m actually implementing the configuration harness that I’m using for all of my applications with a built in Standard MBean. This MBean provides easy JMX access to inspect and update configuration during runtime.

I followed this tutorial to get going. Note that it has no date (always date your technical blog entries!) It’s pretty good but I had to jump through a couple of hoops to get it working. Here is the story of those jumps.

A Singleton Can Not Be a Standard MBean

I didn’t see this mentioned anywhere, but it turns out to be true. Standard MBeans must have a public default constructor. If they do not, you’ll see this friendly stack trace:

java.lang.NullPointerException
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:303)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:482)
    at foo.bar.Configamajig.bootstrap(Configamajig.java:74)

Yeah, it took me awhile to figure that out.

Anyway, I solved the problem by creating a static class adapter for my singleton. The static adapter just proxied the methods of the singleton with a provided public default constructor. For this to be reliable I make sure that I bootstrap my singleton before I create the MBean (just in case it calls some of those methods).

MBean Concrete Class Naming Is Not Flexible

The example had an MBean interface HelloMBean with a concrete implementing class by the name Hello. As it turns out this was not just to make the tutorial easy to follow. It’s required for the MBean to work! This turned out really nice since my concrete class was an adapter (per the above step). As a result my MBean interface must contain the work ‘adapter’ to comply with this convention.

The guys who came up with this must have forgotten that convention over configuration implies that you can override the convention with configuration if you so desire.

Anyway, to help you Google searcher’s find this solution, here’s the stack trace:

javax.management.NotCompliantMBeanException: MBean class foo.bar.ConfigamajigMBeanImpl does not implement DynamicMBean, neither follows the Standard MBean conventions (javax.management.NotCompliantMBeanException: Class foo.bar.ConfigamajigMBeanImpl is not a JMX compliant Standard MBean) nor the MXBean conventions (javax.management.NotCompliantMBeanException: foo.bar.ConfigamajigMBeanImpl: Class foo.bar.ConfigamajigMBeanImpl is not a JMX compliant MXBean)
    at com.sun.jmx.mbeanserver.Introspector.checkCompliance(Introspector.java:160)
    at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:305)
    at com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:482)
    at foo.bar.Configamajig.bootstrap(Configer.java:75)
0 Votes

JavaDocs are great. They're the standard for api documentation, but as good as they are they have one big problem: all classes and all methods are created equal. This can be a problem especially in the quite verbose Java language. Sometimes one class or method is much better than another one. Sometimes you get overwhelmed by the options and have no idea where to even start looking.

Someone has come up with a solution and it's pretty good! It's called Jadeite and it was written four smart guys at CMU. They've even run it on the two common api docs already.

It introduces a few useful features.

  • It weights classes based on usage. java.lang.Date is huge, java.sql.Date is not as big. This is a huge help when dealing with two similar looking classes that have very critical differences.
  • Examples (only for constructors so far) that have been scavenged off of the Internet.
  • Users can annotate the documentation as they use it with placeholders. This is a combination wishlist / alternative finder.

It's a huge time saver already. The features have added the best part of php.net's comments without all the noise. If you're doing Java or Groovy development, go check it out.

0 Votes