13 Replies Latest reply on Feb 25, 2008 7:22 PM by Martin Rostan

    My WS doesn't send any attachment... why?

    Claudio Di Ciccio Newbie

      Hi all!

      I'm using the EJB3.0 spec. with JBoss AS 4.2.2 (and the related JBossWS version inside, of course), in order to create a Web Service using a Stateless Session Bean instead of a Servlet.
      I'd like to send an attachment from within a Web Service method.

      Here I explain my problem.
      I programmed as follows my Stateless Session Bean:

      ...
      @Stateless(name="PortalInfoExchangeServiceEJB")
      @WebService(
       name="PortalInfoExchange",
       serviceName="PortalInfoExchange",
       targetNamespace="http://www.provincia.latina.it/servizi/ws/portal/PortalInfoExchange",
       endpointInterface = "servizi.it.latina.provincia.portal.ws.PortalInfoExchangeWS")
      @Remote(PortalInfoExchangeWS.class)
      public class PortalInfoExchangeBean implements PortalInfoExchangeWS {
       @Resource WebServiceContext context;
      ...
       public String interact(
       String xmlData
       ) throws IllegalArgumentException {
      
       // Start-up
       String pdfFilePath = "/var/www/SOAPprova/prova.pdf";
      ...
       // Attachment
       SOAPMessageContext msgContext = (SOAPMessageContext)context.getMessageContext();
       SOAPMessage soapMessage = msgContext.getMessage();
       DataHandler dh = new DataHandler(new FileDataSource(pdfFilePath));
       AttachmentPart attachment = soapMessage.createAttachmentPart(dh);
      
       soapMessage.addAttachmentPart(attachment);
      ...
       // Return
       return "Ciao " + xQueryResult + "! [ xQuery: \"for $nome in doc('/home/cdc/workspace/LTPortalWS/build/classes/servizi/it/latina/provincia/portal/ws/tmp.xml')/dataWrapper/dati/nome return data($nome)\" ]";
      }
      


      But when I call this service from a PHP Client, sniffing the SOAP response packet I see this:

      HTTP/1.1 200 OK
      Server: Apache-Coyote/1.1
      X-Powered-By: Servlet 2.4; JBoss-4.2.2.GA (build: SVNTag=JBoss_4_2_2_GA date=200710221139)/Tomcat-5.5
      Content-Type: text/xml;charset=UTF-8
      Date: Thu, 06 Dec 2007 09:56:13 GMT
      Connection: close
      
      <env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
      <env:Header>
      </env:Header>
      <env:Body>
      <ns2:interactResponse xmlns:ns2="http://www.provincia.latina.it/servizi/ws/portal/PortalInfoExchange">
      <xmlData>Ciao Claudio! [ xQuery: &quot;for $nome in doc('/home/cdc/workspace/LTPortalWS/build/classes/servizi/it/latina/provincia/portal/ws/tmp.xml')/dataWrapper/dati/nome return data($nome)&quot; ]</xmlData>
      
      </ns2:interactResponse>
      </env:Body>
      </env:Envelope>
      


      Please, could anyone suggest me why there's no attachment?
      Have I got to change somehow manually the WSDL to specify that there will be an attachment?
      Did I make something wrong into the code?

      I searched a lot around the web, but found nothing...

      Any help will be very appreciated!

      Claudio Di Ciccio

        • 1. Re: My WS doesn't send any attachment... why?
          Claudio Di Ciccio Newbie

          Ok, I understood that the main problem is that I'm trying to send back to the client, with a server-response, the attachment.

          Instead, this code:

          SOAPMessageContext msgContext = (SOAPMessageContext)context.getMessageContext();


          gives back the request message, not the response one.

          Does anyone know how to access the response message?
          Or what should I do to attach something to the response message, in general?
          I searched everywhere but I found nothing about it!

          Thanks very much for your help!

          • 3. Re: My WS doesn't send any attachment... why?
            Claudio Di Ciccio Newbie

            Thank you Alessio for your response.

            Considering that my web service client is a PHP page, I suppose I cannot use MTOM. I'll try with SWA-REF.

            I read that article before, actually, but I hoped there could be something more direct to access the response message and attach anything that way. It seems, instead, that I have to work with @XmlAttachmentRef annotation over a complex return type.

            Thanks againg for your precious help - I focus the situation better now.

            • 4. Re: My WS doesn't send any attachment... why?
              Claudio Di Ciccio Newbie

              Ok, I tried and used the SwAref technique many times, and everything worked perfectly.

              Sadly, a new problem: when I wanted to send back to the client a List of complex objects, each with a DataHandler field, to treat as an attachment, a problem came.

              In detail, here's the webservice interface method signature (btw, I'm sorry if I did not translate names from Italian):

              ...
               @WebMethod(operationName="getDocumentiRichiestaAvvioPratica")
               @WebResult(name="documentiData")
               List<DocumentoData> getDocumentiRichiestaAvvioPratica(
               @WebParam(name="numeroIstanza") int numeroIstanza,
               @WebParam(name="settore") String settore,
               @WebParam(name="natura") String natura)
               throws IllegalArgumentException;
              ...
              


              And here is the definition of DocumentoData
              @XmlRootElement(name="DocumentoData")
              public class DocumentoData {
               /**
               * Autore del documento.
               */
               @XmlAttribute(required=true)
               public String autore;
              /*
              many other fields here...
              */
               /**
               * Contenuto binario del documento (mappato come <em>SwAref</em>, allegato SOAP)
               */
               @XmlElement
               @XmlAttachmentRef
               public DataHandler data;
              
               protected DocumentoData() {}
              
               /**
               * Costruttore di istanze <code>DocumentoData</code>
               * @param autore Autore del documento
               * @param dataCreazione Data di creazione del documento
               * @param numeroDocumento Numero del documento
               * @param protocollo Protocollo del documento (può essere <code>null</code>)
               * @param nomeFile Nome del file
               * @param titolo Titolo del file
               * @param descrizione Descrizione del contenuto (può essere una stringa vuota)
               * @param data Handler dei dati fisici del file
               */
               public DocumentoData(String autore, Calendar dataCreazione,
               int numeroDocumento, Protocollo protocollo,
               String nomeFile, String titolo, String descrizione, DataHandler data) {
               this.autore = autore;
               this.dataCreazione = dataCreazione;
               this.numeroDocumento = numeroDocumento;
               this.protocollo = protocollo;
               this.nomeFile = nomeFile;
               this.titolo = titolo;
               this.descrizione = descrizione;
               this.data = data;
               }
              }
              


              This is the outgoing SOAP message, when the method's invocated
              HTTP/1.1 200 OK
              Server: Apache-Coyote/1.1
              X-Powered-By: Servlet 2.4; JBoss-4.2.2.GA (build: SVNTag=JBoss_4_2_2_GA date=200710221139)/Tomcat-5.5
              Content-Type: text/xml;charset=UTF-8
              Date: Fri, 22 Feb 2008 12:17:52 GMT
              Connection: close
              
              <env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
              <env:Header>
              </env:Header>
              <env:Body>
              <ns2:getDocumentiRichiestaAvvioPraticaResponse xmlns:ns2="http://www.provincia.latina.it/servizi/ws/PraticaStartWS">
              <documentiData dataCreazione="2008-02-22T13:17:52.682+01:00" autore="Claudio Di Ciccio">
              <numeroDocumento>14</numeroDocumento>
              <nomeFile>RichiestaAvvio.13.A2.1244.pdf</nomeFile>
              <titolo>Richiesta avvio procedimento - Settore Vincolo Idrogeologico - Allargamento pista camionabile</titolo>
              <descrizione>Richiesta avvio procedimento</descrizione>
              <data>cid:0-1203682672701-305379@ws.jboss.org</data>
              </documentiData>
              <documentiData dataCreazione="2008-02-22T13:17:52.682+01:00" autore="Claudio Di Ciccio">
              <numeroDocumento>14</numeroDocumento>
              <nomeFile>RichiestaAvvio.13.A2.1244.pdf</nomeFile>
              <titolo>Richiesta avvio procedimento - Settore Vincolo Idrogeologico - Allargamento pista camionabile</titolo>
              <descrizione>Richiesta avvio procedimento</descrizione>
              <data>cid:1-1203682672702-32409330@ws.jboss.org</data>
              </documentiData>
              </ns2:getDocumentiRichiestaAvvioPraticaResponse>
              </env:Body>
              </env:Envelope>
              


              That is: there's no attachment, just cids into the SOAP message.
              Instead, if I send back just ONE DocumentoData object, everything works.

              Could someone suggest me why?
              Thank you very much, in advance

              • 5. Re: My WS doesn't send any attachment... why?
                Martin Rostan Newbie

                I believe it's a problem in ReflectiveAttachmentRefScanner, the recursion for collections (arrays or lists) is not working, the annotations are searched in the array or list type and not in the contained type.

                The workaround we have found is to add a wrapper object with a string and the collection, and annotate the string with @XmlMimeType

                This works because the purpose of this class is to return an AttachmentScanResult object, indicating if there are attachments or not.
                I don know why it works even returning XOP as the attachment type instead of SWA_REF.
                I believe it will also work if you change the string object with a DataHandler field annotated with @XmlAttachmentRef

                Regards,
                Martin

                • 6. Re: My WS doesn't send any attachment... why?
                  Claudio Di Ciccio Newbie

                  Thank you very much, Martin, for your help!

                  Sadly, the solutions you suggested me aren't suitable for my case, because the other fields into the DocumentoData class are tightly connected to the DataHandler - that is, it's a design issue: they're all meta-information about the pdf file the DataHandler holds, so the wrapper should wrap a Collection of DocumentoData objects, and not a Collection of DataHandlers "alone"!
                  I tried to wrap a Collection of DocumentoData instances, but it doesn't work anyway.

                  On the other hand, the client is not MTOM/XOP enabled, because it's a PHP PEAR::SOAP client.

                  I think I will have to abandon the idea of putting as attachment the files, then, and use the base64-encoding.

                  Thank you, anyway!

                  Best regards,
                  Claudio

                  • 7. Re: My WS doesn't send any attachment... why?
                    Martin Rostan Newbie

                    Hi Claudio.

                    Maybe I was not clear enough, I'm not sure you have tried my solution, so here is an example:
                    Create a wrapper class, let's say Documentos:

                    public class Documentos {
                     @XmlMimeType("application/octet-stream")
                     private String dummy;
                    
                     private List<DocumentoData> documentos;
                    }
                    


                    It should work, the trick is the annotation in the dummy string, simply put the field, you don't need to use it

                    Btw, I will upload a patch later, and I will test a case similar to yours, so I expect this problem to be fixed on jbossws 2.0.4 .

                    Regards,
                    Martin

                    • 8. Re: My WS doesn't send any attachment... why?
                      Heiko Braun Master

                      Thanks for the thorough report Martin. I've created an isseu for it: http://jira.jboss.org/jira/browse/JBWS-2012

                      • 9. Re: My WS doesn't send any attachment... why?
                        Claudio Di Ciccio Newbie

                        Thank you Martin for your kind reply. I did appreciate it very much but...

                        Here is the new wrapper class:

                        @XmlRootElement(name="Documenti")
                        public class DocumentiDataList {
                         @XmlMimeType("application/octet-stream")
                         protected String dummy;
                        
                         @XmlElement(name="documenti")
                         public List<DocumentoData> documenti;
                        
                         protected DocumentiDataList() {}
                        
                         public DocumentiDataList(List<DocumentoData> list) {
                         this.dummy = "";
                         this.documenti = list;
                         }
                        }
                        


                        where DocumentoData is:
                        @XmlRootElement(name="DocumentoData")
                        public class DocumentoData {
                         /**
                         * Autore del documento.
                         */
                         @XmlAttribute(required=true)
                         public String autore;
                        
                         /**
                         * Data della creazione del documento.
                         */
                         @XmlAttribute(required=true)
                         public Calendar dataCreazione;
                        
                         /**
                         * Numero identificativo (chiave) del documento
                         * <br />Deve essere univoco per ogni documento generato, e positivo.
                         */
                         @XmlElement(required=true)
                         public int numeroDocumento;
                        
                         /**
                         * Numero di protocollo del documento (attributo opzionale).
                         * <br />Qualora presente, questo attributo deve essere univoco per tutti gli oggetti di questa classe.
                         */
                         @XmlElement(required=false)
                         public Protocollo protocollo;
                        
                         /**
                         * Nome del file.
                         */
                         @XmlElement(required=true)
                         public String nomeFile;
                        
                         /**
                         * Titolo del documento.
                         */
                         @XmlElement(required=true)
                         public String titolo;
                        
                         /**
                         * Descrizione del documento (attributo opzionale).
                         */
                         @XmlElement(required=false)
                         public String descrizione;
                        
                         /**
                         * Contenuto binario del documento (mappato come <em>SwAref</em>, allegato SOAP)
                         */
                         @XmlAttachmentRef
                         public DataHandler file;
                        
                         // Costruttore richiesto da JAXB: impostandone l'accesso a "protected", si evita la trasposizione in XML-Schema
                         protected DocumentoData() {}
                        
                         /**
                         * Costruttore di istanze <code>DocumentoData</code>
                         * @param autore Autore del documento
                         * @param dataCreazione Data di creazione del documento
                         * @param numeroDocumento Numero del documento
                         * @param protocollo Protocollo del documento (può essere <code>null</code>)
                         * @param nomeFile Nome del file
                         * @param titolo Titolo del file
                         * @param descrizione Descrizione del contenuto (può essere una stringa vuota)
                         * @param data Handler dei dati fisici del file
                         */
                         public DocumentoData(String autore, Calendar dataCreazione,
                         int numeroDocumento, Protocollo protocollo,
                         String nomeFile, String titolo, String descrizione, DataHandler data) {
                         this.autore = autore;
                         this.dataCreazione = dataCreazione;
                         this.numeroDocumento = numeroDocumento;
                         this.protocollo = protocollo;
                         this.nomeFile = nomeFile;
                         this.titolo = titolo;
                         this.descrizione = descrizione;
                         this.file = data;
                         }
                        }
                        


                        and this is the SessionBean's WebService method the client calls:
                         public DocumentiDataList getDocumentiRichiestaAvvioPratica(int numeroIstanza,
                         String settore, String natura)
                         throws IllegalArgumentException {
                         DocumentoData newDocumentoData = new DocumentoData(
                         "Claudio Di Ciccio",
                         new GregorianCalendar(),
                         14,
                         null,
                         "RichiestaAvvio.13.A2.1244.pdf",
                         "Richiesta avvio procedimento - Settore Vincolo Idrogeologico - Allargamento pista camionabile",
                         "Richiesta avvio procedimento",
                         new DataHandler(new FileDataSource("/var/SemplificAZIONE/RichiestaAvvio.13.A2.1244.pdf")));
                         List<DocumentoData> returnList = new ArrayList<DocumentoData>(2);
                         returnList.add(newDocumentoData);
                         returnList.add(newDocumentoData);
                         return new DocumentiDataList(returnList);
                         }
                        


                        but the response is still:
                        HTTP/1.1 200 OK
                        Server: Apache-Coyote/1.1
                        X-Powered-By: Servlet 2.4; JBoss-4.2.2.GA (build: SVNTag=JBoss_4_2_2_GA date=200710221139)/Tomcat-5.5
                        Content-Type: text/xml;charset=UTF-8
                        Date: Mon, 25 Feb 2008 09:11:13 GMT
                        Connection: close
                        
                        <env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
                        <env:Header>
                        </env:Header>
                        <env:Body>
                        <ns2:getDocumentiRichiestaAvvioPraticaResponse xmlns:ns2="http://www.provincia.latina.it/servizi/ws/PraticaStartWS">
                        <documentiData>
                        <dummy>
                        </dummy>
                        <documenti dataCreazione="2008-02-25T10:11:13.901+01:00" autore="Claudio Di Ciccio">
                        <numeroDocumento>14</numeroDocumento>
                        <nomeFile>RichiestaAvvio.13.A2.1244.pdf</nomeFile>
                        <titolo>Richiesta avvio procedimento - Settore Vincolo Idrogeologico - Allargamento pista camionabile</titolo>
                        <descrizione>Richiesta avvio procedimento</descrizione>
                        <file>cid:0-1203930673914-19807859@ws.jboss.org</file>
                        </documenti>
                        <documenti dataCreazione="2008-02-25T10:11:13.901+01:00" autore="Claudio Di Ciccio">
                        <numeroDocumento>14</numeroDocumento>
                        <nomeFile>RichiestaAvvio.13.A2.1244.pdf</nomeFile>
                        <titolo>Richiesta avvio procedimento - Settore Vincolo Idrogeologico - Allargamento pista camionabile</titolo>
                        <descrizione>Richiesta avvio procedimento</descrizione>
                        <file>cid:1-1203930673914-32990827@ws.jboss.org</file>
                        </documenti>
                        </documentiData>
                        </ns2:getDocumentiRichiestaAvvioPraticaResponse>
                        </env:Body>
                        </env:Envelope>
                        


                        I tried it, believe me, but it doesn't work.

                        Maybe it's because of the version? The running Application Server is:
                        JBoss AS 4.2.2.GA
                        with JBossWS / jbossws-native-2.0.1.SP2 bundled,
                        over Ubuntu Linux 7.10,
                        with Sun Java JDK 1.5.0_13 as the default JDK/JVM

                        Thank you very much, once again!!
                        Best regards,
                        Claudio

                        • 10. Re: My WS doesn't send any attachment... why?
                          Martin Rostan Newbie

                          Hi Claudio.
                          Well, I've tested a case very similar to yours, in the same versions (JBoss 4.2.2 with the default JBossWS: 2.0.1 SP2)

                          I've changed one thing from my previous suggestion, annotate the dummy field with @XmlAttachmentRef:

                          public class DocumentsSet {
                           @XmlAttachmentRef
                           String dummy;
                          
                           @XmlElement(name="Documents")
                           List<Document> documents;
                          }
                          


                          The Document class is very similar:
                          public class Document {
                           public Document() {
                           }
                          
                           public Document(String name, String fileUrl) {
                           this.name = name;
                           try {
                           this.data = new DataHandler(new URL(fileUrl));
                           } catch (MalformedURLException exc) {
                           exc.printStackTrace();
                           }
                           }
                          
                           String name;
                          
                           @XmlAttachmentRef
                           DataHandler data;
                          }
                          


                          And it works here, I see a multipart message as the response, I'm using soapUI to invoke it and I can see the attachments in the result also.

                          So, I believe it should work for you.

                          Regards,
                          Martin

                          • 11. Re: My WS doesn't send any attachment... why?
                            Heiko Braun Master

                            Thanks for the patch Martin. That was the quickest issue turnaround ever ;)
                            It will be included in 2.0.4 (end of march)

                            • 12. Re: My WS doesn't send any attachment... why?
                              Claudio Di Ciccio Newbie

                              Thank you very very VERY much Martin, for your patience, your kindness, and your competence.

                              I'm very glad to confirm that it works that way!

                              Uhh... did I forget to thank you?
                              THANKS! :)

                              • 13. Re: My WS doesn't send any attachment... why?
                                Martin Rostan Newbie

                                Hi Claudio.

                                I'm very glad to hear good news.

                                Just remember this is a workaround, and with version 2.0.4 your original web service (return List) should work.

                                Regards,
                                Martin