# Web Service + SOAP Attachment



## winniwinter (5. Juni 2007)

Puh ich weiss nicht ob ich hier richtig bin. Aber ich stelle mal meine Fragen:

Die Daten des WebService werden ja in SOAP eingebettet. Nun möchte ich, dass mein WebService eine Datei an den Client sendet. Habe dazu schon etwas über SOAP + Attachments gelesen. Bin ich da auf dem richtigen weg?
Hat jmd vlt ein Codebeispiel schon parat, in dem ich sehe, wie ich das unter Java anstelle?

Denke mir, ich muss den ganzen Content, wie mime-type etc an den Client weitergeben, damit der versteht was da ankommt.
Oder bin ich da ganz falsch?


----------



## Gainwar (5. Juni 2007)

Huhu,

welches Framework benutzt du denn? Vermutlich Axis oder XFire.

Wenn du Attachments, also Dateien verschicken willst musst du eigentlich nichts weiter machen als deinem zu serialisierenden Objekt einen byte[] Array mit dem Dateiinhalt zu geben. Praktisch wäre auch eine Eigenschaft mit dem Dateinamen um evtl. an der Dateiendung feststellen zu können um welche Art von Datei es sich handelt.

Das Framework macht den rest.

Gruß Manuel


----------



## winniwinter (5. Juni 2007)

Oh das hatte ich vollkommen vergessen.
Ich nutze Tomcat in Verbindung mit Axis2.

Also du meinst, einfach den Stream in ein byte array speichern und dann beim client wieder auslesen...hmm
werde das aufjedenfall mal probieren.
bin nun auf die beispiele von axis gestoßen, dort wird das Problem so gelöst:

Server:

```
package sample.soapwithattachments.service;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.activation.DataHandler;

import org.apache.axiom.attachments.Attachments;
import org.apache.axis2.context.MessageContext;

public class AttachmentService {

	public String uploadFile(String name, String attchmentID) throws IOException
	{
        MessageContext msgCtx = MessageContext.getCurrentMessageContext();
        Attachments attachment = msgCtx.getAttachmentMap();
        DataHandler dataHandler = attachment.getDataHandler(attchmentID);
        File file = new File(
				name);
		FileOutputStream fileOutputStream = new FileOutputStream(file);
		dataHandler.writeTo(fileOutputStream);
		fileOutputStream.flush();
		fileOutputStream.close();
		
		return "File saved succesfully.";
	}

}
```

Client:

```
package sample.soapwithattachments.client;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.List;
import java.util.Map;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.namespace.QName;

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMText;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.client.OperationClient;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.util.CommandLineOption;
import org.apache.axis2.util.CommandLineOptionParser;
import org.apache.axis2.util.OptionsValidator;
import org.apache.axis2.wsdl.WSDLConstants;

public class SWAClient {

	private static EndpointReference targetEPR = new EndpointReference(
			"http://localhost:8080/axis2/services/SWASampleService");

	public static void main(String[] args) throws Exception {
		CommandLineOptionParser optionsParser = new CommandLineOptionParser(
				args);
		List invalidOptionsList = optionsParser
				.getInvalidOptions(new OptionsValidator() {
					public boolean isInvalid(CommandLineOption option) {
						String optionType = option.getOptionType();
						return !("dest".equalsIgnoreCase(optionType) || "file"
								.equalsIgnoreCase(optionType));
					}
				});

		if ((invalidOptionsList.size() > 0) || (args.length != 4)) {
			// printUsage();
			System.out
					.println("Invalid Parameters.  Usage -file <file to be send> -dest <destination file>");
			return;
		}

		Map optionsMap = optionsParser.getAllOptions();

		CommandLineOption fileOption = (CommandLineOption) optionsMap
				.get("file");
		CommandLineOption destinationOption = (CommandLineOption) optionsMap
				.get("dest");
		File file = new File(fileOption.getOptionValue());
		if (file.exists())
			transferFile(file, destinationOption.getOptionValue());
		else
			throw new FileNotFoundException();
	}

	public static void transferFile(File file, String destinationFile)
			throws Exception {

		Options options = new Options();
		options.setTo(targetEPR);
		options.setProperty(Constants.Configuration.ENABLE_SWA,
				Constants.VALUE_TRUE);
		options.setSoapVersionURI(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
		// Increase the time out when sending large attachments
		options.setTimeOutInMilliSeconds(10000);
		options.setTo(targetEPR);
		options.setAction("urn:uploadFile");

		// assume the use runs this sample at
		// <axis2home>/samples/soapwithattachments/ dir
		ConfigurationContext configContext = ConfigurationContextFactory
				.createConfigurationContextFromFileSystem("../../repository",
						null);

		ServiceClient sender = new ServiceClient(configContext, null);
		sender.setOptions(options);
		OperationClient mepClient = sender
				.createClient(ServiceClient.ANON_OUT_IN_OP);

		MessageContext mc = new MessageContext();
		FileDataSource fileDataSource = new FileDataSource(file);

		// Create a dataHandler using the fileDataSource. Any implementation of
		// javax.activation.DataSource interface can fit here.
		DataHandler dataHandler = new DataHandler(fileDataSource);
		String attachmentID = mc.addAttachment(dataHandler);

		SOAPFactory fac = OMAbstractFactory.getSOAP11Factory();
		SOAPEnvelope env = fac.getDefaultEnvelope();
		OMNamespace omNs = fac.createOMNamespace(
				"http://service.soapwithattachments.sample/xsd", "swa");
		OMElement uploadFile = fac.createOMElement("uploadFile", omNs);
		OMElement nameEle = fac.createOMElement("name", omNs);
		nameEle.setText(destinationFile);
		OMElement idEle = fac.createOMElement("attchmentID", omNs);
		idEle.setText(attachmentID);
		uploadFile.addChild(nameEle);
		uploadFile.addChild(idEle);
		env.getBody().addChild(uploadFile);
		mc.setEnvelope(env);

		mepClient.addMessageContext(mc);
		mepClient.execute(true);
		MessageContext response = mepClient
				.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
	  	SOAPBody body = response.getEnvelope().getBody();
	  	OMElement element = body.getFirstElement().getFirstChildWithName(
	  	new QName("http://service.soapwithattachments.sample/xsd","return"));
		System.out.println(element.getText());
	}
}
```


