Aug 10 04

So much information on Spring OpenID is outdated so quickly…Lots of articles and blog entries describe solutions with Spring Security 2.x which is slightly different from 3.x.

I recommend sticking with the sample application at http://repo1.maven.org/maven2/org/springframework/security/spring-security-samples-openid/<your_version>/spring-security-samples-openid-<your_version>.war as a reference. Also, I found http://www.packtpub.com/article/opening-up-to-openid-with-spring-security quite helpful.

One caveat though is worth mentioning here: the Spring sample application does not work with Google and Yahoo OpenID (and probably many more). The reason is explained in the above article, just scroll down to “The OpenID user registration problem”.

For my sample application I didn’t implement registration just yet. So, when I used Google’s generic OpenID URL https://www.google.com/accounts/o8/id for the input field in openidlogin.jsp I was able to authenticate against my Google account but Spring complained as none of the user names listed in applicationContext-security.xml matched what Google returned. Quick-fix: check your application’s log file for “Verification succeeded for: https://www.google.com/acc”….That URL is the effective user name you should paste to applicationContext-security.xml.

May 10 11

When you start the Dalvik Debug Monitor Server (DDMS) in your Android development environment you might notice its mysterious logo:

I asked my myself: where the heck is this place? What’s the story behind that? My first guess was northern Scandinavia. Turns out I wasn’t quite right but not very wrong either.

I compared it with various coastlines on Google Maps and found a matching spot in northern Iceland. I zoomed closer and bingo! in the center of the logo is a town called Dalvik. Now it all makes sense. There’s even a few words about the link between the town Dalvik and Android on Wikipedia.

May 10 10

If you use ServletFilters that are mapped to URLs/resources that don’t physically exist (e.g. such as Paul Tuckey’s UrlRewriteFilter) IBM WebSphere 6.1 will answer such requests with “Error 404: SRVE0190E”. If WebSphere runs in trace mode you’ll see a FileNotFoundException in the log file.

This is yet another idiotic WebSphere behavior that you need to work around. Set

com.ibm.ws.webcontainer.invokefilterscompatibility=true

in Servers -> Server -> Web Container Settings -> Web Container -> Custom Properties.

IBM has more information in their custom properties documentation (search for “Invoking the filter capability”) and on the respective support document (for fix pack 6.1.07). Since the URLs to those documents might become invalid in the future I persisted the latter in a PDF.

Apr 10 20

Java allows to use a custom VM-wide SSLSocketFactory implementation like so: HttpsURLConnection.setDefaultSSLSocketFactory(SSLSocketFactory). Thus, you can either implement your own SSLSocketFactory or you can configure a regular instance according to your needs/environment. You have to understand that there a probably very few use cases where this method actually really helps. Setting a static default SSLSocketFactory influences all components that require a SSL connection of some sort. The same socket factory instance will be used!

Apache CXF has long had very good SSL support built right in. The documentation is pretty clear about how configure the SSL connection(s). Up to version 2.2.7, however, CXF ignored any custom SSLSocketFactory set as described above. CXF’s HttpsURLConnectionFactory.decorateWithTLS(HttpURLConnection) simply wasn’t prepared for that.

CXF now 2.2.7 supports this through a simple configuration parameter. The feature proposal in the CXF JIRA describes the change: https://issues.apache.org/jira/browse/CXF-2693. I only had to add a few lines to the Spring application context:

  <http-conf:conduit name="*.http-conduit">
    <http-conf:tlsClientParameters useHttpsURLConnectionDefaultSslSocketFactory="true" />
  </http-conf:conduit>
  <!--
    Due to a XML parsing issue mentioned here http://www.mail-archive.com/users@cxf.apache.org/msg13711.html it's
    necessary to import the CXF XMLs explicitly.
  -->
  <import resource="classpath:META-INF/cxf/cxf.xml" />
  <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
  <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
Apr 10 16

WTFs/m

Apr 10 05

When you need to support self-signed SSL certificates in your Apache HttpClient based application you can use the contributed EasySSLProtocolSocketFactory as described in the HttpClient docs.

Instead of using HttpClient’s HostConfiguration object directly you’d modify its protocol socket factory in your code like so:

...
if (config.isAllowSelfSignedCertificates()) {
  ProtocolSocketFactory factory = new EasySSLProtocolSocketFactory();
  try {
    URI uri = new URI(config.getBaseUrl());
    int port = uri.getPort();
    if (port == -1) {
      port = 443;
    }
    Protocol easyHttps = new Protocol(uri.getScheme(), factory, port);
    hostConfiguration.setHost(uri.getHost(), port, easyHttps);
  } catch (URISyntaxException e) {
    throw new IOException("could not parse URI " + config.getBaseUrl(), e);
  }
}
...

