-
Notifications
You must be signed in to change notification settings - Fork 586

Description
In autogenerated com.rabbitmq.client.impl.AMQImpl.Close class, method writeArgumentsTo uses writeShortstr to write replyText:
public void writeArgumentsTo(MethodArgumentWriter writer)
throws IOException
{
writer.writeShort(this.replyCode);
writer.writeShortstr(this.replyText);
writer.writeShort(this.classId);
writer.writeShort(this.methodId);
}
Method writeShortstr throws IllegalArgumentException when argument has length more than 255 bytes.
StrictExceptionHandler.handleConsumerException form closeMessage as "Consumer " + consumer + " (" + consumerTag + ")" + " method " + methodName + " for channel " + channel
. When consumer class name is enough long, uncatched exceptions in hadleDelivery method will trigger close of channel, but close message won`t be sent to server and server will continue to send messages into the closed on client side channel.
Code to show the problem (slightly modified code from tutorial).
Consumer
import com.rabbitmq.client.*;
import java.io.IOException;
public class VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongClassName {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
final Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
System.out.println(" [x] Received '" + message + "'");
channel.basicReject(envelope.getDeliveryTag(), true);
throw new RuntimeException("Some exception");
}
};
channel.basicConsume(QUEUE_NAME, false, consumer);
}
}
Producer
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Send {
private final static String QUEUE_NAME = "hello";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8"));
System.out.println(" [x] Sent '" + message + "'");
channel.close();
connection.close();
}
}
After sending first message it is expected that channel is closed and queue contain one ready message. But channel is not closed and message in queue is in unacked state. Because server does not know that channel is closed, it continue to send new messages to this channel.
This example is not synthetical - i faced this problem in prouction with 90 symbols length full qualified class name (42 symbols for package name, 26 symbols class name and 20 symbols inner class name).