Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Request-reply model for hybrid SOAP over HTTP/JMS over middleware

One of our products implements the following one-way web service structure:

Server <--------------------- Middleware <---------------- Client
        SOAP over JMS (queue)              SOAP over HTTP

In this model, clients send SOAP messages over HTTP to our middleware (Progress SonicMQ). The messages get pushed into JMS queues by SonicMQ and our server fetches them from there. However, as you can see, the server does not send a response to the client (asynchronous JMS).

We would like to implement a response-channel to this model. The often suggested solution is to create a temporary replyTo-queue (on the fly) in the middleware, allowing server to send a response to that queue. Then, client can fetch the response and the replyTo-queue is closed. This sounds convenient enough, but unfortunately our clients operate over plain HTTP and not over JMS, so their clients can not easily set up replyTo queues.

One approach to achieving a response channel in such hybrid HTTP/JMS SOAP model would be to configure the middleware to open the replyTo queue on each succesful SOAP receive, append the replyTo-queue and sender information to the SOAP message and push the message to the queue, where it would be fetched by the server. After receiving and processing the message, the server could send a response to the indicated replyTo-queue in the middleware. Finally, the middleware would send the response (SOAP) over HTTP back to the original client by using the data from the SOAP message (the data that was inserted there in the middleware procedures when the request was first received).

While propably possible, this sounds kind of a hacky. So the question is: any cleaner ways of achieving such request/response model on our case? The server end has been implemented in Java.

The solution:

Progress SonicMQ supports "Content Reply Send" HTTP Acceptor, which allows to easily send JMS reply. The Content Reply Send acceptor works in a following way:

  • Acceptor receives the HTTP message a client sent
  • Acceptor creates a temporary JMS queue
  • Acceptor builds up a JMS message, containing the HTTP body, and adds the temporary queue's identification to the newly created JMS message
  • Acceptor pushes the JMS message into its destination queue (not the temporary queue)
  • Acceptor starts consuming the temporary reply-To queue
  • When client fetches message from original destination queue, it contains the set reply-To queue identification
  • Client consumes message
  • Client sends reply to the reply-To queue
  • Acceptor receives message from the queue
  • Acceptor sends message as HTTP to the client that originally sent the HTTP message

Should consumer ("server" in our case) fail and not send reply causing timeout, Sonic's HTTP Acceptor sends an HTTP message to the client indicating the timeout. This is a very standard feature in SonicMQ. I suppose it exists in other products as well.

This allows using standard SOAP over JMS (see skaffman's answer) in the "server" end avoids any custom programming in the middleware.

I still see some problems in the JMS model though, but this is definitely an improvement.

Update 2009-11-05:

After researching this issue even more, it turns out my suspicion against HTTP<-->middleware<-->JMS has been relevant.

There are a few critical problems in this model. Synchronous-asynchronous model with middleware simply isn't convenient. Either have both ends implement JMS connection (which should rock) or go with HTTP in both ends. Mixing them results only in headaches. Of these two, SOAP-over-HTTP is simpler and better supported than SOAP-over-JMS.

Once more: if you are designing this kind of a system... DON'T.

like image 287
Tuukka Mustonen Avatar asked Oct 25 '09 17:10

Tuukka Mustonen


2 Answers

I don't think your suggested solution is hack at all, I think that's the right solution. You have the client-middle layer with a synchronous protocol, and then the middle-server layer using an asynchronous layer, to which you have to add a reply path in order to satisfy the synchronous semantics. That's what middleware is for. Remember that that JMS provides explicit support for temporary reply-to queues, you won't need to mess with the payload at all.

A more left-field possibility is the leverage the fact that SOAP 1.2 was designed with JMS in mind, and so you could use web service layer between middleware and server layer which does SOAP-over-JMS. That means you can keep SOAP from end-to-end, with the middleware changing only the transport.

The only web service stack that I know of that supports JMS transport is Spring Web Services, where the process and development is documented here. This would also give you the opportunity to port your SOAP layer to Spring-WS, which kicks ass :)

like image 149
skaffman Avatar answered Oct 27 '22 13:10

skaffman


Why not add a link to a page that lets users check to see when a response is ready, a la a Fed Ex tracker ID? Give your users the tracker ID when they send the request.

This would fit into the HTTP request/response idiom, and your users would still know that the request is "fire and forget".

like image 28
duffymo Avatar answered Oct 27 '22 12:10

duffymo