Friday, August 21, 2009

THC, and a bit of Thunking. (Creative ways to deal with multiple return types)

Often is the case that you really do want a method to return multiple values as different client require different parts back. This is often simpler than creating multiple methods; but it might not be worth creating a bean class for. For simple two value return types you can use a nice generic version of Pair; but things get harder if you have more value. (You can use a holder class to simulate IN/OUT parameters, but it doesn't result in pretty code) I was working on a method that needed to return four values depending on the calling context so I turned to a type safe heterogeneous container from the Effective java book:

/**
 * An implementation of a type safe heterogeneous container, taken from
 * effective java
 */
public class THC
{
   final private Map<Class<?>, Object> container = new HashMap<Class<?>, Object>();
   
   public <T> void put(Class<T> key, T value)
   {
      if (key==null) throw new NullPointerException("Key cannot be null");
      container.put(key, value);
   }
   
   
   public <T> T get(Class<T> key)
   {
      // Return the value of think the thunk if required
      //
      Object object = container.get(key);
      return key.cast(object);
   }
}

It doesn't provide full compile time safety; but it is close enough for our purposes. You can write code that looks like:


   THC thc = getSSLConfiguration(...);
   SSLContext sslContext = thc.get(SSLContext.class);
 
   // or in another case

   KeyManager kms[] = thc.get(KeyManager[].class);
   TrustManager tms[] = thc.get(TrustManager[].class);


So this is fine, except as you see from the example above that depending on the context I need different subset of the objects. Some are derived from others so I could end up doing extra work to populate a part of the return value that is never used.

I decided to look at using a Thunk as a way to optimize the work done on the return value of this method. So I modified the THC class to include a new public interface Thunk with one method that takes a reference to the original container.

/**
 * An implementation of a type safe heterogeneous container, taken from
 * effective java
 */
public class THC
{
   /**
    * Allow the client to provide a derived value
    * @param <T>
    */
   public interface Thunk<T>
   {
      public T get(THC that);
   }

   /**
    * Place a value in the structure that has yet to be derived.
    * @param key
    * @param value The value to be thought of in the future
    */
   public <T> void put(Class<T> key, Thunk<T> value)
   {
      if (key==null) throw new NullPointerException("Key cannot be null");
      container.put(key, value);
   }
   
   public <T> T get(Class<T> key)
   {
      // Return the value of thinking the thunk if required
      //
      Object object = container.get(key);
      if (object instanceof Thunk)
      {
         object = ((Thunk)object).get(this);
         container.put(key, object);
      }

      return key.cast(object);
   }

}

You find that because Thunk takes a parameter of the THC the adapter classes can be constants, this saves a little bit on object creation. So I can write something like:



  static final private Thunk<SSLContext> contextT = new Thunk<SSLContext>()
  {
     public SSLContext get(THC that)
     {
        SSLContext c = SSLContext.getInstance("SSL");
        c.init(that.get(KeyManager[].class)
               that.get(TrustManager[].class), null);
        return c;
     }
  }

  static final private Thunk<SSLSocketFactory> factoryT = new Thunk<SSLSocketFactory>()
  {
     public SSLSocketFactory get(THC that)
     {
        return that.get(SSLSocketFactory.class).getSSLSocketFactory();
     }
  }

  public THC getSSLConfiguration(...)
  {
     ...

     THC thc = new THC();
     thc.put(KeyManager[].class, kms);
     thc.put(TrustManager[].class, tms);
     thc.put(SSLContext.class, contextT);
     thc.put(SSLSocketFactory.class, factoryT);
  }

So I can now write my client code as follows and the SSLContext and SSLSocketFactory are created on demand:

   THC context = getSSLConfiguration(...);
   SSLSocketFactory sf = context.get(SSLSocketFactory.class);

Perhaps not a technique that is applicable to all situations; but interesting all the same.

Update: Some time later it occurred that the THC interface if of course not particularly pretty, so an obvious extension is to have THC return a Proxy based on a interface that can be used to define the return types. Not written this yet; but it would be pretty trivial to do.

Wednesday, August 19, 2009

Favourite minor JDeveloper feature, auto highlighting

Following on from Chris' post auto highlight is my favorite minor feature. Just highlights all instances of whatever the cursor is on. Has been available in previous version of jdev as an extension so not that much woo-hoo.

WssConfiguration and JAX-WS

In weblogic you can have multiple security configurations for web services but in 10.3 JAX-WS could only make use of the "default_wss" configuration. There was an annotation to control this; but it only worked for JAX-RPC service. But in 10.3.1, aka AS11R1, it now works for JAX-WS as well. And for completeness here is an example on a JAX-WS service.

Monday, August 10, 2009

Reminder edocs.bea.com -> OTN migration

Just a quick reminder that on the 31st of August edocs.bea.com will be turned off; but the good news is that all of the documentation has moved to the current bea page on document section on otn. Specifically Weblogic Server 10.3 and Weblogic Server 10.3.1 that is part of AS11R1. Guess we need to get used to a new page layout!

Tuesday, August 4, 2009

New default password for the integrated weblogic server in JDeveloper R1

I guess it must be hidden in the help somewhere but it is not 100% clear that the default password for the integrated copy of weblogic server that comes with JDeveloper changed for R1. Rather than weblogic/weblogic it is now weblogic/weblogic1. Not a big change but enough to cause problems for some users.

Monday, August 3, 2009

Problem running Jersey on the Integrated Server in JDeveloper on windows

Prior to the latest 1.1.2EA builds you will find that if you deploy Jersey to the integrated weblogic server in JDeveloper on window that you might see a deployment issue due to the fact that the weblogic domain will have a space in its filename. (Think c:\Document and Settings\%USER_NAME%\Application Data\)

This is logged as oracle bug 8752995, this is fixed in the latest builds but there is a workaround and that is to edit ..jdevevloper/jdev/bin/jdev.boot and change the following entry to a path without spaces in it.

ide.user.dir = D:/MyJdev/LocalSettings

Note without the NLS fix in the previous blog entry deployment will fail with a stack trace that looks like this:

com.sun.jersey.api.container.ContainerException: [failed to localize] no.root.res.in.res.cfg()
        at com.sun.jersey.server.impl.application.WebApplicationImpl.processRootResources(WebApplicationImpl.java:718)
        at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:590)
        at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:383)
        at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:377)
        at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:242)

Useful localization fix in Jersey Achive 1.1.2EA

There was a problem in the 1.1.X series of Jersey builds in that error messages were not localized properly. This has been fixed in the latest 1.1.2EA build so it is well worth downloading this very as it is much easier to diagnose failures.