2017-11-17 3 views
0

Ich habe eine Plattform mit einer Singleton-Bean, wo ich eine Transformer-Instanz lade (weil xslt so groß ist, um bei jeder Anfrage eine Instanz zu erstellen).Javax Transformer schlägt in hoher gleichzeitiger Umgebung fehl

Bei normaler Auslastung funktioniert alles einwandfrei, aber bei einem Stresstest mit einer großen Anzahl von gleichzeitigen Anforderungen beginnt der Transformator eine ArrayIndexOutOfBoundsException auszulösen und funktioniert nicht mehr, sodass ich meine Serverinstanz neu starten oder die Anwendung erneut bereitstellen muss.

Dies ist die Art, wie ich meine Instanz erstellen, wenn die Anwendung bereitgestellt wird:

private Transformer createCFDI33TransformerInstance() { 

      InputStream in = new URL("http://www.sat.gob.mx/sitio_internet/cfd/3/cadenaoriginal_3_3/cadenaoriginal_3_3.xslt").openStream(); 

      TransformerFactory factory = TransformerFactory.newInstance();    
      Transformer transformer 
        = factory.newTransformer(new StreamSource(in)); 
      Logger.getLogger(PadeSingleton.class.getName()).log(Level.INFO, " Se ha cargado la instancia de XSLT"); 
      return transformer; 
     } catch (TransformerConfigurationException | IOException ex) { 
// Loading a remote instance was not possible so I will load a local instance 
      Logger.getLogger(PadeSingleton.class.getName()).log(Level.SEVERE, "No fue posible cargar una nueva instancia de cadena original, se usara la del sistema", ex); 
      InputStream in = CFDIv33Tools.class.getClassLoader() 
        .getResourceAsStream("com/soft/cadenaoriginal_3_3.xslt"); 

      TransformerFactory factory = TransformerFactory.newInstance(); 
      Transformer transformer; 
      try { 
       transformer = factory.newTransformer(new StreamSource(in)); 
       Logger.getLogger(PadeSingleton.class.getName()).log(Level.WARNING, "No fue posible cargar la instancia, se cargara una local"); 
      } catch (TransformerConfigurationException ex1) { 
       Logger.getLogger(PadeSingleton.class.getName()).log(Level.SEVERE, null, ex1); 
       // Estamos en problemas 
       throw new Exception("Error critico"); 
      } 
      return transformer; 
     } 
    } 

Also mit anderen Bohne ich spritze meine Singleton Bean und eine Methode aufrufen, um meine Transformer-Instanz zu erhalten.

public static String transform(String xml, Transformer instance) throws Exception { 

     StringWriter writer = new StringWriter(); 

     try { 

      instance.transform(new StreamSource(new StringReader(xml)), new StreamResult(writer)); 

     } catch (TransformerException e) { 
      throw new Exception("El comprobante contiene simbolos no permitidos o esta mal formado", e); 
     } 

     return writer.toString(); 
    } 

Bei diesem Verfahren ist, wo ich eine ArrayIndexOutOfBoundsException

Caused by: javax.xml.transform.TransformerException: java.lang.ArrayIndexOutOfBoundsException: -1 
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:746) 
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:351) 
    at com.icontech.pade.common.xml.tools.CFDIv33Tools.calcularCadenaOriginalV2(CFDIv33Tools.java:93) 
    ... 138 more 

bekomme ich wiederhole dies geschieht, wenn ich einen Stresstest zu machen, wenn diese Ausnahme folgende Anträge mit derselben Ausnahme fehlschlägt throwed wird. Ich nehme an, meine Instanz ist beschädigt .. oder so etwas.

+0

Also welche Java-Version ist das genau? Haben Sie versucht, die Quelle dieser Java-Version zu finden, um zu überprüfen, was in Zeile 746 von 'TransformerImpl.java' passiert? Hast du eine andere Java-Version ausprobiert? Haben Sie eine andere XSLT-Implementierung wie Saxon 9 ausprobiert? –

+0

https://bugs.openjdk.java.net/browse/JDK-8062518 klingt ähnlich, scheint aber behoben zu sein, so dass Sie möglicherweise die Java-Version aktualisieren müssen. –

+0

Hallo! Ich benutze das Oracle JDK 1.8.0_151 – rafuru

Antwort

1

Die Transformer ist nicht Thread-sicher. Sie sollten ein einzelnes Templates-Objekt erstellen, das das kompilierte Stylesheet darstellt, und dann ein neues Transformer-Objekt für jede Umwandlung instanziieren.

(Im Prinzip ist der Transformer seriell wiederverwendbar, so dass Sie einen Transformer innerhalb desselben Threads wiederverwenden können, sobald eine Transformation abgeschlossen ist. Ich weiß nicht, ob es Vorteile mit Xalan gibt; im Falle von Saxon , es ist besser, jedes Mal einen neuen Transformer zu erstellen.)