これが私のコードスニペットです。
構成用のMQConfiguration
クラス
_@Configuration
public class MQConfiguration {
@Bean
public Receiver receiver() {
return new Receiver();
}
}
_
Receiver
メッセージの受信を処理するためのクラス
_@RabbitListener(queues = "testMQ")
public class Receiver {
@RabbitHandler
public void receive(Message msg){
System.out.println(msg.toString());
}
}
_
そして、これが私がRabbitMQに送信したJSONメッセージです。
_{
"id": 1,
"name": "My Name",
"description": "This is description about me"
}
_
ただし、アプリケーションを実行すると、次のエラーメッセージが表示されました。
_2017-02-28 17:16:35.931 WARN 11828 --- [cTaskExecutor-1] s.a.r.l.ConditionalRejectingErrorHandler : Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener threw exception
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.wrapToListenerExecutionFailedExceptionIfNeeded(AbstractMessageListenerContainer.Java:872) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.Java:782) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.Java:702) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$001(SimpleMessageListenerContainer.Java:95) [spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$1.invokeListener(SimpleMessageListenerContainer.Java:186) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.invokeListener(SimpleMessageListenerContainer.Java:1227) [spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.Java:683) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.Java:1181) [spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.Java:1165) [spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1500(SimpleMessageListenerContainer.Java:95) [spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.Java:1367) [spring-rabbit-1.7.0.RELEASE.jar:na]
at Java.lang.Thread.run(Thread.Java:745) [na:1.8.0_60]
Caused by: org.springframework.amqp.AmqpException: No method found for class [B
at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.getHandlerForPayload(DelegatingInvocableHandler.Java:127) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.adapter.DelegatingInvocableHandler.getMethodNameFor(DelegatingInvocableHandler.Java:224) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.getMethodAsString(HandlerAdapter.Java:61) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.Java:140) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.Java:106) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.Java:779) ~[spring-rabbit-1.7.0.RELEASE.jar:na]
... 10 common frames omitted
_
では、JSONメッセージをreceive()
メソッドで出力するだけの場合はどうすればよいですか?誰もがこれに光を当てることができることを本当に感謝しています。 :)
Spring Bootを使用する場合は、以下を構成する必要があります。
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
それ以外の場合は、以下を構成する必要があります。
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
...
factory.setMessageConverter(new Jackson2JsonMessageConverter());
...
return factory;
}
JSONをRabbitMQに送信し、Spring Bootで使用するには、content_type
を設定する必要があります。
PythonプロデューサーとJavaコンシューマー(Python RabbitMQとSpringBootへJavaはJSONタスクを受け取ることになっていた)。
2つの解決策があります:
解決策1:JSON文字列として送信し、JaksonまたはGSONを使用して手動で変換します
Content_type = "text/plain"を設定し、JSONを文字列に変換する必要があります。次に、Spring側で、リスナーとして入力として文字列を使用する関数を使用し、オブジェクトを手動で変換します。
RabbitHandler:
@RabbitHandler
public void receive(String inputString) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
SimStatusReport theResult = objectMapper.readValue(inputString, SimStatusReport.class);
System.out.println("String instance " + theResult.toString() +
" [x] Received");
}
SimStatusReportオブジェクト:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SimStatusReport {
private String id;
private int t;
}
これが私のPythonコード:
import pika
import json
import uuid
connectionResult = pika.BlockingConnection(pika.ConnectionParameters(Host='localhost'))
channelResult = connectionResult.channel()
routing_key_result = 'sim_results'
channelResult.queue_declare(queue=routing_key_result, durable=True)
def publish_result(sim_status):
message =json.dumps(sim_status)
channelResult.basic_publish(exchange='',
routing_key=routing_key_result,
body=message,
properties=pika.BasicProperties(
content_type="text/plain",
content_encoding= 'UTF-8',
delivery_mode=2, # make message persistent
))
print("Sent ", message)
newsim_status = {'id': str(uuid.uuid4()), 't': 0}
publish_result(newsim_status)
解決策2:JSON文字列を送信し、Jackson2JsonMessageConverterに自動的に変換を実行させます。
Content_type = "application/json"を設定する必要があります。次に、RabbitMQリクエストのヘッダーの__TypeId__
に適切なヘッダーを追加する必要があります。ジャクソンが変換を理解できないように、オブジェクトの正確な名前空間を含める必要があります。
Python(publish_result関数のみ)を使用した私の例を次に示します。
def publish_result(sim_status):
message =json.dumps(sim_status)
channelResult.basic_publish(exchange='',
routing_key=routing_key_result,
body=message,
properties=pika.BasicProperties(
content_type="application/json"
headers={'__TypeId__': 'com.zarinbal.simtest.run.model.SimStatusReport'},
content_encoding= 'UTF-8',
delivery_mode=2, # make message persistent
))
print("Sent ", message)
次に、Jackson2JsonMessageConverterを使用するようにJavaを構成する必要があります:
@Configuration
public class RabbitConfiguration {
@Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
}
これがあなたのリスナーです:
@RabbitListener(queues = "sim_results")
public class TaskReceiver {
@RabbitHandler
public void receive(SimStatusReport in) {
System.out.println("Object instance " + in +
" [x] Received");
}
}
注:すべてのオブジェクトにすべてのプロパティとすべての引数コンストラクターのセッターとゲッターがあることを確認してください。 lombokの@ Data、@ NoArgsConstructor、@ AllArgsConstructorを使用して、自動的に生成します
簡単な方法で、この関数を使用できますnew String(Messages)
@RabbitListener(queues = "testMQ")
public class Receiver {
@RabbitHandler
public void receive(Message msg){
String MQMessage = new String(msg.getBody());
System.out.println(MQMessage);
}
}