-
15. Re: Jwokkkyeob Qin Xi hydrogen
timfox Apr 9, 2010 11:24 AM (in response to timfox)A String in java is simply an array of java characters which are 16 bit values.
They map to displayable characters according to the unicode specification. Not all 16 bit values have displayable characters, nevertheless they are *still valid Java characters*.
The only requirement for a JMSMessageID is it is the string "ID:" prepended with a Java string.
-
16. Re: Jwokkkyeob Qin Xi hydrogen
clebert.suconic Apr 9, 2010 11:26 AM (in response to jmesnil)Jeff Mesnil wrote:
Tim Fox wrote:
In what sense is the string not valid? Just because you can't display all the chars doesn't make it invalid.
If the chars can not be displayed, the JMSMessage ID is useless. How is the user supposed to make the difference between ID:??????B? and ID:??????B? ?
With such IDs, user can not use ID in management API, in correlation ID, etc.
+1
-
17. Re: Jwokkkyeob Qin Xi hydrogen
timfox Apr 9, 2010 11:28 AM (in response to jmesnil)Jeff Mesnil wrote:
Why dealing with bytes and not use simply:
String uid = UUIDGenerator.getInstance().generateUUID().toString();
msg.getCoreMessage().setUserID(new SimpleString("ID:" + uid));
wdyt?
That's what we used to do.
The problem is the length of String generated in that way is about 3 times as long --> which means small messages can be 3 times as long, which can make a huge difference in performance.
-
18. Re: Jwokkkyeob Qin Xi hydrogen
jmesnil Apr 9, 2010 11:29 AM (in response to timfox)I don't say it is not a valid String, I say it is useless if the String can not properly displayed.
When I debug, I look at the JMS Message IDS to correlate things on the client and the server. Having undisplayable ID (i.e. different IDs which display ID:???????) will make this a PITA.
-
19. Re: Jwokkkyeob Qin Xi hydrogen
timfox Apr 9, 2010 11:38 AM (in response to jmesnil)Jeff Mesnil wrote:
Tim Fox wrote:
In what sense is the string not valid? Just because you can't display all the chars doesn't make it invalid.
If the chars can not be displayed, the JMSMessage ID is useless. How is the user supposed to make the difference between ID:??????B? and ID:??????B? ?
With such IDs, user can not use ID in management API, in correlation ID, etc.
That's not true.
Even if chars are not displayable to a particular user, then string operations like equals(), concat() etc all work fine. The computer still can "see" all the characters, so these should all work fine.
The only thing you can't do, is as a human, write down all the chars and manually use that.
-
20. Re: Jwokkkyeob Qin Xi hydrogen
clebert.suconic Apr 9, 2010 11:42 AM (in response to timfox)It still a PITA though.
-
21. Re: Jwokkkyeob Qin Xi hydrogen
jmesnil Apr 9, 2010 11:47 AM (in response to timfox)imagine a user using the admin console. he wants to remove a message corresponding to a given ID. He won't be able to copy/paste the ID.
It seems we sacrifice usability for performance here. If the user wants perf, let him disable message ID completely.
-
22. Re: Jwokkkyeob Qin Xi hydrogen
timfox Apr 9, 2010 11:59 AM (in response to jmesnil)Jeff Mesnil wrote:
imagine a user using the admin console. he wants to remove a message corresponding to a given ID. He won't be able to copy/paste the ID.
JMSMessageID's should not be used in the management API for doing stuff like deleting messages, this is because not all JMS message ids have message ids (JMS message id generation can be disabled by the client), and we need to be able to delete/manage all messages.
The core id should always be used to identify any messages via the management api.
-
23. Re: Jwokkkyeob Qin Xi hydrogen
leosbitto Apr 9, 2010 5:48 PM (in response to timfox)Tim Fox wrote:
The problem is the length of String generated in that way is about 3 times as long --> which means small messages can be 3 times as long, which can make a huge difference in performance.
I guess that you care about the size of the String only for the transport between the client and the server. So why not make the change after the message is transferred, at the client? This is the current implementation in hornetq-2.0.0.GA in src/src/main/org/hornetq/jms/client/HornetQMessage.java:
public String getJMSMessageID(){if (msgID == null){SimpleString id = message.getSimpleStringProperty(HornetQMessage.HORNETQ_MESSAGE_ID);msgID = id == null ? null : id.toString();}return msgID;}This is my proposed change, intentionally incomplete to leave some work for the hopefully interested readers:
public String getJMSMessageID(){if (msgID == null){msgID = createBeautifiedJMSMessageID(message.getSimpleStringProperty(HornetQMessage.HORNETQ_MESSAGE_ID));}return msgID;}private static String createBeautifiedJMSMessageID(SimpleString uglyMessageID){if (uglyMessageID == null) return null;// TODO some coding here}public void setJMSMessageID(final String jmsMessageID) throws JMSException{// something needs to be changed here, too} -
24. Re: Jwokkkyeob Qin Xi hydrogen
leosbitto Apr 9, 2010 6:49 PM (in response to leosbitto)public void setJMSMessageID(final String jmsMessageID) throws JMSException{// something needs to be changed here, too}Actually it seems that there is no reason why setJMSMessageID should propagate the new jmsMessageID to the core message, so the change is pretty easy:
public void setJMSMessageID(final String jmsMessageID) throws JMSException{if (jmsMessageID != null && !jmsMessageID.startsWith("ID:")){throw new JMSException("JMSMessageID must start with ID:");}// if (jmsMessageID == null)// {// message.removeProperty(HornetQMessage.HORNETQ_MESSAGE_ID);// }// else// {// message.putStringProperty(HornetQMessage.HORNETQ_MESSAGE_ID, new SimpleString(jmsMessageID));// }msgID = jmsMessageID;}As a bonus, you can get rid of the weird public method resetMessageID and change the code in HornetQMessageProducer.doSend from the current:
if (!disableMessageID)
{
// Generate an id
SimpleString msgID = generateMessageID();
msg.getCoreMessage().putStringProperty(HornetQMessage.HORNETQ_MESSAGE_ID, msgID);
msg.resetMessageID(msgID.toString());
}
to new:
if (!disableMessageID)
{
// Generate an id - what a great comment for calling the method named generateMessageID ;-)
msg.getCoreMessage().putStringProperty(HornetQMessage.HORNETQ_MESSAGE_ID, generateMessageID());
msg.setJMSMessageID(null); // initialize lazily in getJMSMessageID()
}
-
25. Re: Jwokkkyeob Qin Xi hydrogen
leosbitto Apr 9, 2010 7:11 PM (in response to leosbitto)if (!disableMessageID)
{
// Generate an id - what a great comment for calling the method named generateMessageID ;-)
msg.getCoreMessage().putStringProperty(HornetQMessage.HORNETQ_MESSAGE_ID, generateMessageID());
msg.setJMSMessageID(null); // initialize lazily in getJMSMessageID()
}
D'oh! Typing faster than thinking... Here is corrected version which makes msg.setJMSMessageID(null) work as expected:
if (!disableMessageID)
{
msg.getCoreMessage().putStringProperty(HornetQMessage.HORNETQ_MESSAGE_ID, generateMessageID());
msg.resetJMSMessageID();
}
and in HornetQMessage:
public void resetJMSMessageID()
{
msgId = null;
}
public void setJMSMessageID(final String jmsMessageID) throws JMSException{if (jmsMessageID == null){message.removeProperty(HornetQMessage.HORNETQ_MESSAGE_ID);}else if (!jmsMessageID.startsWith("ID:")){throw new JMSException("JMSMessageID must start with ID:");}msgID = jmsMessageID;} -
26. Re: Jwokkkyeob Qin Xi hydrogen
timfox Apr 10, 2010 7:29 AM (in response to leosbitto)Leos Bitto wrote:
I guess that you care about the size of the String only for the transport between the client and the server. So why not make the change after the message is transferred, at the client?
No, the actual JMS message id as seen by a JMS client must also be in the message at the server, since it can be used in selector expressions, and by several management API operations
-
27. Re: Jwokkkyeob Qin Xi hydrogen
leosbitto Apr 10, 2010 10:37 AM (in response to timfox)Tim Fox wrote:
Leos Bitto wrote:
I guess that you care about the size of the String only for the transport between the client and the server. So why not make the change after the message is transferred, at the client?
No, the actual JMS message id as seen by a JMS client must also be in the message at the server, since it can be used in selector expressions, and by several management API operations
Sure, I forgot about the selectors. I do not use them, because they are usually very inefficient. However, why not use the same transformation of JMSMessageID at the server side, if there would be a selector with JMSMessageID (which seems to be an extremely rare use-case anyway)? For the management API - would it be possible to use the core id instead? Or again to use the same transformation of JMSMessageID?
-
28. Re: Jwokkkyeob Qin Xi hydrogen
timfox Apr 10, 2010 10:45 AM (in response to leosbitto)Yeah, I considered this too.
Basically a UID is 128 bits (two longs), we could pass that in the core message, and do the transformation lazily as you suggest.
Problem is it gets very fiddly, since we'd have to do some awkward changes to the filter implementation to treat JMSMessageID as a special case. It's not trivial.
But perhaps we should revisit it.
I do accept that having non displayable JMSMessageID is not great.
-
29. Re: Jwokkkyeob Qin Xi hydrogen
leosbitto Apr 10, 2010 1:03 PM (in response to timfox)Tim Fox wrote:
Basically a UID is 128 bits (two longs), we could pass that in the core message, and do the transformation lazily as you suggest.
Problem is it gets very fiddly, since we'd have to do some awkward changes to the filter implementation to treat JMSMessageID as a special case. It's not trivial.
I don't think that it is trivial, but I don't think that is should get very fiddly as well. I could contribute the modifications to the code in org.hornetq.jms.client.SelectorTranslator.convertToHornetQFilterString to translate the values of JMSMessageID from the readable JMS client representation to the efficient core representation, if you would like...