You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@qpid.apache.org by Jakub Scholz <ja...@scholz.cz> on 2010/07/01 20:25:32 UTC

Re: Problems with JMS API

Hi Rajith,

Sorry for the late answer, I was busy with different project. The
older API's work as expected - if I call query on exchange or queue, I
need the access right.- However, since on our system, we the client
expects,  that the exchanges exist and if they don't, then the client
anyway doesn't have the right to create them and he cannot use our
service (from my point of view, it doesn't really matter, whether he
gets an exception or whether he finds it out using exchange query).
Therefore, until know, we were able to develop client application
without the need of the access right for the exchanges. Therefore, I
believe it would be great to have the option to define in the address
string, that I'm sure that the node exists and that will force the API
to skip the queries on exchanges/queues.

I have also few other comments/questions to what I found so far:

1) The JMSReplyTo method is expecting JMS Destination as a parameter.
In the AMQMessageDelegate_0_10, the destination is converted to
AMQDestination, to get the exchange name and routing key. However, it
seems, that the destination needs to be initiated by creating
consumer/producer. When I passed a destination which was not used in
consumer / producer (even when the address was the same, only the
object was different), I got NullPointerException, because the
getExchangeName and getRoutingKey methods from AMQDestination return
null:

Code:
Destination response = (Destination) context.lookup("response");
Destination replyto = (Destination) context.lookup("replyto");

MessageConsumer messageConsumer = session.createConsumer(response);

TextMessage message = session.createTextMessage("Hello world!");
message.setJMSReplyTo(response); // works fine
message.setJMSReplyTo(replyto); // triggers the exception

Exception:

java.lang.NullPointerException
        at org.apache.qpid.client.message.AMQMessageDelegate_0_10.setJMSReplyTo(AMQMessageDelegate_0_10.java:251)
        at org.apache.qpid.client.message.AbstractJMSMessage.setJMSReplyTo(AbstractJMSMessage.java:138)
        at org.apache.qpid.example.jmsexample.hello.Hello.runTest(Hello.java:46)
        at jms.Client.main(Client.java:329)

Is it expected behavior that I cannot use every destination in
ReplyTo? I would expect, that I should be able to to every destination
I wan't, since I nay send a request which should be delivered to other
client application.

2) Our broker setup is using queues and exchanges with same names. I'm
trying to send an message to the exchange with specific routing key.
I'm using this Address: "service.CLIENT/CLIENT.ERS; { create: never
}". The API complains, that the object is ambiguous, because both
exchange and queue with the name "service.CLIENT" exist. Therefore, I
specify the node type to "topic" (because it is an exchange, not a
queue) by using a following address: "service.CLIENT/CLIENT.ERS; {
node: { type: topic }, create: never }". But, the service.CLIENT
exchange is direct, not topic. And therefore I'm getting following
exception:

org.apache.qpid.AMQException: The name 'service.CLIENT' supplied in
the address doesn't resolve to an exchange or a queue
        at org.apache.qpid.client.AMQSession_0_10.handleAddressBasedDestination(AMQSession_0_10.java:1194)
        at org.apache.qpid.client.BasicMessageProducer_0_10.declareDestination(BasicMessageProducer_0_10.java:81)
        at org.apache.qpid.client.BasicMessageProducer.<init>(BasicMessageProducer.java:141)
        at org.apache.qpid.client.BasicMessageProducer_0_10.<init>(BasicMessageProducer_0_10.java:60)
        at org.apache.qpid.client.AMQSession_0_10.createMessageProducer(AMQSession_0_10.java:633)
        at org.apache.qpid.client.AMQSession_0_10.createMessageProducer(AMQSession_0_10.java:82)
        at org.apache.qpid.client.AMQSession$6.execute(AMQSession.java:2369)
        at org.apache.qpid.client.AMQSession$6.execute(AMQSession.java:2364)
        at org.apache.qpid.client.AMQConnectionDelegate_0_10.executeRetrySupport(AMQConnectionDelegate_0_10.java:278)
        at org.apache.qpid.client.AMQConnection.executeRetrySupport(AMQConnection.java:765)
        at org.apache.qpid.client.failover.FailoverRetrySupport.execute(FailoverRetrySupport.java:102)
        at org.apache.qpid.client.AMQSession.createProducerImpl(AMQSession.java:2362)
        at org.apache.qpid.client.AMQSession.createProducerImpl(AMQSession.java:2356)
        at org.apache.qpid.client.AMQSession.createProducer(AMQSession.java:1046)
        at org.apache.qpid.client.AMQSession.createProducer(AMQSession.java:95)
        at org.apache.qpid.example.jmsexample.hello.Hello.runTest(Hello.java:30)
        at jms.Client.main(Client.java:329)

I traced this problem into the method isExchangeExist(...) of
AMQSession_0_10, where the exchange type is compared, and since my
exchange is direct and not topic, it returns that the exchange doesn't
exist. How can I send the message to direct exchange, when there is no
type "direct", but only "queue" and "topic"? When I bypass the
exchange type check on line 1056 of AMQSession_0_10, it works
perfectly fine.

3) I'm using this Address as the ReplyTo property:
"amq.direct/CLIENT_X.56789; {create: receiver, link : {name :
'service.tmp.CLIENT_X.123456_resp', x-declare : { auto-delete: true,
exclusive: true, 'qpid.max_size': 1000, 'qpid.policy_type': ring } }
}". My server application prepares an response and sends it back to
the replyTo address. When I receive the message and check the
JMSDestination, I can see following:

JMS Destination:
direct://amq.direct/CLIENT_X.56789/CLIENT_X.56789?routingkey='CLIENT_X.56789'

I would expect to see something like this (ie. the routing key is used ):

JMS Destination: direct://amq.direct/?routingkey='CLIENT_X.56789'

Nevertheless, the response is correctly delivered to amq.direct
exchange with routing key CLIENT_X.56789 and routed to the queue
service.tmp.CLIENT_X.123456_resp. I just noticed, that the destination
contains the desired routing key several times - may be it is correct
like this.

Thanks & Regards
Jakub

On Mon, Jun 28, 2010 at 16:14, Rajith Attapattu <ra...@gmail.com> wrote:
> On Mon, Jun 28, 2010 at 5:25 AM, Jakub Scholz <ja...@scholz.cz> wrote:
>> Hi Rajith,
>>
>> Thanks for the fix - the first three problems are working as expected
>> with latest trunk. I used following address when I found these
>> problems:
>
> Thanks for checking it out and letting me know.
>
>> amq.direct/CLIENT_X.56789; {create: receiver, link : {name :
>> 'service.tmp.CLIENT_X.123456_resp', x-declare : { auto-delete: true,
>> exclusive: true, 'qpid.max_size': 1000, 'qpid.policy_type': ring } } }
>>
> Thx !
>
>> Regarding the "access" right ... I believe in case it would be
>> necessary, we can add the "access" right to the ACL list. The C++ API
>> (version 0.5) and .NET API (version 0.6) are running successfully
>> against the same ACL setup as I'm running this JMS based application.
>
> Are you doing any explicit exchange queries and exchange binds ?
> If yes then the ACL should fail them. If thats not the case then it
> should be a bug and I'd appreciate any info you have on them.
>
>> But these older versions of course don't use the new addressing
>> scheme. From my point of view, it would be great to have a possibility
>> to bypass this querying functionality (for example by another option
>> in address). But I don't have enough knowledge about the APIs to know
>> whether it is possible or isn't.
>
> The new addressing scheme is common to all clients and we aim to have
> a consistent behaviour.
> When interpreting an address-string the client needs to figure out if
> it's an exchange or a queue if the node type is missing (for 0-10) and
> if it actually exists.
> So there will be an exchange and/or queue query. So those permissions
> are needed in the current ACL model.
> I guess your question is, whether we could turn off the querying for
> existence if the node type is present ?
>
>> Thanks & Regards
>> Jakub Scholz
>>

---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscribe@qpid.apache.org


Re: Problems with JMS API

Posted by Rajith Attapattu <ra...@gmail.com>.
On Thu, Jul 1, 2010 at 2:25 PM, Jakub Scholz <ja...@scholz.cz> wrote:
> Hi Rajith,
>
> Sorry for the late answer, I was busy with different project. The
> older API's work as expected - if I call query on exchange or queue, I
> need the access right.- However, since on our system, we the client
> expects,  that the exchanges exist and if they don't, then the client
> anyway doesn't have the right to create them and he cannot use our
> service (from my point of view, it doesn't really matter, whether he
> gets an exception or whether he finds it out using exchange query).
> Therefore, until know, we were able to develop client application
> without the need of the access right for the exchanges. Therefore, I
> believe it would be great to have the option to define in the address
> string, that I'm sure that the node exists and that will force the API
> to skip the queries on exchanges/queues.

The code will be changed as follows.
The client will always do a queue/exchange-declare with a passive=true
to assert the node exists.
If assert evaluates to true then an additional queue/exchange query
will be done to assert all properties.

So in your case you could avoid the exchange/queue query by having
assert=never (which is the default).

In your ACL you would need the following permissions. (Assuming you
are using deny mode)
acl allow all queue declare passive=true
acl allow all exchange declare passive=true

If you have any further questions, please feel free to ask.

> I have also few other comments/questions to what I found so far:
>
> 1) The JMSReplyTo method is expecting JMS Destination as a parameter.
> In the AMQMessageDelegate_0_10, the destination is converted to
> AMQDestination, to get the exchange name and routing key. However, it
> seems, that the destination needs to be initiated by creating
> consumer/producer. When I passed a destination which was not used in
> consumer / producer (even when the address was the same, only the
> object was different), I got NullPointerException, because the
> getExchangeName and getRoutingKey methods from AMQDestination return
> null:
>
> Code:
> Destination response = (Destination) context.lookup("response");
> Destination replyto = (Destination) context.lookup("replyto");
>
> MessageConsumer messageConsumer = session.createConsumer(response);
>
> TextMessage message = session.createTextMessage("Hello world!");
> message.setJMSReplyTo(response); // works fine
> message.setJMSReplyTo(replyto); // triggers the exception
>
> Exception:
>
> java.lang.NullPointerException
>        at org.apache.qpid.client.message.AMQMessageDelegate_0_10.setJMSReplyTo(AMQMessageDelegate_0_10.java:251)
>        at org.apache.qpid.client.message.AbstractJMSMessage.setJMSReplyTo(AbstractJMSMessage.java:138)
>        at org.apache.qpid.example.jmsexample.hello.Hello.runTest(Hello.java:46)
>        at jms.Client.main(Client.java:329)
>
> Is it expected behavior that I cannot use every destination in
> ReplyTo? I would expect, that I should be able to to every destination
> I wan't, since I nay send a request which should be delivered to other
> client application.

This is a bug - I will fix shortly.

> 2) Our broker setup is using queues and exchanges with same names. I'm
> trying to send an message to the exchange with specific routing key.
> I'm using this Address: "service.CLIENT/CLIENT.ERS; { create: never
> }". The API complains, that the object is ambiguous, because both
> exchange and queue with the name "service.CLIENT" exist. Therefore, I
> specify the node type to "topic" (because it is an exchange, not a
> queue) by using a following address: "service.CLIENT/CLIENT.ERS; {
> node: { type: topic }, create: never }". But, the service.CLIENT
> exchange is direct, not topic. And therefore I'm getting following
> exception:
>
> org.apache.qpid.AMQException: The name 'service.CLIENT' supplied in
> the address doesn't resolve to an exchange or a queue
>        at org.apache.qpid.client.AMQSession_0_10.handleAddressBasedDestination(AMQSession_0_10.java:1194)
>        at org.apache.qpid.client.BasicMessageProducer_0_10.declareDestination(BasicMessageProducer_0_10.java:81)
>        at org.apache.qpid.client.BasicMessageProducer.<init>(BasicMessageProducer.java:141)
>        at org.apache.qpid.client.BasicMessageProducer_0_10.<init>(BasicMessageProducer_0_10.java:60)
>        at org.apache.qpid.client.AMQSession_0_10.createMessageProducer(AMQSession_0_10.java:633)
>        at org.apache.qpid.client.AMQSession_0_10.createMessageProducer(AMQSession_0_10.java:82)
>        at org.apache.qpid.client.AMQSession$6.execute(AMQSession.java:2369)
>        at org.apache.qpid.client.AMQSession$6.execute(AMQSession.java:2364)
>        at org.apache.qpid.client.AMQConnectionDelegate_0_10.executeRetrySupport(AMQConnectionDelegate_0_10.java:278)
>        at org.apache.qpid.client.AMQConnection.executeRetrySupport(AMQConnection.java:765)
>        at org.apache.qpid.client.failover.FailoverRetrySupport.execute(FailoverRetrySupport.java:102)
>        at org.apache.qpid.client.AMQSession.createProducerImpl(AMQSession.java:2362)
>        at org.apache.qpid.client.AMQSession.createProducerImpl(AMQSession.java:2356)
>        at org.apache.qpid.client.AMQSession.createProducer(AMQSession.java:1046)
>        at org.apache.qpid.client.AMQSession.createProducer(AMQSession.java:95)
>        at org.apache.qpid.example.jmsexample.hello.Hello.runTest(Hello.java:30)
>        at jms.Client.main(Client.java:329)
>
> I traced this problem into the method isExchangeExist(...) of
> AMQSession_0_10, where the exchange type is compared, and since my
> exchange is direct and not topic, it returns that the exchange doesn't
> exist. How can I send the message to direct exchange, when there is no
> type "direct", but only "queue" and "topic"? When I bypass the
> exchange type check on line 1056 of AMQSession_0_10, it works
> perfectly fine.
>
Again another bug. - I will fix this as well.

