... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)


ALDSP 2.1 vs QName

I tried the same trick that we used for ALDSP 2.0 -- placing a compatible version of javax.namespace.QName in the lib/endorsed directory of the JVM being used by WebLogic 8.1.  That change permitted a standalone Java 1.5 client to execute correctly.  However, running the same code in a servlet hosted by WebLogic 9.1 generated this exception:

<Apr 12, 2006 10:55:21 AM MDT>
<[weblogic.servlet.internal.WebAppServletContext@bc7c0 - name: 'aldsp-servlet.war', context-path: '/aldsp-servlet']
Root cause of ServletException.
com.bea.dsp.dsmediator.client.exception.SDOMediatorException: java.rmi.UnmarshalException: failed to unmarshal interface com.bea.ld.QueryResult; nested exception is:
java.lang.ClassNotFoundException: Failed to load class com.bea.ld.server.QueryResultImpl
at com.bea.dsp.dsmediator.client.XmlDataServiceBase.invokeFunction(XmlDataServiceBase.java:322)
at dstest.mmsandbox.BestPractice1.findItemsWithNameContaining(BestPractice1.java:84)
at mm.AldspServlet.accessAldsp(AldspServlet.java:52)
at mm.AldspServlet.doGet(AldspServlet.java:34)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:743)
Truncated. see log file for complete stacktrace
java.rmi.UnmarshalException: failed to unmarshal interface com.bea.ld.QueryResult; nested exception is:
java.lang.ClassNotFoundException: Failed to load class com.bea.ld.server.QueryResultImpl
at weblogic.rjvm.ResponseImpl.unmarshalReturn(ResponseImpl.java:201)
at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:315)
at weblogic.rmi.cluster.ClusterableRemoteRef.invoke(ClusterableRemoteRef.java:250)
at com.bea.ld.Server_ydm4ie_EOImpl_815_WLStub.executeFunction(Unknown Source)
at com.bea.dsp.dsmediator.client.XmlDataServiceBase.invokeFunction(XmlDataServiceBase.java:312)
Truncated. see log file for complete stacktrace
java.lang.ClassNotFoundException: Failed to load class com.bea.ld.server.QueryResultImpl
at weblogic.rmi.utils.WLRMIClassLoaderDelegate.loadClass(WLRMIClassLoaderDelegate.java:203)
at weblogic.rmi.utils.WLRMIClassLoaderDelegate.loadClass(WLRMIClassLoaderDelegate.java:128)
at weblogic.rmi.utils.Utilities.loadClass(Utilities.java:308)
at weblogic.rmi.utils.Utilities.loadClass(Utilities.java:344)
at weblogic.rjvm.MsgAbbrevInputStream.resolveClass(MsgAbbrevInputStream.java:395)
Truncated. see log file for complete stacktrace


ALDSP 2.1 vs QName

Ironically, I can get Tomcat to run the test ALDSP servlet.  The only wrinkle is that I cannot place weblogic.jar in the WAR because it contains servlet API classes and Tomcat will not load such JARs in conformance with the servlet specification.  The workaround is to put weblogic.jar in Tomcat's shared/lib directory.


ALDSP 2.1 vs QName

We had a test suite that exercised some ALDSP data services.  The suite had been ported to run successfully on ALDSP 2.1, under JVM 1.4.  But when we tried to run the suite under JVM 1.5, all the tests failed with an EOFException on the client side.  The server side reported a class serialization version incompatibility on QName.  Again.  This was supposed to be fixed under ALDSP 2.1.  Apparently not.

Actually, the release notes for ALDSP 2.1 do not specifically mention that Java 1.5 is supported, but they do say that WLS 9.x are now certified as ALDSP clients.  WLS 9.x demands Java 1.5.  I tried writing a servlet to test whether that WLS 9.x can now be used as clients -- no go.  Same exception:

<Apr 11, 2006 5:22:31 PM MDT> <Error> <RJVM> <BEA-000503> <Incoming message header or abbreviation processing failed
java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionUID = 4418622981026545151, local class serialVersionUID = -9120448754896609940
java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionUID = 4418622981026545151, local class serialVersionUID = -9120448754896609940
        at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:463)
        at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1521)
        at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1435)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1264)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
        at weblogic.rjvm.ClassTableEntry.readExternal(ClassTableEntry.java:33)
        at java.io.ObjectInputStream.readExternalData(ObjectInputStream.java:1686)
        at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1644)
        at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
        at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
        at weblogic.rjvm.InboundMsgAbbrev.readObject(InboundMsgAbbrev.java:65)
        at weblogic.rjvm.InboundMsgAbbrev.read(InboundMsgAbbrev.java:37)
        at weblogic.rjvm.MsgAbbrevJVMConnection.readMsgAbbrevs(MsgAbbrevJVMConnection.java:212)
        at weblogic.rjvm.MsgAbbrevInputStream.readMessageContext(MsgAbbrevInputStream.java:237)
        at weblogic.rjvm.ConnectionManager.dispatch(ConnectionManager.java:744)
        at weblogic.rjvm.t3.T3JVMConnection.dispatch(T3JVMConnection.java:782)
        at weblogic.socket.NTSocketMuxer.processSockets(NTSocketMuxer.java:105)
        at weblogic.socket.SocketReaderRequest.execute(SocketReaderRequest.java:32)
        at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224)
        at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183)