----------



## winniwinter (6. Juni 2007)

komme nicht weiter kann jmd helfen?

ich weiss, dass SOAP daten per MTOM oder SwA übertragen kann. 
Leider finde ich außer das axis sample keine passenden beispiele.


----------



## winniwinter (6. Juni 2007)

hallo ich noch mal. ich verfolge nun mal den ansatz mit dem byte array

hier mal der service:


```
public byte[] sendeAngebot(String fangebot) throws Exception
	{
		AngebotsAufrufe aa1 = new AngebotsAufrufe();
		String tresponse = null;
		tresponse = aa1.GetAngebot(fangebot);
		System.out.println(tresponse);
		InputStream fis = new FileInputStream(tresponse);
		
		  int len = 0;
		  byte[] buffer = new byte[1024];
          while ((len = fis.read(buffer)) > 0) 
          	{
              return buffer;
          	}
          return new byte[-1];
```

der Client sieht dann so aus


```
public static void main(String[] args) 
	{
		try
 		{
 		AngebotsServiceAngebotsServiceHttpportStub stub = new AngebotsServiceAngebotsServiceHttpportStub("http://10.100.0.27:8080/axis2/services/AngebotsService");


 		
 		SendeAngebot sa = new SendeAngebot();
 		sa.setFangebot("1");
 		DataHandler data = null;
		data= stub.sendeAngebot(sa).get_return();
		
		
		FileOutputStream fos = new FileOutputStream("D:\\tata.pdf");
		data.writeTo(fos);

		fos.flush();
		fos.close();
		
 		}
 		catch(Exception e) {}
 		
 	}
		// TODO Auto-generated method stub
}
```

SOAP Request:

```
<?xml version='1.0' encoding='utf-8'?>
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body><axis2ns5:sendeAngebot xmlns:axis2ns5="http://10.100.0.27/xsd">
<fangebot>1</fangebot>
</axis2ns5:sendeAngebot>
</soapenv:Body>
</soapenv:Envelope>
```

SOAP Response:

```
<?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<ns:sendeAngebotResponse xmlns:ns="http://10.100.0.27/xsd">
<ns:return>TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAADwSBvDtCl1kLQpdZC0KXWQ6Qt+kLcpdZA3NXuQvCl1kOkLf5C/KXWQ6QtxkLYpdZC0KXSQICl1kHcmKJC/KXWQ6wt+kIopdZBzL3OQtSl1kFJpY2i0KXWQAAAAAAAAAABQRQAATAEEAGZK4kQAAAAAAAAAAOAADwELAQYAACoBAACwAAAAAAAAPx8BAAAQAAAAQAEAAABAAAAQAAAAAgAABAAAAAAAAAAEAAAAAAAAAAAAAgAABAAA4ClZAAIAAAAAABAAABAAAAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAAOBwAQCMAAAAAJABAIhpAAAAAAAAAAAAAOB6WADoFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAEAtAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC50ZXh0AAAAwikBAAAQAAAAKgEAAAQAAAAAAAAAAAAAAAAAACAAAGAucmRhdGEAAOI5AAAAQAEAADoAAAAuAQAAAAAAAAAAAAAAAABAAABALmRhdGEAAACkCgAAAIABAAAIAAAAaAEAAAAAAAAAAAAAAAAAQAAAwC5yc3JjAAAAiGkAAACQAQAAagAAAHABAAAAAAAAAAAAAAAAAEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</ns:return>
</ns:sendeAngebotResponse>
</soapenv:Body>
</soapenv:Envelope>
```

ich erhalte nur ein 1kb file das nicht geöffnet werden kann. 
ist das mit dem datahandler falsch? wird die datei nicht komplett über das byte array verschickt?


----------



## Thomas Darimont (8. Juni 2007)

Hallo,

