2011-03-02 11 views
16

Queremos habilitar la transmisión directa de nuestra carga útil en los puntos finales del servicio web. Tenemos que procesar una gran cantidad de datos y queremos transmitir los datos durante el procesamiento.¿Cómo usar la transmisión directa de SOAP con Spring-WS?

Usamos spring-ws-core, en la versión 2.0.0 y utilizamos el PayloadRootQNameEndpointMapping como asignador de punto final. Como fábrica de mensajes estamos usando el AxiomSoapMessageFactory. Implementamos el StreamingPayload y el método correspondiente writeTo(XMLStreamWriter writer), que usamos para escribir nuestra carga (De acuerdo con el boleto JIRA de spring-ws, SWS-352).

Esto funciona bien sin ningún error, pero queríamos transmitir directamente! Esto aparentemente no es posible. Hicimos una prueba sencilla en la que transmitimos algunos datos para evaluar el comportamiento.

writer.writeStartElement("exampleResponse") 

10000.times 
{ 
    writer.writeStartElement("example") 
    writer.writeEndElement()  
} 

writer.writeEndElement() 

Asumimos que este será transmitido directamente al consumidor/cliente, por lo que el encabezado de jabón ya está escrito en nuestro escritor y se cierra después de que se complete el punto final. Lamentablemente, esto no es posible, ¡la transmisión no se puede usar directamente! La secuencia está envuelta en un ByteArrayInputStream, que se encuentra en la fuente spring-ws.

La implementación de StreamingOMDataSource muestra esto (se puede ver en springs FishEye). El StreamingOMDataSource llama a su implementación de StreamingPayload y le proporciona un escritor para esto.

public XMLStreamReader getReader() throws XMLStreamException { 
    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    serialize(bos, null); 

    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); 
    return StAXUtils.createXMLStreamReader(bis); 
} 

El método #serialize() crea la XMLStreamWriter con el ByteArrayOutputStream y pide la carga útil para permitir la escritura, como se describió anteriormente.

public void serialize(OutputStream output, OMOutputFormat format) 
     throws XMLStreamException 
{ 
    XMLStreamWriter streamWriter; 
    if ([...]) { 
     // Create stream writer with defined charset 
    } 
    else { 
     streamWriter = StAXUtils.createXMLStreamWriter(output); 
    } 
    serialize(streamWriter); 
} 

public void serialize(XMLStreamWriter xmlWriter) throws XMLStreamException { 
    payload.writeTo(xmlWriter); 
    xmlWriter.flush(); 
} 

Así que esto no es utilizable para mí. ¿Es posible lograr transmisión directa? Alguna idea para esto? ¡Gracias de antemano!


actualización: Finalmente creó una JIRA ticket (SWS-704) para la primavera WS. Si desea verlo implementado, considere verlo/votarlo en la página de JIRA. Espero que tengamos al menos una respuesta útil.

+0

¿No veo que SWS-352 permite la transmisión? Usted sabe que los servicios web están sobre HTTP ¿verdad? – ThomasRS

Respuesta

4

También hay que desactivar el almacenamiento en caché de carga útil:

<bean id="messageFactory" 
     class="org.springframework.ws.soap.axiom.AxiomSoapMessageFactory"> 
    <property name="payloadCaching" value="false"/> 
</bean> 

Con este ajuste por fin estamos capaz de realizar el streaming directo para SOAP con Spring WS!

0

Solo puedo pensar en un truco para esto: las pilas (cxf, spring ws, etc.) almacenan el mensaje completo, ya que tienen que validar la respuesta xml, para poder calcular las claves criptográficas si la seguridad está habilitada, etc.

Así que el truco sería escribir su propio servlet personalizado/controlador de primavera que manejaría esta respuesta específica y transmitir el sobre de jabón, luego su carga, y luego la etiqueta final del sobre de jabón. Esto supone que no tienes ningún requisito de WSS.

2

No puede (nunca debería) transmitir los datos dentro de un servicio web, como por ejemplo enviar continuamente XML a través de la conexión HTTP en una única solicitud de servicio web a lo largo del tiempo. Tendrá que hacer muchas llamadas de servicio web individuales o acumular varias llamadas en una sola.

Si necesita un alto rendimiento, los servicios web no son geniales. Pero puede optimizar a mano servicios web simples, no es tan difícil. Pero cambiar a otro transport format sería más 'on the money' si necesita un mayor rendimiento. Todavía mantendría todo sobre HTTP, especialmente si tienes algunos requisitos de autenticación.

+0

Si es tan malo proporcionar servicios web transmitidos, ¿por qué JAX-WS RI proporciona soporte para enviar y recibir archivos adjuntos de gran tamaño de forma continua? ¡Pensaremos en una transferencia de datos fragmentada, pero la implementación de Spring-WS aún no es útil! ¿Puedes explicar qué pasa con una implementación de transmisión basada en servicios web/HTTP? – codevour

+0

La API de transmisión es más eficiente, la alternativa es construir un árbol DOM. Se llama API de transmisión, pero esto solo se aplica a la creación del XML. No tiene garantía, de hecho sería muy extraño, si el receptor (punto final del servicio web) no leyó la solicitud completa, la validó y luego procesó su carga útil como un todo. – ThomasRS

+0

Mantén la vista en la pelota; ¿Desea transmitir sus datos, no necesita hacer streaming de servicios web para lograr eso? ¿Qué tipo de rendimiento necesita y tiene un ejemplo del xml que está enviando? – ThomasRS

Cuestiones relacionadas