PSE/PSE Pro for Java API User Guide
This chapter provides information about concurrency, version numbers, and Java-supplied persistence-capable classes.
This chapter discusses the following topics:
You can use the osjversion utility to display the version number and the build date for the version of PSE/PSE Pro you are running. This command is in the bin subdirectory of the installation directory. You must include bin in your path to run osjversion. For example:
% osjversion
ObjectStore PSE for Java Release 1.1, 97-04-19 12:22:16 on buildhost
%
This command is useful when you want to ensure that you have the right version in your path.
You can also run the unzip -z command against any PSE/PSE Pro .zip file. Doing so allows you to see what version of PSE/PSE Pro the zip file contains. For example:
% unzip -z pro.zip
Archive: pro.zip ObjectStore PSE Pro for Java Release 1.1, 97-04-19 12:22:16 on buildhost,
Copyright 1996, 1997 Object Design, Inc. All rights reserved.
%
The osjversion utility checks what is available through the PATH environment variable. To check what is available through the CLASSPATH variable, you can write a program like the following.
import COM.odi.ObjectStore;
class OSVersion {
public static void main (String[] args) {
ObjectStore.initialize(null,null);
System.out.println(ObjectStore.releaseName());
}
}
Which Java-Supplied Classes Are Persistence-Capable?
Some Java-supplied classes are persistence-capable and others are not and cannot be made persistence-capable.
The following Java classes are persistence-capable:
Identity
PSE/PSE Pro does not preserve identity for objects that are instances of the Java wrapper classes. It is more efficient to store these objects as values rather than as objects. Because identity is not preserved, programs that use object identity to compare wrapper class objects, while perhaps not good programming style, work differently when used with persistent objects. For example, this method is incorrect:
boolean comparePersistIntegers(Integer x, Integer y) {
return (x == y);
}
Instead, it should be written as
boolean comparePersistIntegers(Integer x, Integer y) {
return x.equals(y);
}
Unicode strings
PSE/PSE Pro stores Unicode strings. You can specify any Java string with Unicode characters in it and PSE/PSE Pro can store it persistently and retrieve it correctly. PSE/PSE Pro uses UTF8 encoding/compression to store regular English strings compactly. Sun's Java implementation uses the same mechanism.
There are many Java system classes that cannot be persistence-capable.
Classes that use native methods cannot be made persistence-capable by the postprocessor because the postprocessor cannot annotate the native methods the way it can annotate Java code.
Other system classes do not make sense as persistent objects because they hold state that is inherently tied to the process, like open file channels or Java threads.
For other classes, like java.lang.Stringbuffer, the above obstacles might not apply. If you postprocess the .class file for java.lang.StringBuffer and specify the -modifyjava option, the postprocessor produces a persistence-capable StringBuffer class.
osjcfp -dest \osjcfpout -modifyjava java.lang.StringBuffer
Then you must put the new .class file in your CLASSPATH variable ahead of the standard Java .class file. All subsequent use of the StringBuffer class in this environment would use the persistence-capable version.
There are, however, some drawbacks to doing this. There will be some slowdown of some or all the methods, because the postprocessor must add new instructions to check whether the object needs to be brought in from the database or needs to be marked as modified.
How much slowdown is hard to determine. It depends on the details of the method. Even parts of your program that never handle persistence are affected by these extra instructions. This also applies to indirect uses of the class, for example, if StringBuffer is used heavily in some Java library that you are using, such as a user interface or network library.
There can also be problems with Java library version skew. If you postprocess java.lang.StringBuffer from version 1.0.2 of the Java Virtual Machine, and then your user uses your program with version 1.1, and StringBuffer has changed in some way between 1.0.2 and 1.1, your user will see the 1.0.2 version (persistence-capable) everywhere in the entire Java environment. If your user was depending, directly or indirectly, on the new 1.0.3 version of StringBuffer, something might not work properly.
You might need to rename the newly created persistence-capable version so that the non-persistence-capable version is still available to the other Java system classes.
This avoids the problem and is generally safer. However, you might need the persistence-capable class to have the original class name. For example, suppose you have a library that has a method that takes an argument of type java.lang.Stringbuffer. You want to pass in a persistence-capable object. You cannot rename the class because the argument type would not match.
PSE/PSE Pro itself uses java.util.Hashtable. Consequently, invoking Java or using PSE/PSE Pro with a persistence-capable version of java.util.Hashtable that is available in your CLASSPATH is likely to cause trouble, such as infinite loops. A better approach is to substitute the PSE/PSE Pro-supplied class COM.odi.util.OSHashtable.
You can serialize many classes that extend COM.odi.Persistent. Although COM.odi.Persistent does not implement java.io.Serializable, its no-argument constructor has been made public and all of its fields are transient.
PSE/PSE Pro uses this constructor to deserialize instances of a persistence-capable class that you define. For this to work, the definition of your persistence-capable class must implement the java.io.Serializable interface. The Persistent class does not implement the Serializable interface because doing so would be incompatible with earlier versions of the JDK. COM.odi.Persistent will implement java.io.Serializable in a future release.
During serialization, none of the transient fields in the Persistent class need to be written out. During deserialization, PSE/PSE Pro uses the no-arguments constructor to correctly initialize these transient fields.
Before serializing an object, an application must always invoke Persistent.deepFetch() on the object to be serialized. The deepFetch() method ensures that the contents of all components of the object are accessible. This must be the case for an application to serialize an object.
When an application serializes and deserializes a persistent object with the default serialization methods, PSE/PSE Pro effectively creates a transient copy of the object and its components. Here is code that provides an example of serializing and deserializing persistent objects. In this example, list2 is a transient copy of the persistent list.
public
class SerializationExample {
public static void main(String argv[])
throws java.lang.ClassNotFoundException, java.io.IOException,
java.io.FileNotFoundException {
String dbName = argv[0];
ObjectStore.initialize(null, null);
Database db = Database.create(dbname,
ObjectStore.ALL_READ | ObjectStore.ALL_WRITE);
/* Create a database with a list in it. */
Transaction tr = Transaction.begin(ObjectStore.UPDATE);
List curr = new List("1", null);
db.createRoot("list", curr);
for (int i=2; i < 5; i++) {
curr.next = new List(""+i, null);
curr = curr.next;
}
tr.commit();
/* Illustrate use of serialization in this example. */
tr = Transaction.begin(ObjectStore.UPDATE);
List head = (List)db.getRoot("list");
/* fetch the entire list prior to serializing it. */
Persistent.deepFetch(head);
FileOutputStream f = new FileOutputStream("tmp");
new ObjectOutputStream(f); -> new ObjectOutputStream(f);
os.writeObject(head);
FileInputStream in = new FileInputStream("tmp");
ObjectInputStream is = new ObjectInputStream(in);
/* list2 is effectively a copy of the list denoted by head. */
List list2 = (List)is.readObject();
...
}
tr.commit();
}
}
public class List implements java.io.Serializable {
public Object value;
public List next;
List(Object value, List next) {
this.value = value;
this.next = next;
}
...
}
[previous] [next]
doc@odi.com
Copyright © 1997 Object Design, Inc. All rights
reserved.
Updated: 05/13/97 12:18:48