mkyong jax example ejemplo create consumir java spring soap streaming spring-ws

java - jax - ¿Cómo usar el streaming directo para SOAP con Spring-WS?



spring-ws example (3)

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 mientras se procesan.

Usamos spring-ws-core, en la versión 2.0.0 y usamos PayloadRootQNameEndpointMapping como asignador de puntos finales. Como factoría de mensajes, estamos utilizando AxiomSoapMessageFactory . Implementamos el método StreamingPayload y el correspondiente writeTo(XMLStreamWriter writer) , que utilizamos para escribir nuestra carga útil (de acuerdo con el ticket Spring-ws JIRA, SWS-352 ).

Esto funciona bien sin ningún error, ¡pero queríamos transmitir directamente! Aparentemente esto 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 esto se transmitirá directamente al consumidor / cliente, por lo que el encabezado de jabón ya está escrito en nuestro escritor y se cierra una vez que se completa el punto final. Desafortunadamente esto no es posible, la secuencia no puede ser usada directamente! El flujo está envuelto en un ByteArrayInputStream , que se encuentra en la fuente spring-ws.

La implementación de StreamingOMDataSource muestra esto (se puede ver en los resortes FishEye ). StreamingOMDataSource llama a su implementación StreamingPayload y le da 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 XMLStreamWriter con ByteArrayOutputStream y llama a la carga útil para permitir la escritura, como se describe 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 la transmisión directa? ¿Alguna idea para esto? ¡Gracias de antemano!

Actualización : finalmente creé un ticket JIRA (SWS-704) para Spring WS. Si desea verlo implementado, considere verlo / votarlo en la página JIRA. Esperemos que tengamos al menos una respuesta útil.


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

Si necesita un alto rendimiento, los servicios web no son excelentes. Pero puedes optimizar manualmente los servicios web simples, no es tan difícil. Pero cambiar a otro formato de transporte sería más "rentable" si necesita un mayor rendimiento. Todavía mantendría las cosas a través de HTTP, especialmente si tiene algunos requisitos de autenticación.


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

Así que el truco sería escribir su propio servlet / controlador de resorte que manejaría esta respuesta específica y transmitir el sobre de jabón, luego su carga útil, luego la etiqueta final del sobre de jabón. Esto es asumiendo que usted no tiene ningún requisito de WSS.


También tienes que deshabilitar el almacenamiento en caché de carga útil:

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

¡Con esta configuración, finalmente podemos realizar la transmisión directa para SOAP con Spring WS!