2014-05-14 3 views
1

xml 파일에서 입력 스트림을 가져 오는 웹 서비스가 있습니다. 이제, 나는 동일한 입력 스트림으로 검증하고 그것을 읽고 싶다. 마크를 사용하고 재설정했습니다.유효성을 검사하고 동일한 입력 스트림을 사용하여 읽기

Glassfish 및 Websphere에서 제대로 작동합니다. 그러나 openEJB를 사용하여 통합 테스트를 실행하면 유효성 검사 후 스트림이 닫힙니다. 나는 간단한 예를 들어 그것을 재현 할 수있다.

어떻게하면 좋을까요? 유효성 검사기 구현은 항상 동일합니다. 그러나 모든 환경은 inputstream의 또 다른 구현을 사용합니다.

public class XMLReader { 
public static void main(String[] args) { 
    try { 
     XMLReader reader = new XMLReader(); 
     InputStream stream = new BufferedInputStream(new FileInputStream(
       new File("myXML.xml"))); 
     reader.read(stream); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public void read(InputStream xmlInputStream) throws SAXException, 
     IOException { 
    if (xmlInputStream.markSupported()) { 
     xmlInputStream.mark(0); 
     validateXML(xmlInputStream); 
     xmlInputStream.reset(); 
     readXML(xmlInputStream); 
    } 
} 

private void readXML(InputStream xmlInputStream) { 
    // READ xmInputStream with STAX, JAXB, etc. whatever 

} 

private void validateXML(InputStream xmlInputStream) throws SAXException, 
     IOException { 
    Source schemaFile = new StreamSource(new File("myXSD.xsd")); 
    Source xmlFile = new StreamSource(xmlInputStream); 
    SchemaFactory schemaFactory = SchemaFactory 
      .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
    Schema schema = schemaFactory.newSchema(schemaFile); 
    Validator validator = schema.newValidator(); 
    try { 
     validator.validate(xmlFile); 
     System.out.println("is valid"); 
    } catch (SAXException e) { 
     System.out.println("is NOT valid"); 
     System.out.println("Reason: " + e.getLocalizedMessage()); 
    } 
} 
} 

예외 :

java.io.IOException: Stream closed 
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:145) 
at java.io.BufferedInputStream.reset(BufferedInputStream.java:414) 
at xmltest.XMLReader.read(XMLReader.java:36) 
at xmltest.XMLReader.main(XMLReader.java:27) 
+0

네트워크에서 읽는다면이 사실을 이해할 수 있습니다. 서버에 배포 할 때 실제 파일에서 XML을 읽는 중입니까? –

+0

XML 파일을 REST 서비스를 통해 문자열로 가져옵니다. 그 String은 Inputstream을 만드는 데 사용되었습니다. 맨 위에있는 예제는 동작을 보여주기위한 것입니다. – pL4Gu33

+0

문자열에서 InputStream을 생성하기위한 코드를 보여주십시오. 임의로 긴 String에 내용을로드하는 것은 일반적으로 좋은 생각이 아닙니다. 임시 파일에 복사하십시오 (아마도 [java.nio.file.Files.copy (...)]를 사용하십시오 (http://docs.oracle.com/javase/8/docs/api/java/nio/file/). Files.html # copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption ...-)) 먼저. 감사합니다. –

답변

3

불행하게도, XML 파서는 독서를 마무리시 스트림을 닫습니다. 나는 그것이 정말로 그것을하는 이유를 이해하지 못한다. 그리고 나는 자신이 소유하지 않은 스트림을 폐쇄하는 것을 권하지 않는다. 내가 그것을 빨리 파악할 수없는 이유가있을 수 있습니다. 이 날의 마지막에 당신의 InputStream을 닫습니다 재정의 할 SAX 구현 같은 것을 생각하게

public static void main(String[] args) { 
    try (FileInputStream in = new FileInputStream(new File("myXML.xml"))){ 
     XMLReader reader = new XMLReader(); 
     InputStream stream = new BufferedInputStream(in) { 
      @Override 
      public void close() throws IOException { 
       // don't close 
      } 
     }; 
     reader.read(stream); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

. 그것에 대해 NoCloseStream을 사용하면 정상적으로 작동합니다. – pL4Gu33

0

:

어쨌든, 당신은 BufferedInputStream을 있고있다 무엇을 할 수 있는지, 그 랩 InputSteam 닫히지 않습니다 확인. 그래, 당신은 글래스 피시 아니 었 OpenEJB를 클래스 경로에 어딘가에 Xerces에 병이있는 경우

if (xmlInputStream.markSupported()) { 
    xmlInputStream.mark(0); 
    // validateXML(xmlInputStream); 
    xmlInputStream.reset(); 
    readXML(xmlInputStream); 
} 

: 당신이 validateXML 라인을 코멘트 경우 는

는 모든 것이 잘 작동 하는가

?

나는이 문제가 과거에 있었지만 정확한 문제는 기억할 수 없다고 확신한다.

1

Marcel Steinbach의 솔루션에 약간의 수정이 추가되었습니다. BufferedInputStream은 입력 스트림을 닫지 않아도되는 불필요한 버퍼를 유지합니다. 대신 XML을 포함하는 표시 가능한 입력 스트림에 read 메소드를 위임하는 익명의 InputStream 클래스를 만들 수 있습니다. 의 InputStream의 close 메소드의 기본 구현은 아무것도하지 않는 때문에, 스트림은 확인 후 열린 상태로 유지됩니다

validator.validate(new StreamSource(new InputStream() { 
    @Override 
    public int read() throws IOException { 
     return xmlInputStream.read(); 
    } 
})); 
0

당신이 당신의 입력 스트림이 표시가 지원되는지 확실하지 않은 경우, 사용할 수있는 효율적에 다음을 유효성 검사 후 XML을 읽을 수있는 버퍼에 복사하십시오.

final StringWriter sw = new StringWriter(is.available()); 
validator.validate(new StreamSource(new InputStream() { 
    @Override public int read() throws IOException { 
     int ch = is.read(); 
     sw.write(ch); 
     return ch; 
    } 
})); 
readXML(new ByteArrayInputStream(sw.toString().getBytes())); 
관련 문제