You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@poi.apache.org by "Jana, Kumar Raja" <kj...@ptc.com> on 2009/02/12 11:01:09 UTC

Problem due to making DocumentInputStream final in POI 3.5 beta

Hi,

 

I use MPXJ libraries for parsing MS Project files and Apache Tika
libraries for parsing many other file formats in my application. Both
the libraries rely on Apache POI jars for extracting text from MS Office
files.

 

The latest dev version of Tika has upgraded to POI 3.5 beta 4 but one of
the classes in MPXJ libraries extends
org.apache.poi.poifs.filesystem.DocumentInputStream (which is made final
in POI 3.5 beta 4). This is throwing a NoSuchMethodError and causing my
application to crash. Is there any workaround to avoid this error? Can
the dev team make the class not final again or is there any specific
reason for not allowing extension of this class?

 

 

Thanks,

Kumar


Re: Problem due to making DocumentInputStream final in POI 3.5 beta

Posted by Josh Micich <jo...@gmail.com>.
Hello Kumar,

Thanks for pointing out this incompatibility between the latest versions of
poi and mpxj.
I have posted a proposed patch to mpxj-developers@lists.sourceforge.net .
Jon Iles has already put it into CVS and replied here:

http://sourceforge.net/mailarchive/message.php?msg_name=bba0cc140902121451v141f17f5u8900166451a7a6b0%40mail.gmail.com

To get your application running you have three choices:
  - Get the latest mpxj code from cvs ( see
http://sourceforge.net/cvs/?group_id=70649 )
  - Wait for the next release of mpxj
  - Patch your local poi-3.5-beta4 to make DocumentInputStream non-final

####

The NoSuchMethodError you mention is totally independent DocumentInputStream
being final.
> java.lang.NoSuchMethodError:
org.apache.poi.poifs.filesystem.POIFSFileSystem.getRoot()Lorg/apache/poi/poifs/filesystem/DirectoryEntry;

In April 2008, POIFSFileSystem.getRoot() was changed to return DirectoryNode
instead of DirectoryEntry (
http://svn.apache.org/viewvc?view=rev&revision=646870 ).  This change is a
source compatible but binary incompatible change, and it's the origin of the
NoSuchMethodError you describe.  Change r646870 occurred between POI
versions 3.0.2 and 3.1.  So to observe the error in practice you would need
to run a version of MPXJ which was compiled against POI 3.0.2 or *earlier*
against POI 3.1 or later.  However, it seems very clear to me that MPXJ
version 3.0.0 was compiled against POI 3.2.

I just disassembled line 61 of net/sf/mpxj/mpp/MPPReader.class in version
3.0.0.
(For reference, the mpxj.jar I used had an md5sum of
940f1186c0658c3c33dfd4eccd2bdb23 )

// line 61
  17  aload_3
  18  invokevirtual  Lorg/apache/poi/poifs/filesystem/DirectoryNode;
org/apache/poi/poifs/filesystem/POIFSFileSystem.getRoot()
  21  astore  4

That line of code is clearly compiled against POI post r646870 .  I am
pretty sure that MPXJ version 3.0.0 cannot produce the NoSuchMethodError you
describe. Maybe you have a different version of MPXJ on your classpath.


Having said all that, binary incompatibility changes are a general problem.
There could be other changes (since POI 3.2) that cause similar linkage
errors.  These are not easy to preemptively detect.  It's straightforward to
confirm source compatibility (just compile the mpxj source against the
specific poi.jar).  However, this does not guarantee binary compatibility
(which is generally more restrictive) between (a previously compiled)
mpxj.jar and poi.jar.
When the JVM finds a violation of binary compatibility it throws a subclass
of LinkageError.  However, all possible checks are not applied in a single
sweep across a whole jar, class or even method.  In some cases (like this
one) only when the invoke instruction is executed for the first time is the
method linked.  A linkage error may lay dormant just because a certain piece
of code hasn't executed yet.

I don't know of any tool which verifies complete binary compatibility
between two pre-compiled jars.  Such a tool would be very handy.


Hope this helps,
Josh