Using Binary Serialization


Time for some good news and bad news. First, the good news: both Java 2 Standard Edition (J2SE) v1.4 and Microsoft .NET Framework version 1.0 ship with a binary serializer that can convert any data type that's marked as serializable into a stream of bytes. The classes to perform this serialization are similar and relatively simple.

Now for the bad news: the formats that these binary serializers write are incompatible. This means that if I use the Java binary serializer to serialize an object to a file, the format of this file won't make any sense to the binary serializer that ships with the .NET Framework, and vice versa.

Running the Sample Code

To prove this, let's look at the first example of the book. After installing the samples from the companion CD, you'll find this example in the C:\Interoperability\Samples\Data\Binary\Serialization installation subdirectory. This directory contains three subdirectories: dotNET, Java, and Shared. The dotNET directory contains an example of serializing a CLR type by using C#, and the Java directory contains the equivalent for the Java platform. The Shared directory is an empty directory that output can be written to and read from.

Navigate to the dotNET directory first, and build the sample. (Refer to the "Running the Sample Code in This Book" section in Chapter 1, "Microsoft .NET and J2EE Fundamentals," for instructions on how to do this.) The sample contains three parts : Stock.dll, which contains the data type to be used; Writer.exe, which creates a new Stock object and serializes it to a file, and Reader.exe, which does the reverse.

To test the sample, run Writer, supplying the parameter of a file to write the serialized stream of bytes to:

 Writer ..\Shared\stock.bin 

If serialization is successful, the following message will be displayed:

 ..\Shared\stock.bin was created successfully. 

If you want, you can take a look at the stock.bin file in Microsoft Notepad or another text editor. You'll notice that the file contains a binary representation of a stock (that of course will be unreadable).

To deserialize this file, run Reader. Again, supply the parameter for the file that was written:

 Reader ..\Shared\stock.bin 

If deserialization was successful, the sample will display the data held in the stock:

 Stock Information: ------------------ Ticker:   FTHC Name:     Fourth Coffee Price:    3.02 Previous: 3.12 Volume:   25 

Now let's look at the same example in Java. The Java subdirectory has a similar setup. Once compiled, Stock.class contains the data type definition, Writer.class contains the method to serialize the object to a file, and Reader.class contains the code to deserialize the object. Running both the Java Writer and Reader examples, which can easily be done by executing ant reader and ant writer from the command prompt should yield similar results to those produced by the .NET sample code.

How the Sample Code Works

The sample code works relatively simply. First, the sample in .NET contains the definition for a stock based on our sample scenario:

 using System; namespace Binary {     [Serializable]     public class Stock     {         public String Ticker="";         public String Name="";         public double Price=0;         public double Previous=0;         public int Volume=0;     } } 

This type definition is relatively simple and is marked with the Serializable attribute. To create an object of this type and write it to a file, you use BinaryFormatter , which is part of the System.Runtime.Serialization.Formatters.Binary namespace. Combined with a FileStream , the binary formatter can serialize the object with the following code:

 IFormatter formatter = new BinaryFormatter(); Stream fs = new FileStream(binFile, FileMode.Create); formatter.Serialize(fs,FTHC); fs.Close(); 

The reader uses exactly the same approach, but in reverse. Here, the BinaryFormatter is still used, but the Deserialize method is called to convert the binary file into the required object:

 IFormatter formatter = new BinaryFormatter(); Stream fs = new FileStream(binFile, FileMode.Open); Stock incomingStock = (Stock)formatter.Deserialize(fs); fs.Close(); 

The Java sample works in a similar way, using standard Java classes. Again, a class is defined for the stock type that's marked as being serializable:

 public class Stock implements java.io.Serializable {     public String Ticker;     public String Name;     public double Price;     public double Previous;     public int Volume; } 

To write the object to a binary file, the java.io.ObjectOutputStream class is used. The writeObject method takes the object and outputs a stream, which is then written to a file:

 fs = new FileOutputStream(binFile); os = new ObjectOutputStream(fs); os.writeObject(FTHC); os.close(); 

For reading, you use a similar approach, but the corresponding class is named ObjectInputStream :

 fs = new FileInputStream(binFile); is = new ObjectInputStream(fs); incomingStock = (Stock)is.readObject(); is.close(); 

In this example, we have similar .NET and Java classes being used to serialize and deserialize an object into a binary format.

Breaking the Sample Code

The beginning of this section mentioned that the binary serializers in both the CLR and Java were not compatible. We can prove this by rerunning the sample code, except this time, we'll write and read the data type using code from the different platforms. (It's a little ironic that the first sample in a book covering interoperability is designed to not work, but it's a good test all the same.)

To run the code, return to the dotNET subdirectory in C:\Interoperability\Samples\Data\Binary\Serialization. Rerun the .Net writer sample, passing a location of a file within the Shared subdirectory:

 Writer ..\Shared\stock.bin 

Now navigate to the Java subdirectory and rerun the Java reader sample, using the same location of this file. Instead of the data type being deserialized, an exception is thrown:

 java.io.StreamCorruptedException: invalid stream header 

According to the Java deserializer, this is not a valid byte stream, and for this demonstration, it's correct. We can observe the same behavior if we switch the writer to Java and the reader to .NET. From the Java subdirectory, rerun the writer to overwrite the shared file. Once done, return to the dotNET directory and run Reader. The exception shown here is a SerializationException :

 System.Runtime.Serialization.SerializationException: BinaryFormatter Version incompatibility. Expected Version 1.0.  Received Version 1801678708.2084051481. 

Again, the .NET sample cannot interpret the stream of bytes that's been written by the Java serializer and cannot reconstruct the object.

Can Binary Serialization Ever Be Used for Interoperability?

In short, yes. The principles of serialization, however, state that the serialization and deserialization of any object must be performed with the same formatter. The format that takes the data type and creates a stream of bytes must match the format that takes the bytes and reconstructs the object.

Although the default binary serializers in the CLR and Java aren't compatible and wouldn't serve as a good example of interoperability, a number of ways to achieve this interoperability do exist. For instance, you can use a custom serializer that shares the same formatting options for both the CLR and Java. Alternatively, the binary formatter within the .NET Framework can be licensed, allowing third parties to create their own implementations . One good example of this is using binary serialization in conjunction with .NET Remoting, which we'll explore in some detail in Chapter 4, "Connectivity with .NET Remoting." In Chapter 4, we'll use a third-party product, Ja.NET from Intrinsyc, which relies on a version of the CLR binary serializer created for Java.




Microsoft. NET and J2EE Interoperability Toolkit
Microsoft .NET and J2EE Interoperability Toolkit (Pro-Developer)
ISBN: 0735619220
EAN: 2147483647
Year: 2003
Pages: 132
Authors: Simon Guest

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net