Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4267294

InputStream must be created in getInputStream() of the DataSource, not passed in

XMLWordPrintable

    • Icon: Enhancement Enhancement
    • Resolution: Fixed
    • Icon: P4 P4
    • 1.0.1fcs
    • 1.0.1fcs
    • other-libs
    • 1.0.1fcs
    • generic
    • generic
    • Verified



      Name: sg39081 Date: 08/31/99


      Create a multipart mail message comprising a text
      part and a pdf stream part. If the InputStream
      is created in one object and passed into the
      DataSource, it throws an exception trying to
      read the InputStream.

      If the InputStream is created in the DataSource,
      the InputStream can be read fine.

      This is probably really more of a documentation issue.

      I have wrapped the basic javamail classes with my own EmailMessage class to
      hide all of the implementation details from our programmers. I've given
      them the following method for adding attachments of any type to the message.

      addAttachment(String contentType, InputStream in)

      Because I don't know what type of InputStream that can be passed in, I can't
      use any of the provided DataSource implementation classes (e.g.
      java.activation.FileDataSource). So I have implemented my own class and
      passed the contentType and InputStream object in the constructor:

      The folowing is an example to demonstrate the problem.

      public class MyDataSource implements java.activation.DataSource {
      private String contentType ;
      private InputStream in ;

      // constructor
      public MyDataSource(String contentType, InputStream in) {
      this.contentType = contentType ;
      this.in = in ;
      }

      ...
      // part of the DataHandler interface
      public InputStream getInputStream( ) {
      return in ;
      }
      }

      I would have liked just to return the InputStream in the
      getInputStreamMethod() like in the above, but in the course of executing the
      sendMessage( ) method, it calls getInputStream( ) twice. The stream is
      already consumed when the second getInputStream() is executed. So I'm
      forced to write the stream to a temporary file (because it may not fit in a
      memory resident ByteArrayInputStream), and return a new InputStream object
      each time.

      My question is, why does it call the getInputStream( ) method twice? Is it
      to get the length first?

      It took me quite a while to find the problem. Maybe some documentation
      could be added to the javadoc somewhere.




      Here's the code:

      try {
         Properties props = new Properties() ;
         props.put("mail.smtp.host", myHost) ;
         javax.mail.Session mailSession = javax.mail.Session.getDefaultInstance(props, null) ;

         mailSession.setDebug(true) ;
         MimeMessage msg = new MimeMessage(mailSession) ;
         InternetAddress from = new InternetAddress("###@###.###") ;
         InternetAddress to = new InternetAddress("###@###.###") ;

         msg.setFrom(from) ;
         InternetAddress[] addr = {to} ;
         msg.setRecipients(Message.RecipientType.TO, addr) ;
         msg.setSubject("Test Message") ;
         msg.setSentDate(new Date()) ;
         msg.setHeader("X-Mailer", "msgsend") ;

         //createMessage(msg) ;
         MimeBodyPart mbp1 = new MimeBodyPart() ;
         mbp1.setText("Text part") ;
         MimeBodyPart mbp2 = new MimeBodyPart() ;

         InputStream pdf = new FileInputStream("myfile.pdf") ;
         DataSource mailds = new PdfDataSource(pdf) ;

         mbp2.setDataHandler(new DataHandler(mailds)) ;
         Multipart mp = new MimeMultipart() ;
         mp.addBodyPart(mbp1) ;
         mp.addBodyPart(mbp2) ;
         msg.setContent(mp) ;
         Transport.send(msg) ;

      }

      // Here's the PdfDataSource class
      class PdfDataSource implements DataSource {
      private InputStream pdf = null ;

         // Constructor - passes in the InputStream
         PdfDataSource(InputStream pdf) {
            this.pdf = pdf ;
         }

         // Implement the DataSource interface
         public InputStream getInputStream() throws IOException {
             //If you create the pdf stream here with
             // the code below, the message is sent
             // correctly, with the pdf attachment
             //return new FileInputStream("myfile.pdf") ;

            // Using the passed in InputStream here
            // yields an empty PDF file
            return pdf ;
         }

         public OutputStream getOutputStream() throws IOException {
            throw new IOException("Can't do this") ;
         }

         public String getContentType() {
            return "application/pdf" ;
         }

         public String getName() {
            return "PDFDataSource" ;
         }
      }


      Here's the stacktrace from the exception:
      java.io.IOException: read error
              at java.io.FileInputStream.read(FileInputStream.java:148)
              at javax.activation.DataHandler.writeTo(Compiled Code)
              at javax.mail.internet.MimeBodyPart.writeTo(Compiled Code)
              at javax.mail.internet.MimeBodyPart.writeTo(Compiled Code)
              at javax.mail.internet.MimeMultipart.writeTo(Compiled Code)
              at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:78
      )
              at javax.activation.ObjectDataContentHandler.writeTo(Compiled Code)
              at javax.activation.DataHandler.writeTo(Compiled Code)
              at javax.mail.internet.MimeBodyPart.writeTo(Compiled Code)
              at javax.mail.internet.MimeMessage.writeTo(Compiled Code)
              at com.sun.mail.smtp.SMTPTransport.sendMessage(Compiled Code)
              at javax.mail.Transport.send0(Compiled Code)
              at javax.mail.Transport.send(Transport.java:73)
              at MailTest.main(MailTest.java:45)
      javax.mail.SendFailedException: Sending failed;
        nested exception is:
              javax.mail.MessagingException: IOException while sending message;
        nested exception is:
              java.io.IOException: read error
              at java.lang.Throwable.<init>(Compiled Code)
              at javax.mail.Transport.send0(Compiled Code)
              at javax.mail.Transport.send(Transport.java:73)
              at MailTest.main(MailTest.java:45)
      (Review ID: 43632)
      ======================================================================

            bshannon Bill Shannon (Inactive)
            sgoodsunw Sheri Good (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: