sstone / amqp-client

[THIS PROJECT HAS BEEN ARCHIVED AND IS NO LONGER MAINTAINED] Simple fault-tolerant AMQP client written in Scala and based on Akka and the RabbitMQ java client
MIT License
161 stars 88 forks source link

header value when longer than 1024 bytes converted to java.io.DataInputStream #53

Closed durgadeep closed 10 years ago

durgadeep commented 10 years ago

Here is a sample usage -

When we read the messageHeaders by using the properties.getHeaders of Delivery class

val messageHeaders: collection.mutable.Map[String, AnyRef] = d.properties.getHeaders.asScala

( Where d == Delivery ( in package com.github.sstone.amqp ) )

When we get the class information - we always see the ClassName as com.rabbitmq.client.impl.LongStringHelper$ByteArrayLongString

But actually it is java.io.DataInputStream when we do a toString on this Value (We can see this).

To String == java.io.DataInputStream@7563a320

This is causing lots of issues as ByteArrayLongString is a private Inner class.

http://grepcode.com/file/repo1.maven.org/maven2/com.rabbitmq/amqp-client/3.2.3/com/rabbitmq/client/impl/LongStringHelper.java?av=f

ByteArrayLongString is an private static class

So the asInstanceOf won't work on the private member.

Also the reason we see the output as java.io.DataInputStream is because of this -

https://github.com/spring-projects/spring-amqp/blob/master/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/support/DefaultMessagePropertiesConverter.java#L149

where it converts any String longer than 1024 to java.io.DataInputStream

Thanks much _D

sstone commented 10 years ago

As much as possible, pleasy specify which version of the library you are using what you are doing, what you expect, what you actually get and why it's wrong.

In this case, I suppose that you are trying to send/receive large AMQP headers and it does not work. It does work for me, with this simple test: https://gist.github.com/sstone/057653158646dd7d3ff4 => I suspect that the problem is linked to the Spring library that you are using. Is it on the producer or consumer side (consumer I guess) ? I don't know much about Spring AMQP but couldn't you just read from the stream that you get in the header properties ?

durgadeep commented 10 years ago

We're using this version of sstone -

val amqpClient = "com.github.sstone" % "amqp-client_2.10" % "1.3" withSources

Yes it's on the consumer Side, one of the key has a value that is converted to a DataInputStream, but getClassName always gives that it's an instance of com.rabbitmq.client.impl.LongStringHelper$ByteArrayLongString

Here is our Code Snippet -

val messageHeaders: collection.mutable.Map[String, AnyRef] = d.properties.getHeaders.asScala
val messageBody = new String(d.body)

val headers: scala.collection.mutable.Map[String, String] = new scala.collection.mutable.HashMap[String, String] ()
for (name <- messageHeaders.keySet.toArray.toSeq)
yield {
  val headerValue = messageHeaders.get(name).flatMap(Option(_))
  if (headerValue.isDefined) {
    headers.put(name, headerValue.get.toString)
  }
}
sstone commented 10 years ago

How do you receive messages ? Can you post a simple snippet for this too ? Thanks

sstone commented 10 years ago

No news is good news... So I suppose you've found and fixed the pb (which I believe was not in my library).