我有一个REST服务,它接收一些数据并通过异步IBM请求检查数据。
休息控制器:
@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接收器:
@Component
public class JmsReceiver {
@JmsListener(destination = "QUEUE.FROM.MQ, containerFactory = "DefaultJmsListenerContainerFactory")
public void receiveMessage(String message) {
// How to pass the message to the controller?
}
}
如何等待来自MQ的正确数据在控制器中创建正确的响应?
是否可以像描述的BlockingQueue
那样使用这里?在我的例子中,我必须区分数据。我不能只从阻塞队列中获取第一个数据。
例如,如果同时有两个REST请求(带有数据:abc
和xyz
)。我如何确保响应正确的答案,而不仅仅是从MQ获得的第一个答案?
我也不能更改MQ接口。
发布于 2017-01-09 12:34:35
因为我找不到合适的解决方案,所以我创建了一个简单的等待机制来获取数据。
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();
}
}
发布于 2017-01-06 18:42:51
尝试使用如下所示的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。
@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实例从控制器扩展到发送方和接收方类,并在收到消息后调用countDown方法。
https://stackoverflow.com/questions/41507982
复制相似问题