Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 2.0
    • Fix Version/s: None
    • Labels:
      None

      Description

      Logged on behalf of Philippe Marschall, who posted this to the community alias:
      https://java.net/projects/jms-spec/lists/users/archive/2013-12/message/16

      Since it's time to gather ideas for JMS 2.1 I thought I'd mention this early. I noted that #getBody does not have any conversions defined for StreamMessage. IMHO it would be really convenient if the following conversions where offered:

      • java.io.InputStream (if the message is not in write-only mode)
      • java.io.OutputStream (if the message is not in read-only mode)
      • java.io.Reader (if the message is not in write-only mode)
      • java.io.Writer (if the message is not in read-only mode)

      This would also make it very easy to plug StreamMessage into anything else that does stream oriented IO in Java.

      Obviously #isBodyAssignableTo(Class) would have to be updated as well.

        Activity

        Hide
        braghest added a comment -

        To explain our problem a bit. We currently use JSR 353 (JSONP) to parse JSON we receive over JMS. JSR 353 is a streaming API and operates on the standard InputStream and Reader classes. Since{{StreamMessage}} does not offer adapters for these classes combining these two JavaEE technologies is more work than strictly necessary.

        The proposal would not add any new methods to StreamMessage, it would do it all through the #getBody method.

        I don't think ObjectInputStream and ObjectOutputStream are a good match since they are intended for Java Serialization.

        I used "conversions" but meant type adapters.

        The proposal would not force an implementor to use a stream internally or expose the underlying stream. See the class below on how such a stream could be provided with the current implementation. It is a bit inefficient since no bulk reading methods are provided. A similar solution could be come up for input stream.

        public final class StreamMessageReader extends Reader {
          
          private final StreamMessage streamMessage;
        
          public StreamMessageReader(StreamMessage streamMessage) {
            this.streamMessage = streamMessage;
          }
        
          @Override
          public int read(char[] cbuf, int off, int len) throws IOException {
            int i = 0;
            try {
              char c = this.streamMessage.readChar();
              while (i < len) {
                cbuf[i + off] = c;
                i += 1;
                c = this.streamMessage.readChar();
              }
            } catch (MessageEOFException e) {
              return i;
            } catch (JMSException e) {
              throw new IOException("read failed", e);
            }
            return i;
          }
          
          @Override
          public int read() throws IOException {
            try {
              return this.streamMessage.readChar();
            } catch (MessageEOFException e) {
              return -1;
            } catch (JMSException e) {
              throw new IOException("read failed", e);
            }
          }
          
          @Override
          public void reset() throws IOException {
            try {
              this.streamMessage.reset();
            } catch (JMSException e) {
              throw new IOException("reset failed", e);
            }
          }
        
          @Override
          public void close() throws IOException {
            // ignore
          }
        
        }
        
        Show
        braghest added a comment - To explain our problem a bit. We currently use JSR 353 (JSONP) to parse JSON we receive over JMS. JSR 353 is a streaming API and operates on the standard InputStream and Reader classes. Since{{StreamMessage}} does not offer adapters for these classes combining these two JavaEE technologies is more work than strictly necessary. The proposal would not add any new methods to StreamMessage , it would do it all through the #getBody method. I don't think ObjectInputStream and ObjectOutputStream are a good match since they are intended for Java Serialization. I used "conversions" but meant type adapters. The proposal would not force an implementor to use a stream internally or expose the underlying stream. See the class below on how such a stream could be provided with the current implementation. It is a bit inefficient since no bulk reading methods are provided. A similar solution could be come up for input stream. public final class StreamMessageReader extends Reader { private final StreamMessage streamMessage; public StreamMessageReader(StreamMessage streamMessage) { this .streamMessage = streamMessage; } @Override public int read( char [] cbuf, int off, int len) throws IOException { int i = 0; try { char c = this .streamMessage.readChar(); while (i < len) { cbuf[i + off] = c; i += 1; c = this .streamMessage.readChar(); } } catch (MessageEOFException e) { return i; } catch (JMSException e) { throw new IOException( "read failed" , e); } return i; } @Override public int read() throws IOException { try { return this .streamMessage.readChar(); } catch (MessageEOFException e) { return -1; } catch (JMSException e) { throw new IOException( "read failed" , e); } } @Override public void reset() throws IOException { try { this .streamMessage.reset(); } catch (JMSException e) { throw new IOException( "reset failed" , e); } } @Override public void close() throws IOException { // ignore } }
        Hide
        Nigel Deakin added a comment - - edited

        This proposal doesn't simply provide a simpler alternative to existing API, it adds new functionality to StreamMessage. StreamMessage doesn't currently have methods to return objects of any of these four types, so the first thing to consider is whether we would want to add four new methods to StreamMessage to return an InputStream, OutputStream, Reader and Writer.

        The StreamMessage object has methods which make it look like a stream, but it doesn't actually have any methods to return the stream directly. This was probably deliberate as it didn't force the implementer to use a stream internally. We need to consider carefully whether exposing the underlying stream (or perhaps forcing the implementation to create one if it doesn't use one internally) might cause problems for implementers.

        The classes Reader and Writer are for character streams only, whereas a StreamMessage can hold a stream of different object types. I'm not sure that's a good match.

        As for InputStream or OutputStream: I wonder whether returning an ObjectInputStream or ObjectOutputStream would be more appropriate, since these stream types, like StreamMessage, have specific methods to read and write various primitives such as boolean or long rather than simply bytes. However the methods it allows are not identical to the methods on StreamMessage (e.g. StreamMessage defines its own rules on type conversion). I wonder whether the differences would cause difficulties.

        You use the word "conversions". Currently #getBody doesn't perform type conversions. There is currently a one-to-one mapping between the message type and the class that must be passed in. For example you can't use call getBody(byte[].class) on a TextMessage to obtain the text string as an array of bytes. But if we allow the body of a StreamMessage to be returned as (say) a OutputStream, do we also need to allow the same for other message types such as BytesMessage or TextMessage?

        Show
        Nigel Deakin added a comment - - edited This proposal doesn't simply provide a simpler alternative to existing API, it adds new functionality to StreamMessage . StreamMessage doesn't currently have methods to return objects of any of these four types, so the first thing to consider is whether we would want to add four new methods to StreamMessage to return an InputStream , OutputStream , Reader and Writer . The StreamMessage object has methods which make it look like a stream, but it doesn't actually have any methods to return the stream directly. This was probably deliberate as it didn't force the implementer to use a stream internally. We need to consider carefully whether exposing the underlying stream (or perhaps forcing the implementation to create one if it doesn't use one internally) might cause problems for implementers. The classes Reader and Writer are for character streams only, whereas a StreamMessage can hold a stream of different object types. I'm not sure that's a good match. As for InputStream or OutputStream : I wonder whether returning an ObjectInputStream or ObjectOutputStream would be more appropriate, since these stream types, like StreamMessage , have specific methods to read and write various primitives such as boolean or long rather than simply bytes. However the methods it allows are not identical to the methods on StreamMessage (e.g. StreamMessage defines its own rules on type conversion). I wonder whether the differences would cause difficulties. You use the word "conversions". Currently #getBody doesn't perform type conversions. There is currently a one-to-one mapping between the message type and the class that must be passed in. For example you can't use call getBody(byte[].class) on a TextMessage to obtain the text string as an array of bytes. But if we allow the body of a StreamMessage to be returned as (say) a OutputStream , do we also need to allow the same for other message types such as BytesMessage or TextMessage ?

          People

          • Assignee:
            Unassigned
            Reporter:
            Nigel Deakin
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated: