OK... looking up their code tree a bit I see why it gets confused by the Qpid destination... because the Qpid AMQP 1.0 DestinationImpl implements both Queue and Topic... I'm not sure why it does that (probably a historical artefact). If I change that in Qpid, it might make ActiveMQ happier...
-- Rob On 19 February 2014 21:10, Rob Godfrey <rob.j.godf...@gmail.com> wrote: > Ah interesting... it's ActiveMQ code that is throwing the exception... As > per the JMS contract, the Qpid message producer is setting the > JMSDestination on the message it is sending (in this case a foreign > message, namely an ActiveMQ message). The ActiveMQ message class doesn't > seem to like having a destination set on it which isn't one that it can > resolve (even though it doesn't need to). The code in question appears to > be here in the activeMQ codebase: > > > http://grepcode.com/file/repo1.maven.org/maven2/org.apache.activemq/activemq-core/5.6.0/org/apache/activemq/command/DefaultUnresolvedDestinationTransformer.java > > It looks like ActiveMQ is requiring Queue and Topic implementations to > implement the methods isQueue() and/or isTopic()... but these are not part > of the API defined for JMS Queues and topics AFAIK (see > http://docs.oracle.com/javaee/6/api/javax/jms/Queue.html for example). > So I think that ActiveMQ is in error / violation of the JMS spec here > (though Robbie who has been reading the JMS spec carefully lately may be > able to give better advice). If ActiveMQ is absolutely determined to turn > the destination object into an ActiveMQ one, I'm not entirely sure why the > ActiveMQ code doesn't fall back to an instanceof test to determine whether > the the passed in Destination is a Queue (or if not a Topic)... > > -- Rob > > > On 19 February 2014 20:01, Mark Barker <mark.bar...@shaw.ca> wrote: > >> Hi Rob, >> >> Here is the stack trace. The line (72) in Listener.java (app code) that >> is failing is just: >> >> messageProducer2.send(msg); >> >> where messageProducer2 is a MessageProducer from the Qpid >> connection/session, >> and msg is just a "Message" which was received from Q1 just prior, via >> the Openwire transport (from its own connection/session). >> >> javax.jms.JMSException: Unresolvable destination: >> org.apache.qpid.amqp_1_0.jms.impl.QueueImpl.isQueue(): >> org.apache.qpid.amqp_1_0.jms.impl.QueueImpl@706254aa >> at >> org.apache.activemq.command.DefaultUnresolvedDestinationTransformer.transform(DefaultUnresolvedDestinationTransformer.java:48) >> at >> org.apache.activemq.command.ActiveMQDestination.transform(ActiveMQDestination.java:132) >> at >> org.apache.activemq.command.ActiveMQMessage.setJMSDestination(ActiveMQMessage.java:243) >> at >> org.apache.qpid.amqp_1_0.jms.impl.MessageProducerImpl.send(MessageProducerImpl.java:309) >> at >> org.apache.qpid.amqp_1_0.jms.impl.MessageProducerImpl.send(MessageProducerImpl.java:215) >> at Listener.main(Listener.java:72) >> >> Is this enough to tell you what's happening? >> >> If not, please let me know what else I can provide to understand this >> issue! >> I can include code. It's only for testing purposes anyway. >> >> Thanks, >> Mark. >> >> Sent from my iPhone >> >> > On Feb 19, 2014, at 1:51, Rob Godfrey <rob.j.godf...@gmail.com> wrote: >> > >> > Hi Mark, >> > >> >> On 19 February 2014 05:23, Mark Barker <mark.bar...@shaw.ca> wrote: >> >> >> >> Thanks again to Rob and Robbie for their answers thus far! >> >> >> >> So I managed to slap (i.e. Frankenstein) together two pieces of >> >> example/client code in order to attempt to facilitate a bridge of sorts >> >> between two disparate queues. >> >> >> >> For this test, I'm using an ActiveMQ broker with two client >> processes/JVMs >> >> (client1 and client2). >> >> The ActiveMQ broker is configured with 2 active protocols (transport >> >> connectors) - Openwire (standard) on port 61616, and AMQP (1.0) on port >> >> 5673 (only because I was experimenting previously with the Qpid broker >> on >> >> the more conventional port 5672) on the same box. >> >> >> >> client1 is a process based purely on an ActiveMQ Java/JMS openwire >> client >> >> (Publisher.java) example and its only purpose is to publish a >> TextMessage >> >> into Q1 via the openwire (tcp://) connection URL. >> >> >> >> client2 contains client code (and is linked/run with .jar libraries) >> for >> >> both ActiveMQ AND Qpid JMS (AMQP 1.0). Its intent is to read messages >> from >> >> Q1 (via ActiveMQ) and re-deliver them into Q2 (via AMQP). This >> situation is >> >> a little contrived to start with, as eventually Q2 may well be on a >> >> physically separate broker on a physically separate machine. >> >> >> >> So far, so good. I did some basic testing and proved my single client2 >> >> process can successfully (independently) interact with both queues (via >> >> both protocols). >> >> >> >> My issue is now this: >> >> If I receive a "TextMessage" in client2 using "consumer2" (a >> >> MessageConsumer for the ActiveMQ connection/session), this message >> >> object/entity ("msg") is not just something I can use (unaltered) to >> "send" >> >> via client2's "producer2" (a MessageProducer for the AMQP >> >> connection/session). Indeed, if I just try and "producer2.send(msg)", >> I get >> >> a Java exception at runtime. Something like: >> >> "javax.jms.JMSException: Unresolvable destination: >> >> org.apache.qpid.amqp_1_0.jms.impl.QueueImpl.isQueue(): >> >> org.apache.qpid.amqp_1_0.jms.impl.QueueImpl@e127d8ab" on the "send" >> call. >> >> >> >> I can only assume that this is because TextMessage has 2 separate >> >> implementations context-dependant on the protocol/client interface with >> >> which we are dealing. >> >> Some digging (printing out the .getClass() results) shows that the msg >> >> received is something like an >> org.apache.activemq.command.ActiveMQTextMessage, >> >> and the message needed to be sent is actually an >> >> org.apache.qpid.amqp_1_0.jms.impl.TestMessageImpl. >> >> >> >> If this is the case, what is the best way to solve this problem. >> >> If msg has a number of header and application-defined property >> attributes >> >> (never minding the body), how exactly is client2 supposed to >> copy/preserve >> >> them all across into a TextMessage object implementation suitable for >> >> delivery to Q2. Will client2 need to know the exact structure of the >> >> messages in order to deconstruct and reconstruct to satisfy the >> protocol >> >> bridging?? >> > >> > So, in general a JMS library should be able to send a valid JMS message >> > created or received from a different JMS provider... these are known as >> > "foreign" messages in JMS terms. The exception is that Destinations >> (such >> > as those found in the JMSReplyTo field) are provider specific. However >> if >> > you don't have a ReplyTo set in the incoming message then I don't >> believe >> > there should be any other issues as long as the messages are conformant >> > with the JMS specification (note that many providers may "extend" the >> JMS >> > specification to allow for non standard behaviours such as allowing map >> > messages to contain nested maps or lists... such messages cannot be >> > guaranteed to be resent without issue). >> > >> > Having said all of the above, I'm not sure that this is actually your >> > issue... the error you are seeing sounds more like it is to do with >> trying >> > to send to a queue which doesn't exist, however I can't find the error >> text >> > you pasted in the Qpid codebase anywhere... Would it be possible to >> paste >> > in the complete stack trace (or at least all the bits that are within >> the >> > qpid code if you want to remove any confidential parts from your own >> > program)? >> > >> > Thanks, >> > Rob >> > >> > >> >> As ever, any help with this would be hugely appreciated... >> >> Thanks in advance, >> >> Mark. >> >> >> >> >> >> -----Original Message----- From: Rob Godfrey >> >> Sent: Monday, February 17, 2014 5:54 PM >> >> >> >> To: users@qpid.apache.org >> >> Subject: Re: New User JMS API Questions >> >> >> >> On 18 February 2014 01:11, Mark Barker wrote: >> >> >> >> Robbie, >> >>> thanks again for your answers. >> >>> >> >>> As for your first suggestion: >> >>> >> >>> "connecting an ActiveMQ JMS client to the ActiveMQ >> >>> broker and a Qpid JMS client to the Qpid broker within the same JVM" >> >>> >> >>> Is this going to be possible in practice? I'm something of a novice at >> >>> Java too. Will there be some kind of conflict if trying to use both >> the >> >>> ActiveMQ JMS client and the Qpid JMS client APIs in the same process? >> How >> >>> would/could this be done (example build command)? Thus far I have been >> >>> building simple example code from the command line and referencing the >> >>> relevant .jar dependency in the classpath params for both javac >> (build) >> >>> and >> >>> java (runtime). >> >>> >> >>> >> >>> There shouldn't be an issue as long as there are no conflicts between >> the >> >> dependencies of the ActiveMQ client and the Qpid client. The Qpid >> clients >> >> aim to have as few dependencies as possible, so there really shouldn't >> be >> >> an issue. >> >> >> >> >> >> Finally, >> >>> today I've been looking at getting the simple Hello.java example >> running >> >>> on the ActiveMQ broker. >> >>> Obviously, this means I have to use a JMS AMQP 1.0 client, so I've >> been >> >>> using the Qpid JMS 1.0 client. >> >>> I've encountered some issues which seem to relate to the Connection >> URL >> >>> syntax from the JNDI (hello.properties) file. >> >>> >> >>> For instance, >> >>> in a previous Qpid client talking AMQP 0-10 with a Qpid broker, I >> used: >> >>> amqp://username:password@clientid >> /test?brokerlist='tcp://localhost:5672' >> >>> however I've read and seen in practice that this won't work with the >> 1.0 >> >>> client. >> >>> Instead I have to use something like: >> >>> amqp://username:password@localhost:5672 >> >>> >> >>> Can somebody please point me to the relevant documentation that >> explains >> >>> this difference in syntax. For all my digging on the Qpid website, I >> can >> >>> only find examples of the first/former (0-10 style), with no >> disclaimers >> >>> or >> >>> caveats regarding the 1.0 client. >> >>> >> >>> >> >>> No - there isn't a lot (or indeed really any) documentation around the >> >> AMQP >> >> 1.0 client. As you've noted the syntax is a little different from the >> 0-10 >> >> style... but you've pretty much got all of the syntax already. >> >> >> >> There are currently a number of options (set in the normal URI way: >> >> amqp://username:password@host:port?option1=value1&option2=value2...) >> to >> >> fine tune some AMQP settings. If you are interested you can look in >> the >> >> code which parses them here: >> >> >> >> https://svn.apache.org/viewvc/qpid/trunk/qpid/java/amqp-1-0- >> >> client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ >> >> ConnectionFactoryImpl.java?revision=1557982&view=markup&pathrev=1568703 >> >> >> >> Between lines 295 and 381 you will see the available options defined >> along >> >> with a brief description of their purpose. >> >> >> >> >> >> In addition, I've found I can use "queue://" or "topic://" prefixes in >> the >> >>> JNDI properties to specify the object type when using the generic >> >>> interface >> >>> (i.e. general instead of p2p/pub-sub). Is that syntax a feature of the >> >>> AMQP >> >>> protocol, or something specific to the Qpid client or ActiveMQ >> broker? I >> >>> can't find much mention of it anywhere. >> >>> >> >>> >> >>> That's something specific to the ActiveMQ broker. >> >> >> >> >> >> Thanks again for giving these questions your attention!! >> >>> >> >>> >> >>> >> >>> -- Rob >> >> >> >> >> >> >> >>> -----Original Message----- From: Robbie Gemmell >> >>> Sent: Saturday, February 15, 2014 2:57 PM >> >>> >> >>> To: users@qpid.apache.org >> >>> Subject: Re: New User JMS API Questions >> >>> >> >>> On 14 February 2014 04:55, Mark Barker wrote: >> >>> >> >>> If anyone has a tried this, or can confirm: >> >>> >> >>>> will it be possible to have a JMS client using an ActiveMQ broker on >> one >> >>>> machine (or maybe a producer/consumer pair), ultimately sending a >> message >> >>>> which then routes to a Qpid broker and associated local JMS consumer >> on a >> >>>> second machine (preserving all standard and application-specific JMS >> >>>> message headers/properties). Has this been done and are there further >> >>>> tricks, considerations and caveats here? >> >>>> Maybe the ActiveMQ JMS consumer process on the first machine makes >> the >> >>>> routing decision and then places the message via a producer instance >> for >> >>>> the Qpid broker on the 2nd machine? >> >>> It sounds like you are talking about bridging two brokers, which you >> >>> presumably do either by connecting an ActiveMQ JMS client to the >> ActiveMQ >> >>> broker and a Qpid JMS client to the Qpid broker within the same JVM, >> or by >> >>> using the Qpid AMQP 1.0 JMS client to connect to both brokers. >> >> >> > >