4 Replies Latest reply on Jan 26, 2009 5:45 AM by mendret

    file transfer via SOAP and RPC

    mendret

      hi folks,

      I'm trying to write a webservice which is capable of receiving and sending files, for JBoss 5 GA.
      So I'm quite new to webservices and jboss, thus I`ve got a few problems concerning this matter.

      I`m quite sure that I need to use attachments to the soap message, but the question is how to do that?

      I tried something using MTOM/SwaRef like it stand here:
      http://jbossws.jboss.org/mediawiki/index.php/JAX-WS_User_Guide#Attachments

      but the code fragments are a bit short, thus I wasn't able to see how I actually attach the files and retrieve them from the attachment

      I tried the following:

      Interface IFileTransfer:

      @WebService(targetNamespace = "http://server/")
      @SOAPBinding(style = SOAPBinding.Style.RPC, parameterStyle = SOAPBinding.ParameterStyle.BARE)
      @BindingType(value="http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true")
      public interface IFileTransfer extends java.rmi.Remote {
      
       @WebMethod
       DocumentPayload beanAnnotation(DocumentPayload payload) ;
      }
      


      Implementation FileTransfer:
      @WebService(name = "FileTransfer",
       serviceName = "FileTransferService",
       portName = "FileTransfer",
       endpointInterface = "remote.IFileTransfer")
      @SOAPBinding(style = SOAPBinding.Style.RPC)
      public class FileTransfer implements IFileTransfer {
      
       @WebMethod
       public DocumentPayload beanAnnotation(DocumentPayload payload) {
      
       System.out.println(payload.getData().getContentType());
       //do something cool with the data
       return payload;
       }
      }
      


      DocumentPayload:

      package remote;
      
      import javax.activation.DataHandler;
      import javax.xml.bind.annotation.XmlAttachmentRef;
      import javax.xml.bind.annotation.XmlElement;
      import javax.xml.bind.annotation.XmlRootElement;
      
      @XmlRootElement
      public class DocumentPayload
      {
       private DataHandler data;
      
       public DocumentPayload()
       {
       }
      
       public DocumentPayload(DataHandler data)
       {
       this.data = data;
       }
      
       @XmlElement
       @XmlAttachmentRef
       public DataHandler getData()
       {
       return data;
       }
      
       public void setData(DataHandler data)
       {
       this.data = data;
       }
      }
      


      and on client side:
      QName serviceName = new QName("http://server/", "FileTransferService");
       Service service = Service.create(new URL("http://127.0.0.1:8080/SOAP-test?wsdl"), serviceName);
       IFileTransfer port = service.getPort(IFileTransfer.class);
      
       // enable MTOM
       SOAPBinding binding = (SOAPBinding)((BindingProvider)port).getBinding();
       binding.setMTOMEnabled(true);
       DataHandler data = new DataHandler(new File("/opt/test.dat").toURI().toURL());
       DocumentPayload dp = (DocumentPayload)port.beanAnnotation(new DocumentPayload(data));
      


      hopefully you understand my problem and can give some good advices

      mendret

        • 1. Re: file transfer via SOAP and RPC
          mendret

          ok, now I found a relativ good example at
          http://jbossws.jboss.org/mediawiki/index.php?title=Security_and_attachments_sample#MTOM.2FXOP_newspaper_server
          and tried to convert it a bit into real file transfer and not only text, like it is in the example and I tried the following at server side:

          public EditionMTOM doSomething(EditionMTOM data)
           {
           try {
           System.out.println(data.getContent().getContentType());
           InputStream is = data.getContent().getInputStream();
           InputStreamReader isr = new InputStreamReader(is, "UTF-8");
           char[] buff = new char[10];
           isr.read(buff);
           isr.close();
           is.close();
           for (char b : buff) {
           System.out.print(b);
           }
           }
           catch (UnsupportedEncodingException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
           }
           catch (IOException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
           }
          
           EditionMTOM edition = new EditionMTOM();
           edition.setContent(new DataHandler(new FileDataSource("/opt/test2.dat"), "application/octet-stream"));
           edition.setDate(new Date());
           edition.setId("test2.dat");
           return edition;
           }
          


          I get some warnings but at all it works until the server tries to send back data, then i get the following exception:

          org.jboss.ws.WSException: No ByteArrayConverter for class: javax.activation.FileDataSource
          


          My question is now what can I do to make this work?

          I'm grateful for every advise you can give me

          • 2. Re: file transfer via SOAP and RPC
            mendret

            ok, found the "error", it is quite simple but I don't get the why... well maybe later on

            the error was simply that

            edition.setContent(new DataHandler(new FileDataSource("/opt/test2.dat"), "application/octet-stream"));
            


            must be
            edition.setContent(new DataHandler(new FileDataSource("/opt/test2.dat")));
            


            @off topic
            wouldn't it be nice to have something like an edit button? or is there one and I simply overlooked it?

            • 3. Re: file transfer via SOAP and RPC
              mendret

              after managing the server side, which works without problems, i still get problems with the client side, i tried different approaches but got errors i wasn't able to resolve, maybe someone has an idea what i'm doing wrong.

              first try was with the files that wsconsume generated:

              public class Client
              {
               protected FileTransferMTOMEndpoint mtomEndpoint;
              
               public Client(URL url) {
               FileTransferMTOMService mtomService = new FileTransferMTOMService(url,
               new QName("http://127.0.0.1:8080/news_test?wsdl",
               "FileTransferMTOMService"));
               mtomEndpoint = (FileTransferMTOMEndpoint)mtomService.getFileTransferMTOMPort();
               }
              
               public void run() throws IOException {
               ((SOAPBinding)(((BindingProvider)mtomEndpoint).getBinding())).setMTOMEnabled(true);
              
               System.out.println("Uploading test2.dat and downloading test.dat");
               EditionMTOM edition2 = new EditionMTOM();
               edition2.setId("test.dat");
               edition2.setContent(new DataHandler(new FileDataSource("/tmp/test2.dat")));
              
               EditionMTOM edition = mtomEndpoint.doSomething(edition2);
               System.out.println("Content: " + edition.getContent());
               InputStream is = edition.getContent().getInputStream();
               InputStreamReader isr = new InputStreamReader(is, "UTF-8");
              
               char[] buff = new char[20];
               isr.read(buff);
               isr.close();
               is.close();
               for (char b : buff) {
               System.out.print(b);
               }
               }
              
               public static void main(String[] args) {
               try {
               Client client = new Client(new URL("http://127.0.0.1:8080/news_test?wsdl"));
               client.run();
               }
               catch (Exception e) {
               e.printStackTrace();
               }
               }
              }
              


              here i get the following error:

              Exception in thread "main" java.lang.NoSuchMethodError: method org.jboss.ws.core.utils.JBossWSEntityResolver.getEntityMap with signature ()Ljava.util.Map; was not found.
               at org.jboss.ws.tools.JavaToXSD.resolveNamespaceURI(JavaToXSD.java:224)
               at org.jboss.ws.tools.JavaToXSD.parseSchema(JavaToXSD.java:171)
               at org.jboss.ws.tools.wsdl.WSDL11Reader.processTypes(WSDL11Reader.java:402)
               at org.jboss.ws.tools.wsdl.WSDL11Reader.processDefinition(WSDL11Reader.java:179)
               at org.jboss.ws.tools.wsdl.WSDLDefinitionsFactory.parse(WSDLDefinitionsFactory.java:126)
               at org.jboss.ws.metadata.umdm.ServiceMetaData.getWsdlDefinitions(ServiceMetaData.java:293)
               at org.jboss.ws.metadata.builder.jaxws.JAXWSClientMetaDataBuilder.buildMetaData(JAXWSClientMetaDataBuilder.java:84)
               at org.jboss.ws.core.jaxws.spi.ServiceDelegateImpl.<init>(ServiceDelegateImpl.java:136)
               at org.jboss.ws.core.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:62)
               at javax.xml.ws.Service.<init>(Service.java:79)
               at client.FileTransferMTOMService.<init>(FileTransferMTOMService.java:36)
               at client.Client.<init>(Client.java:19)
               at client.Client.main(Client.java:49)
              


              the next try was a DII client, which looks like this:

              public class DII2Client {
              
               public static void main(String[] args) {
               try {
               QName serviceName = new QName(
               "http://127.0.0.1:8080/news_test?wsdl",
               "FileTransferMTOMService");
               ServiceFactory factory = ServiceFactory.newInstance();
               Service service = factory.createService(serviceName);
               QName operationName = new QName("http://127.0.0.1:8080/news_test?wsdl", "doSomething");
               QName operationPort = new QName("http://127.0.0.1:8080/news_test?wsdl", "FileTransferMTOMPort");
              
               Call call = service.createCall(operationPort);
               call.setOperationName(operationName);
               call.setProperty("BindingType", "http://schemas.xmlsoap.org/wsdl/soap/http?mtom=true");
               call.setTargetEndpointAddress("http://127.0.0.1:8080/news_test?wsdl");
              
               call.addParameter("arg0", new QName("http://127.0.0.1:8080/news_test?wsdl", "arg0"), EditionMTOM.class, ParameterMode.IN);
              
               EditionMTOM edition2 = new EditionMTOM();
               edition2.setId("test.dat");
               edition2.setContent(new DataHandler(new FileDataSource("/opt/cats/test.dat")));
              
               Object[] params = {edition2};
              
               SimpleDateFormat formatter = new SimpleDateFormat ("yyyy.MM.dd 'at' HH:mm:ss ");
              
               System.out.println("before call:" + formatter.format(new Date()));
               EditionMTOM result = (EditionMTOM)call.invoke(params);
               System.out.println("after call:" + formatter.format(new Date()));
               System.out.println(result);
               } catch (Exception ex) {
               ex.printStackTrace();
               }
               }
              }
              


              as long as i call: factory.createService(serviceName);
              I get the following error:

              java.rmi.RemoteException: Call invocation failed; nested exception is:
               java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage
               at org.jboss.ws.core.jaxrpc.client.CallImpl.invokeInternal(CallImpl.java:533)
               at org.jboss.ws.core.jaxrpc.client.CallImpl.invoke(CallImpl.java:274)
               at client.DII2Client.main(DII2Client.java:43)
              Caused by: java.lang.UnsupportedOperationException: setProperty must be overridden by all subclasses of SOAPMessage
               at javax.xml.soap.SOAPMessage.setProperty(SOAPMessage.java:441)
               at org.jboss.ws.core.soap.SOAPMessageImpl.<init>(SOAPMessageImpl.java:82)
               at org.jboss.ws.core.soap.MessageFactoryImpl.createMessage(MessageFactoryImpl.java:169)
               at org.jboss.ws.core.CommonSOAP11Binding.createMessage(CommonSOAP11Binding.java:57)
               at org.jboss.ws.core.CommonSOAPBinding.bindRequestMessage(CommonSOAPBinding.java:156)
               at org.jboss.ws.core.CommonClient.invoke(CommonClient.java:290)
               at org.jboss.ws.core.jaxrpc.client.CallImpl.invokeInternal(CallImpl.java:514)
               ... 2 more
              


              if i try to run it with: Service service = factory.createService(new URL("http://127.0.0.1:8080/news_test?wsdl"),serviceName);
              i get this error:
              Exception in thread "main" java.lang.NoSuchMethodError: org.jboss.ws.core.utils.JBossWSEntityResolver.getEntityMap()Ljava/util/Map;
               at org.jboss.ws.tools.JavaToXSD.resolveNamespaceURI(JavaToXSD.java:224)
               at org.jboss.ws.tools.JavaToXSD.parseSchema(JavaToXSD.java:171)
               at org.jboss.ws.tools.wsdl.WSDL11Reader.processTypes(WSDL11Reader.java:402)
               at org.jboss.ws.tools.wsdl.WSDL11Reader.processDefinition(WSDL11Reader.java:179)
               at org.jboss.ws.tools.wsdl.WSDLDefinitionsFactory.parse(WSDLDefinitionsFactory.java:126)
               at org.jboss.ws.metadata.umdm.ServiceMetaData.getWsdlDefinitions(ServiceMetaData.java:293)
               at org.jboss.ws.metadata.builder.jaxrpc.JAXRPCClientMetaDataBuilder.buildMetaData(JAXRPCClientMetaDataBuilder.java:114)
               at org.jboss.ws.metadata.builder.jaxrpc.JAXRPCClientMetaDataBuilder.buildMetaData(JAXRPCClientMetaDataBuilder.java:85)
               at org.jboss.ws.core.jaxrpc.client.ServiceImpl.<init>(ServiceImpl.java:109)
               at org.jboss.ws.core.jaxrpc.client.ServiceFactoryImpl.createService(ServiceFactoryImpl.java:155)
               at org.jboss.ws.core.jaxrpc.client.ServiceFactoryImpl.createService(ServiceFactoryImpl.java:126)
               at client.DII2Client.main(DII2Client.java:23)
              


              i found a post regarding the last error but it was never resolved:
              http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4063940#4063940

              so it would be nice if someone has an idea what is causing these problems and how to resolve them

              • 4. Re: file transfer via SOAP and RPC
                mendret

                just for completeness, problem was that i used some wrong libs

                now everything is working except an dii client, which still throws exceptions like this:

                org.jboss.xb.binding.JBossXBRuntimeException: Failed to find read method or field for property 'commandMap' in class javax.activation.DataHandler
                 at org.jboss.xb.binding.introspection.ClassInfo.getFieldInfo(ClassInfo.java:82)
                


                or if i specify the url to the WSDL

                org.jboss.ws.WSException: Cannot obtain java type mapping for: {http://server/}tns:documentPayload
                 at org.jboss.ws.metadata.builder.jaxrpc.JAXRPCMetaDataBuilder.buildInputParameter(JAXRPCMetaDataBuilder.java:264)
                
                


                so it would be nice if someone is able to tell me what the problem is and what i should do to resolve it