どのように私はクラスローダでapachのXMLBeansクラスをロードしますか?

ニレ:

私たちは、デフォルトでは、PDF出力を生成することを報告aplicationを持っていますが、他の出力形式を生成するために、独自のクラスを書くことができます。この方法で私は、Apache POI 10.0を使用してXLSファイルを生成しています。しかし、今のxlsxファイルを生成するための要求が来ました。私はこのコードでブックを作成しようとすると:

XSSFWorkbook wbTemplate=new XSSFWorkbook()

私はエラーを得ました:

java.lang.NoSuchMethodError: org.apache.xmlbeans.XmlOptions.setSaveAggressiveNamespaces()Lorg/apache/xmlbeans/XmlOptions;

私は、アプリケーションがすでにもちろん、上記の方法が含まれていないことをXMLBeansのファイルの非常に古いバージョンを使用していることを発見しました。まず、私はちょうど私が運を持っている場合には、より新しいバージョンを持つXML Beanファイルを置き換えるためにしようと試みたが、アプリケーションがフリーズします。

私の次のアイデアは、クラスローダを使用して、アプリがXLSXファイルを生成するために、私のクラスを実行するとき、私は上記の方法をロードすることです。私はこのソリューションを実装しているので、実行するには、インターネット上のが見つかりました:

URL[] classLoaderUrls = new URL[]{new URL("file:/C:/HOME/Installs/Apache POI/poi-3.10/ooxml-lib/xmlbeans-2.6.0.jar")};
URLClassLoader urlClassLoader = new URLClassLoader(classLoaderUrls);
Class<?> beanClass = urlClassLoader.loadClass("org.apache.xmlbeans.XmlOptions");
Constructor<?> constructor = beanClass.getConstructor();
Object beanObj = constructor.newInstance();
Method[] m=beanClass.getMethods();
Method method = beanClass.getMethod("setSaveAggressiveNamespaces");
method.invoke(beanObj);

しかし、どのような驚き、それは私が再びこの関数が存在しないというエラーを得た「setSaveAggressiveNamespaces」メソッド名を取得したいです。それから私は、ファイルにこのクラスのすべての関数名を書かれているし、それが真である、その名前は存在しません。しかし、1つのSで「setSaveAggresiveNamespaces」と呼ばれる別のものを存在します!私はXSSFを作成するためにwan'tとき、私それが動作します。この呼び出すと、もちろん、私はまだ(ダブルSS付き)setSaveAggressiveNamespacesが存在しないというメッセージが表示されますワークブック。しかしsetSaveAggressiveNamespacesが、これはApacheのポイパッケージに来ているので、クラスにする必要があります。

私はそれを動作させるために、この場合に何ができますか?アプリケーションは、Java 1.6の下で実行されます

答えを事前に感謝します。

更新

アクセル、これは私が今、クラスをロードする方法です。

 public void customClassLoader() throws Exception
{
    URL[] classLoaderUrls = new URL[]{new URL("file:/C:/HOME/Installs/Apache POI/poi-3.10/ooxml-lib/xmlbeans-2.3.0.jar")};
    URLClassLoader urlClassLoader = new URLClassLoader(classLoaderUrls,null);
    Class<?> beanClass = urlClassLoader.loadClass("org.apache.xmlbeans.XmlOptions");
    log("RESOURCES:" +beanClass.getResource("/org/apache/xmlbeans/XmlOptions.class"));
    Constructor<?> constructor = beanClass.getConstructor();
    Object beanObj = constructor.newInstance();
    Method[] m=beanClass.getMethods();
    for (int i=0;i<m.length;++i)
        log("QQQ:" +String.valueOf(i)+".: "+ m[i].getName());
    Method method = beanClass.getMethod("setSaveAggressiveNamespaces");
    method.invoke(beanObj);
}

そして私は、レポートを生成するクラスの最初の行で、上記の関数を呼び出します。それ以前には何もありません。

「リソース::jarファイル:ファイル:/ C:!/ HOME /インストールします/ ApacheのPOI / POI-3.10 / OOXML-libに/ XMLBeansの-2.3.0.jar / ORG / apacheの/ XMLBeansの/ RESOURCEは、次のようにログに書かれていますXmlOptions.class」

アクセル・リヒター:

URLClassLoaderの(のjava.net.URL [])状態:

指定されたURLの新しいURLClassLoaderを構築し、デフォルトの委譲の親であるClassLoaderを使用して

