Caching in Tomcat - SOLVED!

June 19th, 2007

It took forever, but I've finally how to stop Tomcat adding a Pragma: no-cache header to any resources in a secure context. You need to set disableProxyCaching to false, so if you're using basic authentication you need a valve like:

<Valve className="org.apache.catalina.authenticator.BasicAuthenticator"  disableProxyCaching="false" />

That needs to go within the <context> definition for your web-app. So, within the META-INF (some sources say within WEB-INF?) create a context.xml file like:

<Context><Valve className="org.apache.catalina.authenticator.BasicAuthenticator"  disableProxyCaching="false" /></Context>

I found deploying as a WAR didn't work (it seemed to ignore the context.xml), but deploying the exploded files did work and that's fine by me.

Combine that with the awesome cache control filter that Danny posted in the comments and you have a very nice, easily configurable caching mechanism that doesn't cause browsers to download the CSS and JavaScript resources for every single page.


Dear lazyweb,

Does anyone have best practices for implementing correct, useful caching for a webapp running in Tomcat? I'm using container managed security and it's happily adding Pragma: No-cache to everything, including the static CSS file which is pretty brain dead. It looks like I can add a custom filter to get rid of that header and then manage caching myself, but it seems like something that everyone should have solved before so I thought I'd ask….

Thanks,

Lazy me.

Wowsers! Sun’s Updating The Swing Text APIs

June 19th, 2007

Apparently Sun has finally decided to give some love to the Swing text APIs with the addition of a removeElement method. What the linked article fails to mention is that in the particular example given, you can remove the list item with a simple document.remove(e.getStartOffset(), e.getEndOffset() - e.getStartOffset());

When you get into trouble with the swing text apis is when there are two elements that start and end at the same point - ie: a list as the only child of a table cell:

<table>
  <tr>
    <td>
      <ul>
        <li>Remove me!</li>
      </ul>
    </td>
  </tr>
</table>

If you try the document.remove trick, the entire table will be deleted because the start and end offsets for the list item is the same as for the table (they contain the same text content). Unfortunately, the new removeElement method won't help with this because if you remove the last child element it also removes the parent element so document.removeElement(li) has the exact same effect as document.removeElement(table). The work around for that is of course to insert another element into the table cell first - most likely an empty p or p-implied element which you can do with insertBefore or insertAfter, but not if you want the table cell to be empty because you can't insert the required p-implied and line ending with insertBefore or insertAfter. Instead, you'd have to insert an empty p tag and then use document.setParagraphAttributes to convert it to a p-implied after the fact. That or insert some text and then delete it again (but keep the trailing newline that will be inserted automatically). Both those cases will make a mess of your undo buffer because they count as two changes instead of one.

No Signed Applets For Windows Safari

June 12th, 2007

