tomcat 6 servletcontext problems with attributes

Tue, Jun 16, 2009

I got a report that the Guanxi IdP doesn’t work on Tomcat 6, so I went digging and it came down to this line in the AttributeAuthority:

EntityDescriptorType sp = (EntityDescriptorType)servletContext.getAttribute(
  request.getParameter(samlRequest.getAttributeQuery().getResource()));
It’s a bit of code that checks to see if the AttributeStatement needs to be signed. It works on Java 5 and Java 6 as well as Tomcat 5.x but it blows up with this exception on Tomcat 6:
java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:768)
…
at org.guanxi.idp.service.shibboleth.AttributeAuthority.
preHandle(AttributeAuthority.java:299)
So I downloaded the source for Tomcats 5 and 6 and compared the classes:
org.apache.catalina.core.ApplicationContext.java
but they both had the exact same code for getAttribute():
public Object getAttribute(String name) {
  synchronized (attributes) {
    return (attributes.get(name));
   }
}
The difference was in the definition of attributes. In Tomcat 5 it’s a simple HashMap:
protected HashMap attributes = new HashMap();
but in Tomcat 6, it’s completely different:
protected Map attributes = new ConcurrentHashMap();
The problem stemmed from the fact that there was a long trail of null which basically meant this was happening:
servletContext.getAttribute(null);
You can pass a null key to a HashMap as you can key a value against null but you can’t pass null to a ConcurrentHashMap as it will throw a NullPointerException if the key is null.

So I’ve sorted that and committed the change to HEAD. It’s interesting to think that object orientation has completely broken down here. Changing the implementation of a class should not break the clients of the class. Is the AttributeAuthority a client of the class? Of course it is. It uses it. It makes an assumption about the class works, which was correct until the implementation of the class was changed and the assumption was no longer valid. ServletContext::getAttribute makes no mention of null attribute names so technically the AttributeAuthority is well within its rights to pass it a null, especially as it works. Or it did until Tomcat 6 imposed an unnecessary condition on the interface.

comments powered by Disqus