> 3) I'm using this Address as the ReplyTo property:
> "amq.direct/CLIENT_X.56789; {create: receiver, link : {name :
> 'service.tmp.CLIENT_X.123456_resp', x-declare : { auto-delete: true,
> exclusive: true, 'qpid.max_size': 1000, 'qpid.policy_type': ring } }
> }". My server application prepares an response and sends it back to
> the replyTo address. When I receive the message and check the
> JMSDestination, I can see following:
>
> JMS Destination:
> direct://amq.direct/CLIENT_X.56789/CLIENT_X.56789?routingkey='CLIENT_X.56789'
>
> I would expect to see something like this (ie. the routing key is used ):
>
> JMS Destination: direct://amq.direct/?routingkey='CLIENT_X.56789'
>
> Nevertheless, the response is correctly delivered to amq.direct
> exchange with routing key CLIENT_X.56789 and routed to the queue
> service.tmp.CLIENT_X.123456_resp. I just noticed, that the destination
> contains the desired routing key several times - may be it is correct
> like this.

I need to find a way to get the toString method to print the
destination correctly.
Thanks again for the detailed explanations.

> Thanks & Regards
> Jakub
>
> On Mon, Jun 28, 2010 at 16:14, Rajith Attapattu <ra...@gmail.com> wrote:
>> On Mon, Jun 28, 2010 at 5:25 AM, Jakub Scholz <ja...@scholz.cz> wrote:
>>> Hi Rajith,
>>>
>>> Thanks for the fix - the first three problems are working as expected
>>> with latest trunk. I used following address when I found these
>>> problems:
>>
>> Thanks for checking it out and letting me know.
>>
>>> amq.direct/CLIENT_X.56789; {create: receiver, link : {name :
>>> 'service.tmp.CLIENT_X.123456_resp', x-declare : { auto-delete: true,
>>> exclusive: true, 'qpid.max_size': 1000, 'qpid.policy_type': ring } } }
>>>
>> Thx !
>>
>>> Regarding the "access" right ... I believe in case it would be
>>> necessary, we can add the "access" right to the ACL list. The C++ API
>>> (version 0.5) and .NET API (version 0.6) are running successfully
>>> against the same ACL setup as I'm running this JMS based application.
>>
>> Are you doing any explicit exchange queries and exchange binds ?
>> If yes then the ACL should fail them. If thats not the case then it
>> should be a bug and I'd appreciate any info you have on them.
>>
>>> But these older versions of course don't use the new addressing
>>> scheme. From my point of view, it would be great to have a possibility
>>> to bypass this querying functionality (for example by another option
>>> in address). But I don't have enough knowledge about the APIs to know
>>> whether it is possible or isn't.
>>
>> The new addressing scheme is common to all clients and we aim to have
>> a consistent behaviour.
>> When interpreting an address-string the client needs to figure out if
>> it's an exchange or a queue if the node type is missing (for 0-10) and
>> if it actually exists.
>> So there will be an exchange and/or queue query. So those permissions
>> are needed in the current ACL model.
>> I guess your question is, whether we could turn off the querying for
>> existence if the node type is present ?
>>
>>> Thanks & Regards
>>> Jakub Scholz
>>>
>



-- 
Regards,

Rajith Attapattu
Red Hat
http://rajith.2rlabs.com/

---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscribe@qpid.apache.org