だからデフォルトの委譲の親であるClassLoaderも使用され、そうorg.apache.xmlbeans.XmlOptionsではなく、追加の与えられたから見つかった場合はそこからロードされますURL

だから我々は必要がないデフォルトの委譲の親であるClassLoaderを使って。URLClassLoaderの(のjava.net.URL []、nullが)これをやっています。

例:

import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.Constructor;

public class UseURLClassLoader {

 public static void main(String[] args) throws Exception {
  URL[] classLoaderUrls;
  URLClassLoader urlClassLoader;
  Class<?> beanClass;

  classLoaderUrls = new URL[]{new URL("file:/home/axel/Dokumente/JAVA/poi/poi-3.10.1/ooxml-lib/xmlbeans-2.6.0.jar")};
  urlClassLoader = new URLClassLoader(classLoaderUrls); //default delegation parent ClassLoader is used
  beanClass = urlClassLoader.loadClass("org.apache.xmlbeans.XmlOptions");
System.out.println(beanClass.getResource("/org/apache/xmlbeans/XmlOptions.class")); //class is loaded using default parent class loader

  URL context = new URL("file:/home/axel/Dokumente/JAVA/poi/poi-3.10.1/");
  classLoaderUrls = new URL[] {
   new URL(context, "poi-3.10.1-20140818.jar"),
   new URL(context, "poi-ooxml-3.10.1-20140818.jar"),
   new URL(context, "poi-ooxml-schemas-3.10.1-20140818.jar"),
   // maybe others also necessary
   new URL(context, "lib/commons-codec-1.5.jar"),
   // maybe others also necessary
   new URL(context, "ooxml-lib/xmlbeans-2.6.0.jar")
   // maybe others also necessary
  };
  for (int i = 0; i < classLoaderUrls.length; i++) {
System.out.println(classLoaderUrls[i]);
  }
  urlClassLoader = new URLClassLoader(classLoaderUrls, null); //set default parent class loader null
  beanClass = urlClassLoader.loadClass("org.apache.xmlbeans.XmlOptions");
System.out.println(beanClass.getResource("/org/apache/xmlbeans/XmlOptions.class")); //class is loaded using this class loader

 }

}

次のように私のために呼ばれます。

axel@arichter:~/Dokumente/JAVA/poi/poi-4.0.0$ java -cp .:./*:./lib/*:./ooxml-lib/* UseURLClassLoader 

それが生成します。

jar:file:/home/axel/Dokumente/JAVA/poi/poi-4.0.0/ooxml-lib/xmlbeans-3.0.1.jar!/org/apache/xmlbeans/XmlOptions.class
file:/home/axel/Dokumente/JAVA/poi/poi-3.10.1/poi-3.10.1-20140818.jar
file:/home/axel/Dokumente/JAVA/poi/poi-3.10.1/poi-ooxml-3.10.1-20140818.jar
file:/home/axel/Dokumente/JAVA/poi/poi-3.10.1/poi-ooxml-schemas-3.10.1-20140818.jar
file:/home/axel/Dokumente/JAVA/poi/poi-3.10.1/lib/commons-codec-1.5.jar
file:/home/axel/Dokumente/JAVA/poi/poi-3.10.1/ooxml-lib/xmlbeans-2.6.0.jar
jar:file:/home/axel/Dokumente/JAVA/poi/poi-3.10.1/ooxml-lib/xmlbeans-2.6.0.jar!/org/apache/xmlbeans/XmlOptions.class

だから、最初のクラスは、デフォルトの親クラスローダを使ってロードされます。私にとっては、ロードorg.apache.xmlbeans.XmlOptions新しいから遠いですxmlbeans-3.0.1.jarあなたのためにそれは遠く、古いからロードしますxmlbeans-1.*.jarこれらのjarファイルは、デフォルトの親クラスローダのクラスパス内にあるためです。

2番目のコード部分は、デフォルトの親クラスローダはnullを設定し、そのクラスは、このクラスローダを使用してロードされます。

しかし、クラスローダをいじりは混乱です。デフォルトの親クラスローダセットヌルを持つ、私のコードで示唆されるように、我々は必要なすべてのクラスのソースローダー現在のクラスを与える必要があります。これは、多くの場合、非常に高価なものとなります。そうでない古い持つjarクラスパスにSは常にクラスローダをいじりよりも優れたソリューションとなります。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=212991&siteId=1