Skip to main content

Issue reading SOAP message with attachment

7 replies [Last post]
xxiemeciel
Offline
Joined: 2007-08-29
Points: 0

Hi,

I have an issue with the SOAP with attachment API in javax.xml.soap

I try to create a SOAP message with attachment into a file :

Quote:

final MessageFactory factory = MessageFactory.newInstance();

SOAPMessage message = factory.createMessage();

message.getSOAPHeader().setTextContent( "Dummy header" );
final SOAPBody body = message.getSOAPBody();
DocumentBuilderFactory docFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

Document d = docBuilder.newDocument();

Element rootEl = d.createElement( "Element01" );
Element inCovEl = d.createElement( "Element02" );
Element covEl = d.createElement( "Element03" );
Element titleEl = d.createElement( "Element04" );
titleEl.setTextContent( "titre" );
Element refEl = d.createElement( "Element05" );
refEl.setAttribute( "attrib01", "attachment01" );
refEl.setAttribute( "attrib02", "test" );

covEl.appendChild( titleEl );
covEl.appendChild( refEl );

inCovEl.appendChild( covEl );

rootEl.appendChild( inCovEl );

d.appendChild( rootEl );

body.addDocument( d );
AttachmentPart att = message.createAttachmentPart();
att.setContentId( "attachment01" );
File fileAtt = new File( "attachment01.txt" );
if ( fileAtt.exists() )
{
fileAtt.delete();

}
fileAtt.createNewFile();
FileWriter writer = new FileWriter( fileAtt );
writer.write( "This is the attachement file." );
writer.flush();
InputStream in = new FileInputStream( fileAtt );
att.setRawContent( in, "text" );

message.addAttachmentPart( att );

message.writeTo( out );

At this level, message.countAttachment() return 1.

This is the output result I have ( I am not a SOAP and MIME expert so I assumed it is good )

Quote:

------=_Part_0_18303751.1192033037825
Content-Type: text/xml; charset=utf-8

Dummy Header

titre

------=_Part_0_18303751.1192033037825
Content-Type: text
Content-ID: attachment01

This is the attachement file.
------=_Part_0_18303751.1192033037825--

When I try to read the created message, I proceed like this :

Quote:

final MessageFactory factory = MessageFactory.newInstance();

final SOAPMessage message =
factory.createMessage( null, request.getInputStream() );

int count = message.countAttachment()

And here count == 0.

I really don't understand why I cannot recover the original SOAPMessage when I read the file I created with writeTo.

Thanks
Vincent

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
syedrifai
Offline
Joined: 2008-12-03
Points: 0

so some code like this is used :
----------------------------------------
MimeHeaders headers = new MimeHeaders();

String key, value;

// Header field 0 is the status line so we skip it.

int i = 1;

while (true) {
key = httpConnection.getHeaderFieldKey(i);
value = httpConnection.getHeaderField(i);

if (key == null && value == null)
break;

if (key != null) {
StringTokenizer values =
new StringTokenizer(value, ",");
while (values.hasMoreTokens())
headers.addHeader(key, values.nextToken().trim());
}
i++;
}

[b]i am not able to understand this code on particularly httpConnection.[/b]

Client Code

package soap.message;

import javax.activation.DataHandler;
import javax.xml.namespace.QName;
import javax.xml.soap.*;

import java.util.*;
import java.net.URL;

public class RequestClear {

public static void main(String[] args)
{
try
{
SOAPFactory soapFactory = SOAPFactory.newInstance();
MessageFactory messageFactory = MessageFactory.newInstance();

// Creating a Message
SOAPMessage message = messageFactory.createMessage();
// Retrieve a SOAP Part
SOAPPart soapPart = message.getSOAPPart();
// Retrieve a SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();

// Retrieve a SOAP Header and Body & delete header
SOAPHeader header = message.getSOAPHeader();
SOAPBody body = message.getSOAPBody();
header.detachNode(); // delete the header (header is optional)

// Creating Body Element
QName bodyName = new QName("http://wombat.ztrade.com", "GetLastTradePrice", "m");
SOAPBodyElement bodyElement = body.addBodyElement(bodyName);

// there is still no content in bodyElement

QName name = new QName("symbol");
SOAPElement symbol = bodyElement.addChildElement(name);
symbol.addTextNode("SUNW");

// add attachmentPart to SOAPMessage : text
String sContent = "String Attachments Demo";
AttachmentPart attachmentPartA = message.createAttachmentPart();
attachmentPartA.setContent(sContent, "text/plain");
attachmentPartA.setContentId("demo_attajchment");
message.addAttachmentPart(attachmentPartA);

// add attachmentPart to SOAPMessage : image
URL url = new URL("file:/C:/icon.jpg");
DataHandler dataHandler = new DataHandler(url);
AttachmentPart attachment2 = message.createAttachmentPart(dataHandler);
attachment2.setContentId("attached_image");
message.addAttachmentPart(attachment2);

// Creating a SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection connection = soapConnectionFactory.createConnection();

String endpoint = "http://localhost:8080/WebServiceProject_SAAJ/TryReceive1";
SOAPMessage response = connection.call(message, endpoint);
connection.close();

System.out.println("send completed");

} catch (Exception ex) {
ex.printStackTrace();
}
}
}

my Servlet code:

