users@glassfish.java.net

Re: Sending Attachments to a JAX-WS Web Service

From: <glassfish_at_javadesktop.org>
Date: Tue, 05 Jun 2007 12:04:24 PDT

Hi

Im no expert in web services but i managed to make the code work. My needs were a little different, i needed to send a generic array of objects to the server.

in net beans 5.5:

file > new Project > Enterprise > Enterprise Application
Give the project a name and all the stuff (be sure to use JavaEE 1.5 not 1.4)

Once the project is created right click on the ejb module and click on new > web service (if it doesnt appear look for it in File/Folder...)

create an empty web service with the name 'TestBinaryWS' and the package 'test.binary'

now copy and paste the following code:

package test.binary;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import javax.activation.DataHandler;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@Stateless()
@WebService()
public class TestBinaryWS
{
    @Resource()
    WebServiceContext wsContext;
    
    @WebMethod
    public String sendCommand()
    {
        // Obtain a reference to the attachments.
        MessageContext context = wsContext.getMessageContext();
        Map attachments = (Map) context.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS) ;
        
        // Get a collection of values from the attachments map.
        Collection values = attachments.values();
        
        // Get the iterator from the collection.
        Iterator itr = values.iterator();
        
        while (itr.hasNext())
        {
            // Get a reference to the data handler.
            DataHandler dh = (DataHandler) itr.next();
            
            try
            {
                // Get a reference to the datahandlers input stream.
                InputStream is = dh.getInputStream();
                
                // Open an object output stream to recieve the data.
                ObjectInputStream ois=new ObjectInputStream(is);
                
                Object object=null;
                try
                {
                    object = ois.readObject();
                }
                catch (ClassNotFoundException ex)
                {
                    ex.printStackTrace();
                }
                catch (IOException ex)
                {
                    ex.printStackTrace();
                }
                
                Object[] parameters=(Object[])object;
                
                for(Object parameter : parameters)
                {
                    System.out.println("parameter: "+parameter);
                }
                
                // Close the output stream.
                ois.close();
            }
            catch (FileNotFoundException ex)
            {
                ex.printStackTrace();
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
        return "success";
    }
    
}

compile the file, right click on the enterprise application and deploy the project in an application server

now let netbeans create the client for you; create a regular java application project

file > new Project > general > Java Application

create a new web service client: right click on the project > new > web service client

select WSDL URL: and put the ULR of the deployed service, in my case is:
http://localhost:8081/TestBinaryWSService/TestBinaryWS?wsdl

Netbeans should locate the wsdl and build the client for you, now lets finish.

The client must be able to send any object, so neither the javax.activation.FileDataSource nor the javax.activation.URLDatasource will do, unless you want to do a bad web service

The first step is to create a new javax.activation.DataSource able to manage serializable objects, the class is:
package test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import javax.activation.DataSource;

public class ObjectDataSource implements DataSource
{
    private Object object;
    
    public ObjectDataSource(Object object)throws IOException
    {
        this.object=object;
    }

    public String getContentType()
    {
        return "multipart/*";
    }

    public String getName()
    {
        return "java.object";
    }
    
    public InputStream getInputStream() throws IOException
    {
        ByteArrayOutputStream output=new ByteArrayOutputStream();
        ObjectOutputStream objectStream=new ObjectOutputStream(output);
        objectStream.writeObject(object);
        objectStream.flush();
        
        ByteArrayInputStream result=new ByteArrayInputStream(output.toByteArray());
        
        return result;
    }

    public OutputStream getOutputStream() throws IOException
    {
        throw new IOException("Unsupported");
    }
}

Finally create a main class with the following code:

/*
 * TestMain.java
 *
 * Created on June 4, 2007, 11:42 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package test;

import java.awt.Point;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.activation.DataHandler;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.MessageContext;

/**
 *
 * @author root
 */
public class TestMain
{
    
    public static void main(String[] args)
    {
        try
        {
            // Call Web Service Operation
            TestBinaryWSService service=new TestBinaryWSService();
            TestBinaryWS port=service.getTestBinaryWSPort();

            Serializable[] parameters=new Serializable[]{
                new Point(131, 216),
                new Point(231, 316),
                new Point(331, 416),
                new Point(431, 516)
            };
            DataHandler dh = new DataHandler(new ObjectDataSource(parameters));
            
            // Get a reference to the request context.
            Map requestContext = ((BindingProvider) port).getRequestContext();
            
            // Get a reference to the attachments map.
            Map attachments = (Map) requestContext.get(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS);
            
            // If the attachments map is null, then create a new map and place it in the request context.
            if (attachments == null)
            {
                attachments = new HashMap();
                requestContext.put(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS, attachments);
            }

            // Add the data handler to the list of outbound attachments.
            attachments.put("multipart/*", dh);

            System.out.println("sending...");
            // Invoke the webservice call.
            System.out.println(port.sendCommand());
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

And hopefully thats it; if you have any doubt you can contact me at david.diaz.co_at_sun.com
[Message sent by forum member 'david_arturo_diaz' (david_arturo_diaz)]

http://forums.java.net/jive/thread.jspa?messageID=220639