2013-06-18 9 views
0

SOAP 기반 웹 서비스를 통해 전송 된 대용량 파일을 읽으려고합니다. 메모리 부족 예외로 인해 클라이언트 코드가 실패합니다. MTOM을 사용하여 이진 데이터를 보내고 큰 파일을 전송하고 읽을 수 있기를 바랍니다. 문제의 파일 크기는 750MB입니다. 나는 아파치 cxf를 사용하고있다. 다음은 웹 서비스 엔드 포인트 implentation입니다.SOAP 웹 서비스를 사용하여 대용량 파일을 검색하는 동안 메모리 부족 예외가 발생했습니다.


<jaxws:endpoint id="contentService" implementor="#contentServiceImpl" 
     address="/contentservice"> 
     <jaxws:dataBinding> 
      <bean class="org.apache.cxf.jaxb.JAXBDataBinding"> 
       <property name="marshallerProperties"> 
        <map> 
         <entry> 
          <key> 
           <value>jaxb.encoding</value> 
          </key> 
          <value>UTF-8</value> 
         </entry> 
        </map> 
       </property> 
      </bean> 
     </jaxws:dataBinding> 
     <jaxws:properties> 
      <entry key="mtom-enabled" value="true" /> 
     </jaxws:properties> 
    </jaxws:endpoint> 

당신이 알 수 있듯이


@MTOM 
@WebService(endpointInterface = "com.test.contentservice.service.IContentService") 
@BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING) 
public class ContentServiceImpl implements IContentService { 

@Override 
    public ContentResponse getFile(ContentRequest req) { 
     ContentResponse res = new ContentResponse(); 
     try { 
      File file = this.contentManager.getFile(req); 
      DataSource source = new FileDataSource(file); 
      DataHandler dataHandler = new DataHandler(source); 
      res.setFileData(dataHandler); 
      res.setFileName(file.getName()); 
     } catch (Exception ex) { 
     } 
     return res; 
    } 

봄 항목은, "MTOM 지원은"설정되어 있습니다.

클라이언트 코드는 cxf wsdl2java 도구를 사용하여 생성됩니다. 다음은 샘플 클라이언트 코드 여기


ContentResponse res = new ContentResponse(); 
     try{ 
      res = getRegisterPort().getFile(req); 
      DataHandler dataHandler = res.getFileData(); 
      if(dataHandler!=null){ 
        final InputStream in = dataHandler.getInputStream(); 
        byte[] bytes = IOUtils.toByteArray(in); 
      } 
     }catch (Exception ex) { 
      LOGGER.error("Error in invoking getContent service",ex); 
     } 

는 응답 오브젝트


@XmlAccessorType(XmlAccessType.FIELD) 
public class ContentResponse extends ContentServiceResponseBase { 

    private String content; 
    private String source; 
    private String fileName; 
    @XmlMimeType("application/octet-stream") 
    private DataHandler fileData; 
// Getter/Setter ... 
} 

나뿐만 아니라 클라이언트 코드 수준에서 MTOM을하고 있어요 것입니다

 
final BindingProvider bpAdmin = (BindingProvider) port; 
     bpAdmin.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, curlUrl); 
     SOAPBinding binding = (SOAPBinding)bpAdmin.getBinding(); 
     binding.setMTOMEnabled(true); 

JVM 항목은 같다 다음과 같습니다 :


java -Xms64m -Xmx6144m 

그리고 예외 :

 
Exception in thread "taskExecutor-12" java.lang.OutOfMemoryError: Java heap space 
     at java.util.Arrays.copyOf(Arrays.java:2882) 
     at java.lang.AbstractStringBuilder.expandCapacity(AbstractStringBuilder.java:100) 
     at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:515) 
     at java.lang.StringBuilder.append(StringBuilder.java:189) 
     at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.handleCharacters(StAXStreamConnector.java:312) 
     at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StAXStreamConnector.bridge(StAXStreamConnector.java:176) 
     at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:349) 
     at com.sun.xml.internal.bind.v2.runtime.BridgeImpl.unmarshal(BridgeImpl.java:109) 
     at com.sun.xml.internal.bind.api.Bridge.unmarshal(Bridge.java:222) 
     at com.sun.xml.internal.ws.client.sei.ResponseBuilder$DocLit.readResponse(ResponseBuilder.java:514) 
     at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:110) 
     at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78) 
     at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107) 
     at $Proxy33.getFile(Unknown Source) 

확인 내가 여기에 누락 무엇을, 어떤 포인터가 높게 평가되는 것은 아닙니다.

  • 감사
+0

JVM에서 JVM 옵션을 선택하셨습니까? – WeMakeSoftware

+0

@Funtik .. "ps -ef"는 올바른 jvm 매개 변수를 보여줍니다. – Shamik

답변

0

UPDATE 서버에 readOnce에 전화로 데이터를 보낼 때

당신이이 경우에 StreamingDataHandler을 시도 할 수 있을까요? 그냥 스트리밍 핸들러의 경우, 적용 할 수

참조 : http://docs.oracle.com/cd/E14571_01/web.1111/e13734/mtom.htm


는 IOUtils.toByteArray에서 발생하는 문제인가?

예외가 발생하는 작업 범위를 좁히려 고 시도하지 말고 질문을 업데이트하십시오.

+0

그것도 도달하지 못하는 경우 (dataHandler! = null) { final InputStream in = dataHandler.getInputStream(); byte [] bytes = IOUtils.toByteArray (in); 메모리 부족 예외가 DataHandler에서 발생합니다. dataHandler = res.getFileData(); – Shamik

+0

아파치 cxf를 사용하고 있습니다. CXF는 특별한 StreamingDataHandler를 요구하지 않고 직접 스트리밍을 지원합니다. StreamingDataHandler는 JAX-WS에 적용 가능합니다. – Shamik