package com.message.receiver;
import java.io.*;
import java.net.*;
import java.util.Iterator;
import javax.activation.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.soap.*;

public class TryReceive1 extends HttpServlet
{
static MessageFactory msgFactory = null;

SOAPMessage message;

public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{

doPost(req, resp);
}

public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
Writer output = null;
String text = "";
File file = new File("c:\\write.txt");
output = new BufferedWriter(new FileWriter(file));
try
{

msgFactory = MessageFactory.newInstance();

InputStream is = req.getInputStream();
SOAPMessage msg = msgFactory.createMessage([b]new MimeHeaders(),[/b] is);

Iterator it = msg.getAttachments();
if(!it.hasNext())
text=text+"No attachment....";
else
{
while(it.hasNext())
{
text=text+it.next().toString();
}
}

while(it.hasNext())
{

AttachmentPart attachmentPart = (AttachmentPart) it.next();
String id = attachmentPart.getContentId();
String type = attachmentPart.getContentType();

System.out.println("id :" + id + "\t content type : " + type );
}

System.out.println("parsing completed");

// resp.setStatus(HttpServletResponse.SC_OK);
// resp.setHeader("Content-Type", "text/xml");
//
// OutputStream os = resp.getOutputStream();
//
// msg.writeTo(os);
// os.flush();

} catch (Exception e)
{
text=text+"; "+e.toString();
e.printStackTrace();
}
output.write(text);
output.close();
}
}

MimeHeaders is not determine here. but InputStream is coiming properly.

How to make SoapMessage using this two

It prints "No attachment.."

Pls reply me
[b]output[/b]

Content of the message:

------=_Part_0_28061596.1228364835546
Content-Type: text/xml; charset=utf-8

SUNW
------=_Part_0_28061596.1228364835546
Content-Type: text/plain
Content-ID: demo_attajchment

String Attachments Demo
------=_Part_0_28061596.1228364835546
Content-Type: image/jpeg
Content-ID: attached_image

ÿØÿà

Dec 4, 2008 9:57:15 AM com.sun.xml.internal.messaging.saaj.client.p2p.HttpSOAPConnection post
WARNING: SAAJ0014: Invalid reply message. Content length of reply was zero.

Message was edited by: syedrifai

Message was edited by: syedrifai

Message was edited by: syedrifai

kumarjayanti
Offline
Joined: 2003-12-10
Points: 0

Hi,

You are right, the boundary parameter is something that is generated randomly and you cannot know it beforehand.

However the way to read such messages is by making use of the info in Transport Headers. So for example when you do SOAPConnection.call() it will be able to return you a MultiPart SOAPMessage correctly because it would read the Transport Headers to find out the Content-Type info.

so some code like this is used :
----------------------------------------
MimeHeaders headers = new MimeHeaders();

String key, value;

// Header field 0 is the status line so we skip it.

int i = 1;

while (true) {
key = httpConnection.getHeaderFieldKey(i);
value = httpConnection.getHeaderField(i);

if (key == null && value == null)
break;

if (key != null) {
StringTokenizer values =
new StringTokenizer(value, ",");
while (values.hasMoreTokens())
headers.addHeader(key, values.nextToken().trim());
}
i++;
}

If you want we also have a sample which tries to save a Multipart SOAPMessage and reload it :

http://fisheye5.cenqua.com/browse/saaj/saaj-ri/samples/saveandload/src/S...
http://fisheye5.cenqua.com/browse/saaj/saaj-ri/samples/persister/src/com...

thanks.

xxiemeciel
Offline
Joined: 2007-08-29
Points: 0

Thanks,

the few examples help me a lot to complete my code, it works fine.

Regards,
Vincent

kumarjayanti
Offline
Joined: 2003-12-10
Points: 0

Hi,

Reading a Multipart Mime Packaged message using :

final SOAPMessage message =
factory.createMessage( null, request.getInputStream() );

is always a problem because you have not supplied the MimeHeaders argument. Specifically the Content-Type Mime Header is required when you want to read a mutlipart message. Otherwise the behavior of the createMessage can be undetermined.

For your case i just tried to save the message in a file "soap.xml" and i tried to read it as follows :

MessageFactory mf = MessageFactory.newInstance();
MimeHeaders hdrs = new MimeHeaders();
hdrs.addHeader("Content-Type", "multipart/related; boundary=\"----=_Part_0_18303751.1192033037825\"");
SOAPMessage sm = mf.createMessage(hdrs, new FileInputStream("E:\\LATESTBUGS\\soap.xml"));
System.out.println("Attachments=" + sm.countAttachments());

And here is the output :

Attachments=1

So what you really need to do is save the MimeHeaders as well and supply it to createMessage.

thanks.

dcx20
Offline
Joined: 2011-11-28
Points: 0

Great help thanks

xxiemeciel
Offline
Joined: 2007-08-29
Points: 0

Hi,

thanks for the response, I just don't understand how I can know the boundary part (boundary=\"----=_Part_0_18303751.1192033037825\"") before receiving the message.

is there a way to be able to receive this kind of message if I don't know the boundary ?

Regards,
Vincent

dcx20
Offline
Joined: 2011-11-28
Points: 0

You can get the header value from the http request.

I made a simple example which created a Soap message with attachments, wrote it to a string, and tried to reconstruct the message from the string. In that case, the content-type was available in message.getAllHeaders.