¿Cómo se carga la clase apach xmlbeans con cargador de clases?

olmo:

Tenemos una aplicacion de informes que, por defecto genera salidas PDF, pero se puede escribir sus propias clases para generar cualquier otro formato de salida. De esta manera he generado archivos XLS usando Apache POI 10.0. Pero, ahora llegó una petición para generar xlsx. Cuando trato de crear un libro con este código:

XSSFWorkbook wbTemplate=new XSSFWorkbook()

Tengo el error:

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

He descubierto que la aplicación ya utiliza una versión muy antigua del archivo xmlbeans que por supuesto no contiene el método anterior. En primer lugar He probado para reemplazar el archivo XML de frijol con una nueva versión si acaso tengo suerte, pero se congela la aplicación.

Mi siguiente idea es utilizar el cargador de clases y cuando la aplicación se ejecuta mi clase para generar el archivo xlsx que cargar el método anterior. Para ello he implementado esta solución se encuentran en Internet:

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);

Pero qué sorpresa cuando se quiere obtener el "setSaveAggressiveNamespaces" nombre del método llegué de nuevo el error que esta función no existe. A continuación, he escrito en un archivo de todos los nombres de las funciones de esta clase, y es verdad, no existe ese nombre. Pero existe otra que se llama "setSaveAggresiveNamespaces" con una S! Si invoco esta funciona, pero por supuesto cuando me wa no para crear el libro de trabajo XSSF Todavía recibo el mensaje de que no existen los setSaveAggressiveNamespaces (con doble SS). Pero los setSaveAggressiveNamespaces deben estar en la clase ya que este viene con el paquete de Apache POI.

¿Qué puedo hacer yo en este caso para hacer que funcione? La aplicación se ejecuta en Java 1.6

Gracias de antemano por las respuestas.

ACTUALIZAR

Axel, así es como me carga ahora la clase:

 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);
}

Y luego llamo a la función anterior en la primera fila de la clase que genera el informe. No hay nada antes de ella.

El recurso está escrito en el registro como: "RECURSOS: Tarro: file: / C: / home / Instala / Apache POI / poi-3.10 / OOXML-lib / xmlbeans-2.3.0.jar / org / apache / xmlbeans / XmlOptions.class"

Axel Richter:

URLClassLoader (java.net.URL []) estados:

Construye un nuevo URLClassLoader para los URL especificados utilizando el cargador de clases de delegación principal predeterminada .

Por lo que el cargador de clases padre delegación por defecto también se utilizará por lo que el org.apache.xmlbeans.XmlOptionsse cargarán a partir de ahí si se encuentra y no de lo dado adicional URL.

Por lo que necesitamos no usar el cargador de clases de delegación principal predeterminada. URLClassLoader (java.net.URL [], null) está haciendo esto.

Ejemplo:

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

 }

}

Para mi llamada de la siguiente manera:

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

produce:

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

Así que al principio se carga la clase utilizando el cargador de clase padre por defecto. Para mí se carga org.apache.xmlbeans.XmlOptionsmás lejos de la más reciente xmlbeans-3.0.1.jar. Para que se cargue más lejos de la más antigua xmlbeans-1.*.jar. Esto es así porque esos frascos están en la ruta de clase del cargador de clases padre por defecto.

La segunda parte de código a continuación, establece la matriz por defecto cargador de clases nula y por lo tanto la clase sólo se ha cargado el uso de este cargador de clases.

Pero jugar un poco con los cargadores de clases es un desastre. Como se deduce de mi código, teniendo la matriz por defecto conjunto de cargador de clases nula, necesitamos dar el cargador de clases actual todas las fuentes necesarias de clase. A menudo, esto se vuelve muy costoso. Por lo tanto , no tener los viejos jars en la ruta de clase será siempre la mejor solución que jugar un poco con los cargadores de clases.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=212994&siteId=1
Recomendado
Clasificación