2017-01-06 26 views
3

データを受信し、非同期IBM MQ要求を介してデータをチェックするRESTサービスがあります。非同期通信を同期する

RESTコントローラ:

@RestController 
@RequestMapping("/request") 
public class RequestController { 

    @RequestMapping(method = RequestMethod.POST) 
    public Response postRequest(@RequestBody Request request) { 

     String data = request.getData(); 

     jmsSender.send(data); 

     // Now I need the response from MQ 
     // String mqResponse = ... 
     if (mqIsValid(mqResponse)) { 
      return createValidResponse(); 
     } 
     return createNotValidResponse(); 
    } 
} 

MQ送信者:

@Service 
public class JmsSender { 

    public void send(String data) { 
     jmsTemplate.convertAndSend("QUEUE.TO.MQ", data); 
    } 

} 

MQ受信機:私は正しい応答を作成するためにMQから右のデータを待つことができますどのように

@Component 
public class JmsReceiver { 

    @JmsListener(destination = "QUEUE.FROM.MQ, containerFactory = "DefaultJmsListenerContainerFactory") 
    public void receiveMessage(String message) { 
     // How to pass the message to the controller? 
    } 

} 

コントローラー?

BlockingQueueをこのように使用することは可能ですか?here?私の場合は、データを区別する必要があります。私はブロッキングキューから最初のデータを取ることはできません。

たとえば、2つのREST要求(データ:abcおよびxyz)が同時に存在する場合。 MQから得た最初の答えだけでなく、正しい答えに確実に答えることができますか?

また、MQインターフェイスを変更することもできません。

+1

あなたは、この使用してJMSを達成できるかどうか私は知りません。私は数か月前に何かsimillarをしなければならなかったので、これを実現するためにIBM MQクラスを使用しなければなりませんでした。 MQクラスを使用できる場合は、固有のcorrelationIdを設定して使用して、要求との応答を一致させる必要があります。 –

+0

ありがとう、私はそれを調べます。実際には、データそのものには、それを識別するために使用できる固有のIDが含まれています。しかし、どのようにしてRESTコントローラにMQからの応答を待って応答をコントローラに渡すように指示できますか? – deve

答えて

0

私は適切な解決策を見つけることができなかったので、データを取得するための簡単な待機メカニズムを作成しました。

MqReceiver:

@Component 
public class JmsReceiver { 

    private final Lock lock; 
    private final Condition containsKey; 
    private final Map<String, String> responses; 

    public JmsReceiver() { 
     this.lock = new ReentrantLock(); 
     this.containsKey = lock.newCondition(); 
     this.responses = new HashMap<>(); 
    } 

    @JmsListener(destination = "QUEUE.FROM.MQ", containerFactory = "DefaultJmsListenerContainerFactory") 
    public void receiveMessage(String message) { 
     put(getKeyFromMessage(message), message); 
    } 

    public String get(String key) throws InterruptedException { 
     lock.lock(); 
     try { 
      while (!responses.containsKey(key)) { 
       containsKey.await(); 
      } 
      return responses.get(key); 
     } finally { 
      lock.unlock(); 
     } 
    } 

    public void put(String key, String messagee) { 
     lock.lock(); 
     try { 
      responses.put(key, messagee); 
      containsKey.signalAll(); 
     } finally { 
      lock.unlock(); 
     } 
    } 

} 

これは、コントローラで使用することができます:

@RestController 
@RequestMapping("/request") 
public class RequestController { 

    @RequestMapping(method = RequestMethod.POST) 
    public Response postRequest(@RequestBody Request request) { 

     String data = request.getData(); 

     jmsSender.send(data); 

     String key = getKeyFromData(data); 
     // waits until MQ sends the data 
     String mqResponse = jmsReceiver.get(key); 

     if (mqIsValid(mqResponse)) { 
      return createValidResponse(); 
     } 
     return createNotValidResponse(); 
    } 
} 
1

以下のようにCountDownLatchを試してみてください。

@RestController 
@RequestMapping("/request") 
public class RequestController { 

    @RequestMapping(method = RequestMethod.POST) 
    public Response postRequest(@RequestBody Request request) { 
     final CountDownLatch jmsLatch = new CountDownLatch (1); 

     String data = request.getData(); 

     jmsSender.send(data, jmsLatch); 

     try { 
      latch.await(); // wait untill latch counted down to 0 
     } catch (InterruptedException e) { 
      return createNotValidResponse(); 
     } 

     return createValidResponse(); 
    } 
} 

コントローラからCountDownLatchを取得するためにsendメソッドを変更します。

@Service 
public class JmsSender { 

    public void send(String data, final CountDownLatch jmsLatch) { 
     jmsLatch.await(); 
     jmsTemplate.convertAndSend("QUEUE.TO.MQ", data); 
    } 

} 

受信メソッドを変更して、同じCountDownLatchをコントローラから取得します。

@Component 
public class JmsReceiver { 

    @JmsListener(destination = "QUEUE.FROM.MQ", containerFactory = "DefaultJmsListenerContainerFactory") 
    public void receiveMessage(String message, final CountDownLatch jmsLatch) { 
     // Pass the message to the controller 
     jmsLatch.countDown(); 
    } 

} 

ここのトリックは、あなたが送信者と受信者のクラスに、コントローラから同じたCountDownLatchインスタンスを広げて、あなたがメッセージを受信した後、カウントダウンメソッドを呼び出す必要があります。

+0

'CountDownLatch'を使う理由はありますか? 'Object#wait'や' Object#notify'や 'ReentrantLock'のようなモニタでも同じことをすることはできませんか?そして、MQから正しい回答を得るにはどうすればいいですか?たとえば2つの要求がMQに送信され、第1のMQ応答は第2の要求に対応する。 – deve

+0

私は、同様の種類のシナリオに直面したときに、 'CounDownLatch'を好んでいました。しかし、我々は待機/通知のアプローチに行く場合は、どのオブジェクト上で待機/通知を使用しますか? – Avinash

+0

2番目の質問では、値を取得する方法についてコードを書き留める必要があります。 – Avinash

関連する問題