2017-11-17 3 views
0

Transformer 인스턴스를로드하는 곳의 Singleton Bean이있는 플랫폼이 있습니다 (xslt는 모든 요청에 ​​대해 인스턴스를 생성하기에 너무 크기 때문에).높은 동시 환경에서 Javax Transformer가 실패 함

일반적인로드에서는 모든 것이 잘 작동하지만 트랜스 포머가 ArrayIndexOutOfBoundsException을 던지기 시작하여 작동을 멈추고 서버 인스턴스를 다시 시작하거나 응용 프로그램을 다시 배포해야하는 동시 요청이 많은 스트레스 테스트를 수행합니다.

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

그래서 다른 콩에 내 싱글 콩을 주입 내 변압기 인스턴스를 얻을 수있는 메소드를 호출

은 응용 프로그램이 배포 될 때 내 인스턴스를 생성하는 방법입니다. 내가는 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 

을받을 경우이 방법

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

내가이 예외이 같은 예외와 함께 실패 다음과 같은 요청을 throwed 때 나는, 스트레스 테스트를 할 때 이런 일이 발생 반복이다. 내 인스턴스가 손상된 것 같아. 아니면 뭔가.

+0

그럼 Java 버전이 정확히 무엇입니까? 그 Java 버전의 소스를 찾아서'TransformerImpl.java'의 746 행에서 어떤 일이 일어나는지 확인하려고 했습니까? 다른 Java 버전을 사용해 보셨습니까? Saxon 9와 같은 다른 XSLT 구현을 시도해 보셨습니까? –

+0

https://bugs.openjdk.java.net/browse/JDK-8062518 소리는 비슷하지만 수정 된 것으로 보이므로 Java 버전을 업데이트해야합니다. –

+0

안녕하세요! oracle JDK 1.8.0_151을 사용하고 있습니다. – rafuru

답변

1

Transformer은 스레드로부터 안전하지 않습니다. 컴파일 된 스타일 시트를 나타내는 단일 Templates 개체를 만든 다음 각 변환에 대해 새 Transformer 개체를 인스턴스화해야합니다.

(원칙적으로 Transformer는 순차적으로 재사용 할 수 있으므로 변환이 완료되면 동일한 스레드 내에서 변압기를 재사용 할 수 있습니다 .Saxon의 경우 Xalan을 사용하여 이점을 얻을 수 있는지 여부는 알 수 없습니다. 매번 새로운 Transformer를 만드는 것이 더 좋습니다.)

관련 문제