It turns out the root cause of the problems I was seeing with Safari on Windows is that it simply doesn't support signed applets. That's pretty sad really. Apple seem to have implemented their own Java plugin instead of using the one that Sun provides (they're using the Sun JRE via their plugin) and of course it's missing most of the features you'd want from a Java plugin.

I'll report it to Apple officially just as soon as someone fixes the bug reporter - it's currently down. Perhaps there are too many people logging bugs against the new Safari and Leopard builds….

Safari Brings Horrible Debugging To Another Platform

June 12th, 2007

So Apple have released Safari for Windows - really no idea why, but they have. Sadly, just like on Mac it has terrible JavaScript and Java debugging support. In fact, it's worse on Windows than on Mac - anyone know how to turn the debug menu on? Anyone know how to get a Java console to appear?

I'd really, really like to make things work with it but all I can do at the moment is randomly guess at the source of problems.

UPDATE: You can open the JavaScript console with the keyboard shortcut control-shift-J. So JavaScript is now usable, but sadly Java still seems very broken and undebuggable.

The Benefits Of Open Sourcing Java For Developers

May 11th, 2007

There was an interesting panel discussion at JavaOne today about the open sourcing of Java. The panel was made up of folks developing open source JVMs and a representative from Sun. Compatibility is obviously a common theme to these discussions and there were a number of mentions to just how bug for bug compatible the alternative JVMs are trying to be. It occurs to me though that if all the implementations wind up behaving in precisely the same way, there's not really any point to having multiple implementations. Yes multiple licenses are nice for particular niches but for the average Java developer, what's the benefit?

A reporter came up to me after the session (apparently I'd made some good comments) and asked about what benefits I saw. Her first question was about how useful having the source code would be. The trouble is, the source code for the standard Java class library has been available for as long as I can remember and open sourcing Java doesn't change the legality of copying and pasting code (unless your product is GPL) so there's no real advantage in source access. There are a few sun.* classes that now have source code available and didn't previously which can be useful but not overly so.

The other advantage is that was mentioned by the panel is that you can fix bugs for clients *now* instead of having to wait for the next release of Java. Of course, for the average developer this isn't really an option either because it would involve deploying the fixed JVM to all their customers. It might be feasible for people running controlled servers that just run their apps but it's unlikely to be practical very often. You could however add a workaround to your application for now and contribute a fix back to the JDK for the future which is likely to happen a fair bit.

One interesting aspect of contributing fixes back is that in a lot of ways, there is an incentive for companies not to contribute the fix back - they now have one less bug than their competitors. If the fix requires significant maintenance contributing it back is a pretty clear win, but many work arounds don't have any real need for maintenance. They might be in areas of code that are very infrequently changed, they might be modular enough to be quite separate etc.  Ephox products have a lot of work around for bugs in various browsers, JREs and OSs, many of which receive so little attention and maintenance that we can be surprised to find them years later, still working perfectly and still working around an unfixed bug (we do report these to Sun, but few people run into them so they tend to be low priority). The other consideration is that even if future versions of the JRE include the fix, you still can't remove the work around because the older JVMs are still in use by various clients, so you pay the maintenance price anyway.

There are other business considerations involved with the decision to contribute to the JDK as well - you have to sign the copyright on the code over to Sun which can be a sticking point with a lot of companies. After all, why should Sun get to sell the code that you paid to have developed? (And Sun does still sell the code, they have a bunch of different licenses for the Java code including commercial ones, not just the GPL). You also have to go to the expense of reviewing the various legal agreements for contributors and going through the patch review process etc. It's not just a simple matter of putting the patch on your blog and it being magically part of the JDK.

It will be really important for the OpenJDK team to work hard to limit these barriers to contribution if they want to attract contributions. I'm certain it's something that they're already thinking about, but how it pans out with the lawyers will be interesting to see.

The other potential benefit that an open source JVM may provide is the ability to port it to other OSs and architectures. People are already suggesting that this will mean OS X will always have up to date Java just by recompiling. Unfortunately, it's just not that simple, you first have to port the JITC to output PPC code instead of x86 which is a huge job, then you have to rewrite the AWT toolkit implementation to work with Quartz. Then you have to write a plugin that works with OS X browsers and deal with all the Cocoa vs Java threading issues. Then you have a working JVM, but still no native L&F, no tie ins to the OS (Apple provide some reasonably simple but very powerful features like being able to put the menubar at the top of the screen and handle dropping files onto the application etc). It's good that it's possible to port, but it won't happen soon and it won't be easy. Judging by the number of Apple laptops here at JavaOne there may just be enough interest to get it done though. BSD is also a likely candidate for a porting project and that should be a lot simpler.

Beyond that, Java developers aren't going to see much difference except possibly that they have to stop making assumptions that if it works with Sun's JRE it will work anywhere. Of course, that's never been true anyway, particularly from a performance perspective, as people who have brought apps over to OS X have found out. It's a huge change for the Java community, but one that only a very, very small subset of the community is going to be affected by.