Somewhere you’d instantiate a HttpClient object. Then you get its host config through HttpClient#getHostConfiguration() – I stored this in the hostConfiguration variable. The if, the config variable, checking for port, etc. is all my own code and has nothing to do with HttpClient directly.

There is one caveat, though! Never use absolute URIs against the HttpClient 3.x with the EasySSLProtocolSocketFactory in place! If you did you’d get the dreaded

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I found that the HttpClient 3.x has the following code in its executeMethod() method:

...
if (hostconfig == defaulthostconfig || uri.isAbsoluteURI()) {
  // make a deep copy of the host defaults
  hostconfig = (HostConfiguration) hostconfig.clone();
  if (uri.isAbsoluteURI()) {
      hostconfig.setHost(uri);
  }
}
...

So, in my case (absolute URI) the modified host config (uses EasySSLProtocolSocketFactory) is cloned.

Problem: since the so called “deep copy” isn’t a proper deep copy the copy’s protocol’s socket factory is no longer EasySSLProtocolSocketFactory but the standard SSLProtocolSocketFactory instead!

Update

Apparently, this behavior is “well known and documented”. Since I couldn’t find anything in the HttpClient 3.x documentation I tried Google again and made note of the following JIRA issues and one particular mailing list entry:

Please note that HttpClient 4.x does not have this limitation!

Feb 10 09

In a recent stackoverflow.com question I asked for input on how to implemented animated GIFs in SWT table/tree viewer cells. Below is some code of the final solution.

Animation thread

The animation thread can be asked for the “current frame index” (CFI) by interested parties. The CFI thusly denotes the frame of an animated GIF which should be rendered. LabelProviders are the interested parties in this context because they actually render the images.

The thread increments the CFI in its run method. Also, Display#asyncExec is triggered in the run method. During the async execution the table/tree is ask to redraw and update – see lines 69ff.

/**
 * This animation thread doesn't actually animate anything itself. However, it acts as a pace maker
 * for other components that are able to render animated images. In a loop this thread marks
 * designated columns of a tree viewer (see constructor) for redrawing and calls
 * update() on the tree itself. Label providers on the other hand ask this thread for
 * the current frame index whenever they're triggered provide an image for the designated column.
 *
 * The viewer's content provider is ideally suited to control the life cycle of this thread. It can
 * create/destroy a thread instance whenever the viewer's content is updated.
 *
 */
public class BuildColorAnimationThread extends Thread {

  private final TreeViewer viewer;
  private final int animationColumnIndex;
  private final ImageLoader sampleImage;
  private int currentFrameIndex;
  private boolean cancel;
  private static BuildColorAnimationThread runningInstance;

  /**
   * C'tor which sets this instance to be the one running instance.
   *
   * @param viewer the viewer whose content should be animated
   * @param animationColumnIndex the index of the column to be animated
   * @param sampleImage a sample image which resembles the animation images in the viewer, the
   *        thread uses it to extract repeat-counts and frame delays
   * @see BuildColorAnimationThread#getRunningInstance()
   */
  public BuildColorAnimationThread(final TreeViewer viewer, final int animationColumnIndex,
      final ImageLoader sampleImage) {
    this.viewer = viewer;
    this.animationColumnIndex = animationColumnIndex;
    this.sampleImage = sampleImage;
    this.currentFrameIndex = 0;
    BuildColorAnimationThread.setRunningInstance(this);
  }

  /**
   * Returns the running instance of the animation thread or null if there's none.
   *
   * @return the running instance of the animation thread or null if there's none
   */
  public static BuildColorAnimationThread getRunningInstance() {
    return runningInstance;
  }

  private static void setRunningInstance(BuildColorAnimationThread runningInstance) {
    BuildColorAnimationThread.runningInstance = runningInstance;
  }

  @Override
  public void run() {
    int repeatCount = this.sampleImage.repeatCount;
    /*
     * The repeat count takes into consideration that an animated image might not be animated
     * infinitely but only for a given number of loops.
     */
    while (!this.cancel && !this.viewer.getTree().isDisposed()
        && (this.sampleImage.repeatCount == 0 || repeatCount > 0)) {
      this.viewer.getTree().getDisplay().asyncExec(new Runnable() {

        public void run() {
          final BuildColorAnimationThread thread = BuildColorAnimationThread.this;
          final Tree tree = thread.viewer.getTree();
          if (!tree.isDisposed()) {
            final Rectangle clientArea = tree.getClientArea();
            // Marks ONLY the animation column to be redrawn and not the entire table!
            tree.redraw(clientArea.x, clientArea.y, tree.getColumn(thread.animationColumnIndex)
                .getWidth(), clientArea.height, false);
            tree.update();
            // During the first loop currentFrameIndex=0...then currentFrameIndex=1,etc.
            thread.currentFrameIndex =
                (thread.currentFrameIndex + 1) % thread.sampleImage.data.length;
          }
        }
      });

      try {
        int ms = this.sampleImage.data[this.currentFrameIndex].delayTime * 10;
        if (ms < 20) {
          ms += 30;
        }
        if (ms < 30) {
          ms += 10;
        }
        Thread.sleep(ms);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
      }
      /*
       * If the last frame was signaled as being the current frame, decrement the repeat count and
       * start again.
       */
      if (this.currentFrameIndex == this.sampleImage.data.length - 1) {
        repeatCount--;
      }
    }
  }