Headless Eclipse Ant Builds

If you want to run an Ant build within the Eclipse environment, you can launch Eclipse headless as follows:

@echo off

set JAVA="c:\esidev\jdk1.5.0_06\bin\java.exe"
set ECLIPSE="c:\esidev\eclipse3.1.x\startup.jar"
set WORKSPACE="c:\work\workspace"
set BUILDFILE="%WORKSPACE%\esi.environment utilities\rebuild-all.ant.xml"

@echo on
%JAVA% ^
  -cp %ECLIPSE% ^
  org.eclipse.core.launcher.Main ^
  -application org.eclipse.ant.core.antRunner ^
  -data %WORKSPACE% ^
  -buildfile %BUILDFILE% ^

This can come in handy if the Ant script uses some of the Eclipse tasks or if the build relies upon Eclipse's built-in build processes.


Eclipse TreeViewer Selections

Using Eclipse RCP, I noticed that whenever I refreshed a TreeViewer the selection was lost.  Reading the code, I found out that RCP was attempting to preserve the selection but it just wasn't working.  After further experimentation, I noticed that treeViewer.setSelection(treeViewer.getSelection()) does not work at all.  After a lot of fiddling around, I finally tracked down the problem:  one of my model objects had a broken Object.equals() method that erroneously thought that the object was equal to the tree's root object.  Needless to say, this caused the RCP framework to get very confused.

Having worked through all that, I was pleasantly surprised to find that the TreeViewer gracefully handles modifications to the model without collapsing the tree view or losing its selection.  It uses the registered IElementComparer to perform the equality test (naturally, the default comparer uses Object.equals()).

One thing to note:  if you do set an element comparer on a tree viewer, then for some reason the getElements() method on the ITreeContentProvider will be called.


Wikipedia vs. the Generic LCS Delta Algorithm

Wikipedia offers the following method to compute the longest common subsequence of two sequences (using the so-called "Generic LCS Delta" algorithm):

m <- LENGTH[X];
n <- LENGTH[Y];
for i <- 1 to m, do c[i,0] <-0;
for j <- 0 to n, do c[0,j] <-0;
b <- c;
for i <- 1 to m, do {
    for j <- 1 to n do {
         if (xi = yj) {
             c[i,j] <- c[i-1,j-1]+1;
             b[i,j] <- "UP-LEFT";
         else if (c[i-1,j] >= c[i,j-1]) {
             c[i,j] <- c[i-1,j];
             b[i,j] <- "UP";
         else {
             c[i,j] <- c[i,j-1];
             b[i,j] <- "LEFT";
return c and b

This algorithm fails for various trivial cases, such as (X, Y) = ({1}, {-1}), (X, Y) = ({1}, {}), and (X, Y) = ({}, {1}).  The problem is that the highlighted lines should read as follows:

for i <- 1 to m, do c[i,0] <- "LEFT";
for j <- 0 to n, do c[0,j] <- "UP";

If you neglect this initialization, differences at the beginning of the sequence are ignored.

Actually, I am probably being too hard on the wikipedia article since it suggests that the differences be computed from the LCS array using the following, somewhat confusing, algorithm:

The following algorithm will give the list of edits needed to make Y equal to X (the diff algorithm):

Notation: [n,m] refers to a LCS component at X[n] and Y[n]


   The LCS as found by findLCS() is placed on a stack moving from the lower-right corner and
   following the direction arrows to form the LCS.

oldElem <---- [-1,-1]
while stack is not empty
   elem <---- pop from stack
   // diff does not require LCS components but add to list here if desired
   for i=oldElem[n] to elem[n]
        add delete X(i) from list of edits
   for i=oldElem[m] to elem[m]
        add insert Y(i) to list of edits

The change that I suggest makes it possible to recover the LCS by reversing the links in the table rather than using a stack.  I have an implementation in Java.

Blog Archive