We've begun localizing an application that uses BurlapProxyFactory to
transport objects between servers.  As part of this process, we've
added a java.util.Locale property to all of the objects.
Unfortunately, the Locale object has no no-arg constructor, and all
the other constructors throw NPE's when provided null arguments.  I
tried having the getter methods wrap the locale in an object that is
burlap friendly, but the Locale class has been marked final.

I've written LocaleSerializer and LocaleDeserializer classes based on
the SqlDateDeserializer that solve this problem.  They are included
along with a test at the bottom of this message.  Unfortunately, there
does not seem to be a way to augment the SerializerFactory used by the
BurlapOutput or BurlapInput objects in the proxy.  I recognize that
including serializers for all classes that are incompatible with
Hessian/Burlap is not feasible, but I would argue this is a special
case because:

1) The Locale class is in the java.util package, and could not be more standard.
2) Localization is a common development task, and - no matter what you
might think of it's implementation - the Locale object is the right
way to encapsulate localization information.
3) The fact that the Locale class is final makes it very difficult to
work around the absence of a custom serializer.

Regardless of whether LocaleSerializer is added to the default
SerializerFactory, it would be handy to be able to map additional
serializers when using the BurlapProxyFactory API.  It appears that
adding a serializerFactory property to the BurlapProxyFactory and
setting the property in the getBurlapInput() and getBurlapOutput()
methods would be all that is necessary to allow developers to
customize the serialization from proxy classes.

At any rate, I hope you will consider adding Locale serialization and
deserialization in the next release Hessian/Burlap release.

Thanks,
Alex Cruikshank
Carbon Five

................................
LocaleSerializer.....................................
package com.caucho.hessian.io;

import java.io.IOException;
import java.util.Date;
import java.util.Locale;

/**
 * Serializing a java.util.Locale object.
 */
public class LocaleSerializer extends AbstractSerializer
{
 public void writeObject(Object obj, AbstractHessianOutput out)
   throws IOException
 {
   if (obj == null)
     out.writeNull();
   else {
     Class cl = obj.getClass();

     int ref = out.writeObjectBegin(cl.getName());

     if (ref < 0) {
       out.writeString("language");
       out.writeString( ((Locale) obj).getLanguage() );
       out.writeString("country");
       out.writeString( ((Locale) obj).getCountry() );
       out.writeString("variant");
       out.writeString( ((Locale) obj).getVariant() );
       out.writeMapEnd();
     }
     else {
       if (ref == 0)
       {
         out.writeInt(3);
         out.writeString("language");
         out.writeString("country");
         out.writeString("variant");
       }
       out.writeString( ((Locale) obj).getLanguage() );
       out.writeString( ((Locale) obj).getCountry() );
       out.writeString( ((Locale) obj).getVariant() );
     }
   }
 }
}


................................ LocaleDeserializer
.....................................
package com.caucho.hessian.io;

import java.io.IOException;
import java.util.Locale;

/**
 * Deserializing a string valued Locale object
 */
public class LocaleDeserializer extends AbstractDeserializer {

 public LocaleDeserializer()
 {
 }

 public Class getType()
 {
   return Locale.class;
 }

 public Object readMap(AbstractHessianInput in)
   throws IOException
 {
   String language = null;
   String country = null;
   String variant = null;

   while (! in.isEnd()) {
     String key = in.readString();

     if (key.equals("language"))
       language = in.readString();
     else if (key.equals("country"))
       country = in.readString();
     else if (key.equals("variant"))
       variant = in.readString();
     else
             in.readString();
   }

   in.readMapEnd();

   return create(language,country,variant);
 }

 public Object readObject(AbstractHessianInput in, String []fieldNames)
   throws IOException
 {
   String language = null;
   String country = null;
   String variant = null;

   for (int i = 0; i < fieldNames.length; i++) {
     String key = fieldNames[i];

     if (key.equals("language"))
       language = in.readString();
     else if (key.equals("country"))
       country = in.readString();
     else if (key.equals("variant"))
       variant = in.readString();
     else
             in.readObject();
   }

   return create(language,country,variant);
 }

 private Object create( String language, String country, String variant )
   throws IOException
 {
   if (language == null)
     throw new IOException("Locale expects language.");

   try {
     return new Locale(language, country, variant);
   } catch (Exception e) {
     throw new IOExceptionWrapper(e);
   }
 }
}

................................ LocaleSeserializerTest
.....................................
package com.caucho.hessian.io;

import com.caucho.burlap.io.*;

import java.io.*;
import java.util.*;

import junit.framework.TestCase;

public class LocaleSerializerTest extends TestCase
{
 public void testLocaleInBurlap() throws Exception
 {
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   BurlapOutput out = new BurlapOutput(baos);
   out.writeObject(new Locale("en"));
   out.writeObject(new Locale("en","US"));
   out.writeObject(new Locale("en","US","drawl"));

   ByteArrayInputStream bain = new ByteArrayInputStream(baos.toByteArray());
   BurlapInput in = new BurlapInput(bain);

   assertEquals( Locale.ENGLISH, in.readObject() );
   assertEquals( Locale.US, in.readObject() );
   assertEquals( new Locale("en","US","drawl"), in.readObject() );
 }

 public void testLocaleInHessian() throws Exception
 {
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   HessianOutput out = new HessianOutput(baos);
   out.writeObject(new Locale("en"));
   out.writeObject(new Locale("en","US"));
   out.writeObject(new Locale("en","US","drawl"));

   ByteArrayInputStream bain = new ByteArrayInputStream(baos.toByteArray());
   HessianInput in = new HessianInput(bain);

   assertEquals( Locale.ENGLISH, in.readObject() );
   assertEquals( Locale.US, in.readObject() );
   assertEquals( new Locale("en","US","drawl"), in.readObject() );
 }

 public void testLocaleInHessian2() throws Exception
 {
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   Hessian2Output out = new Hessian2Output(baos);
   out.writeObject(new Locale("en"));
   out.writeObject(new Locale("en","US"));
   out.writeObject(new Locale("en","US","drawl"));
   out.flush();

   ByteArrayInputStream bain = new ByteArrayInputStream(baos.toByteArray());
   Hessian2Input in = new Hessian2Input(bain);

   assertEquals( Locale.ENGLISH, in.readObject() );
   assertEquals( Locale.US, in.readObject() );
   assertEquals( new Locale("en","US","drawl"), in.readObject() );
 }
}


_______________________________________________
hessian-interest mailing list
[email protected]
http://maillist.caucho.com/mailman/listinfo/hessian-interest

Reply via email to