ich würde das einfach mit XFire (http://xfire.codehaus.org/) und MTOM (http://xfire.codehaus.org/MTOM) = Message Transfer Optimization Mechanism machen...

Gruß Tom


----------



## winniwinter (8. Juni 2007)

hi thomas,

generell hätte ich nichts dagegen auch XFire einmal zu testen. Jedoch habe ich nur noch 3 Wochen Zeit um den Web Service inklusive meiner Diplomarbeit fertigzustellen. Deswegen habe ich nicht mehre die Zeit jetzt noch das FrameWork zu wechseln, da ich nicht weiss was für Aufwand dadurch auf mich zu käme und ich noch andere Baustellen habe, die fertig werden müssen. 
Axis2 unterstützt ebenfalls MTOM, jedoch finde ich kein gutes Codebeispiel, dass es für mich verständlich macht mein Problem zu lösen

Also eine Art Notlösung habe ich nun folgendes gemacht:
Der Web Service gibt die url der PDF Datei zurück. 
Der Client nimmt sie entgegen und baut eine URLConnection auf und liest die Datei per InputStream ein. 

Keine schöne Lösung sollte ich es aber nicht innerhalb der nächsten Tage hinbekommen, werde ich das so übernehmen (müssen).Leider...


@gainwar
das mit dem byteArray funktioniert nicht, da soap keine arrays übergeben kann (zumindest sah das so bei mir aus)
ich habe versucht die bytes als string anzuhängen. Jedoch ist das auch keine Lösung für mich, da die Performance doch zu wünschen übrig lässt.


----------



## Thomas Darimont (8. Juni 2007)

Hallo,

gibt's denn hier nicht genug infos?
http://ws.apache.org/axis2/1_1/mtom-guide.html#31

Gruß Tom


----------



## winniwinter (13. Juni 2007)

so habe es jetzt bin SwA hinbekommen, dass ich eine datei mit SOAP versenden kann. 
der code in dem ich das attachement hinzufüge lautet:


```
MessageContext mc = new MessageContext();
		FileDataSource fileDataSource = new FileDataSource(file);
		
		
		// Create a dataHandler using the fileDataSource. Any implementation of
		// javax.activation.DataSource interface can fit here.
		DataHandler dataHandler = new DataHandler(fileDataSource);
		String attachmentID = mc.addAttachment(dataHandler);
```

ich möchte jedoch einen InputStream übergeben!

also so:


Servlet erhält Stream:

```
InputStream is = element.getInputStream();
```

Nun soll der InputStream ohne zwischenspeichern über soap versendet werden.

ist das möglich?


----------



## Thomas Darimont (13. Juni 2007)

Hallo,

wie wär's denn mit einem einer entsprechenden eigenen DataSource?

```
/**
 * 
 */
package de.tutorials;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;

import javax.activation.DataSource;

/**
 * @author Thomas.Darimont
 *
 */
public class InputStreamDataSource implements DataSource {

    WeakReference<InputStream> inputStreamReference;
    
    public InputStreamDataSource(InputStream inputStream){
        this.inputStreamReference = new WeakReference<InputStream>(inputStream);
    }
    
    @Override
    public String getContentType() {
        return "application/octet-stream";
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return this.inputStreamReference.get();
    }

    @Override
    public String getName() {
        //return this.inputStream.toString();
        throw new UnsupportedOperationException("An InputStream has no Name");
    }

    @Override
    public OutputStream getOutputStream() throws IOException {
        throw new UnsupportedOperationException("Cannot open OutputStream on InputStream");
    }

}
```

Gruß Tom


----------



## winniwinter (14. Juni 2007)

hmm ok das hab ich nicht ganz hinbekommen. 

noch was anderes. Da ich es jetzt hinbeommen habe vom client zum service ne datei zu senden, wollte ich das ganze umkehren.

dazu habe ich so ein attachment erzeugt:


```
MessageContext mc = new MessageContext();
		FileDataSource fileDataSource = new FileDataSource(datei);
		
		
		  
		DataHandler dataHandler = new DataHandler(fileDataSource);
		String attachmentID = mc.addAttachment(dataHandler);
```

nun bin ich mir aber nicht sicher wie ich das attachment an die soap nachricht anhängen kann!

ich hab es so versucht:


```
SOAPFactory fac = OMAbstractFactory.getSOAP11Factory();
		SOAPEnvelope env = fac.getDefaultEnvelope();
		
		OMNamespace omNs = fac.createOMNamespace(
				"http://10.100.0.27/xsd", "swa");
		
		OMElement uploadFile = fac.createOMElement("uploadFile", omNs);
		OMElement idEle = fac.createOMElement("attchmentID", omNs);
		OMElement nameEle = fac.createOMElement("name", omNs);
		
		idEle.setText(attachmentID);
		uploadFile.addChild(nameEle);
		uploadFile.addChild(idEle);
		
		env.getBody().addChild(uploadFile);
		mc.setEnvelope(env);
```
aber das funktioniert so nicht...geht wohl nur auf der ClientSeite.


----------