  /**
   * Returns the index of the current frame. Animation providers (i.e. renderers) call this method
   * in order to find out which frame of an animated image they should render at any given point in
   * time.
   *
   * @return frame index starting at 0
   */
  public int getCurrentFrameIndex() {
    return this.currentFrameIndex;
  }

  /**
   * Signals the thread to stop. It will finish the current execution in its run method and will
   * then stop.
   */
  public void cancel() {
    this.cancel = true;
  }
}

LabelProvider

I use my own implementation of an OwnerDrawLableProvider which paints a static image if the icon doesn’t have to be animated. If it needs to be animated (based on some attribute of the row’s input) it paints the frame of an animated GIF. The index of the frame to draw is determined by the animation thread shown above. Hint: the getImage() method is called by paint().

  /*
   * For each (animated) job color the provider keeps a map of frame_index-to-image entries. This
   * speeds up the process of delivering images for rendering because they don't have to be created
   * all the time from ImageData objects.
   */
  private final Map> imagesMap =
      new HashMap>();

  @Override
  protected Image getImage(Event event, Object element) {
    final IJob job = (IJob) element;
    Image image = BuildColorInfo.getIconImage(job.getColor());
    if (job.isRunning()) {
      final BuildColorAnimationThread animationThread =
          BuildColorAnimationThread.getRunningInstance();
      /*
       * Should no animation thread be running, the static image fetched a few lines above will be
       * returned.
       */
      if (animationThread != null) {
        final int currentFrameIndex = animationThread.getCurrentFrameIndex();
        Map images = this.imagesMap.get(job.getColor());
        if (images == null) {
          images = new HashMap();
          this.imagesMap.put(job.getColor(), images);
        }
        image = images.get(Integer.valueOf(currentFrameIndex));
        if (image == null) {
          image = createNewImage(event, job.getColor(), currentFrameIndex);
          images.put(Integer.valueOf(currentFrameIndex), image);
        }
      }
    }
    return image;
  }

  private Image createNewImage(Event event, JobColor color, int currentFrameIndex) {
    final ImageLoader imageLoader = BuildColorInfo.getImageLoader(color);
    return new Image(event.gc.getDevice(), imageLoader.data[currentFrameIndex]);
  }

“Controller”

The controller is responsible to start/stop the animation thread. Basically, whenever the viewer’s input changes the running animation thread must be canceled and a new thread must be started. The best hook for that is the viewer’s content provider – an implementation of I<Tree|Table>ContentProvider as it declares an inputChanged() method.

    @Override
    public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
      if (this.animationThread != null) {
        this.animationThread.cancel();
      }
      // Animates the first column.
      this.animationThread =
          new BuildColorAnimationThread((TreeViewer) viewer, 0, BuildColorInfo
              .getImageLoader(JobColor.BLUE_ANIME));
      this.animationThread.start();
    }

The code presented here was implemented for H2Eclipse, the Hudson plugin for Eclipse.

Feb 10 08

Use the JavaScript console in Firebug and run the following script snippet:

var xmlhttp = new XMLHttpRequest();
xmlhttp.open("HEAD", "the_url",true); // Async HEAD request (relative path to avoid cross-domain restrictions)
xmlhttp.onreadystatechange=function() {
  if (xmlhttp.readyState==4) { // make sure the request is complete
    alert(xmlhttp.getAllResponseHeaders()) // display the headers
  }
}
xmlhttp.send(null); // send request
Jan 10 28

cache-control, pragma, no-cache, expires header, and tons more. I learned a lot from the below referenced articles.

Caching tutorial for web authors: http://www.mnot.net/cache_docs/

jGuru forum question: http://www.jguru.com/faq/view.jsp?EID=377

Jan 10 18

This is a follow-up for the Beware of WebSphere admins post just below.

My first immediate conclusion after the described deployment problems was to ban the use of the jsession cookie  in future applications. If the application always includes the jsessionid parameter in URLs there’s nothing that can go wrong during deployment in terms of cookie paths.

Contemplating a second longer made it obvious that maybe this wouldn’t be such a wise decision after all. There are number of developers who try to enforce the exact opposite because the jsessionid URL parameter can be considered harmful. I highly recommend reading the following two blog posts that support this thesis:

http://randomcoder.com/articles/jsessionid-considered-harmful
http://boncey.org/2007_1_8_purging_jsessionid