BlackBerry Forums Support Community
              

Closed Thread
 
Thread Tools
Old 05-22-2008, 02:49 AM   #1
AniketAnikhindi
New Member
 
Join Date: Apr 2008
Location: Pune, India
Model: 8830
PIN: N/A
Carrier: Sprint
Posts: 12
Default SwA (SOAP with Attachment): Extracting attached binary content from SwA response

Please Login to Remove!

AIM: To be able to extract the binary file that is part of a SwA (SOAP with Attachment) response via a client running on the BlackBerry.

I have the following setup:

An Axis2/Java web service that serves a binary file. I have referred the tutorial accessible at: Downloading a Binary File from a Web Service using Axis2 and SOAP with Attachments | WSO2 Oxygen Tank. Web service works fine, and I am also able to download the binary file using the J2SE client code thats part of the tutorial. (The source code for web service and J2SE client are available for download at the mentioned URL).

I need help in getting the binary file which is part of the SwA (SOAP with Attachment) response.

The client code that I have written is able to retrieve the XML part of the response returned by the service, and is able to query web services and get data of if data type is primitive (string, int etc.).

Am pasting the relevant sources of my codebase for reference:


UI thread:

Code:
import java.io.ByteArrayInputStream;

import wsdemo.util.ConnectionThread;
import wsdemo.util.ResponseHandler;

import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.component.Status;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.xml.jaxp.SAXParserImpl;

public class DownloadFileWebServiceDemoScreen extends MainScreen {

  protected boolean sending = false;
  
  private ConnectionThread connThread;
  private BasicEditField input = new BasicEditField("Input:  ", "");
  private BasicEditField response = new BasicEditField("Response:  ", "");
  private BasicEditField xmlResponse = new BasicEditField("xml:  ", "");
  private ButtonField sendButton = new ButtonField("Download");
  
  public DownloadFileWebServiceDemoScreen(ConnectionThread connThread) {
    this.connThread = connThread;
    setTitle("Download File Web Service Demo");
    FieldListener sendListener = new FieldListener();
    sendButton.setChangeListener(sendListener);
    response.setEditable( false );
    xmlResponse.setEditable( false );
    add(input);
    add(new SeparatorField());
    add(sendButton);
    add(new SeparatorField());
    add(response);
    add(new SeparatorField());
    add(xmlResponse);
  }

  public boolean onClose() {
    close();
    return true;
  }

  private String getRequestParameters() {
    StringBuffer sb = new StringBuffer();
    sb.append("getStats?project=");
    sb.append(input.getText());
    return sb.toString();
  }

  private void parseResults( String xml ){
    SAXParserImpl saxparser = new SAXParserImpl();
    ResponseHandler handler = new ResponseHandler();
    ByteArrayInputStream stream = new ByteArrayInputStream(xml.getBytes());
    try {
      saxparser.parse( stream, handler );
    } catch ( Exception e ) {
      response.setText( "Unable to parse response.");
    }
    response.setText( handler.response );
  }

  //Inner class used to track the button clicks
  class FieldListener implements FieldChangeListener {
    public void fieldChanged(Field field, int context) {
      String url = null;
      StringBuffer sb = new StringBuffer("Sending...");
      
      //Access the Download File Service (ref: tutorial 'http://wso2.org/library/1675')
      //e.g: "http://192.168.1.4:8080/axis2/services/StatisticsService/getStats?project=axis2"
      
      url = "http://192.168.1.4:8080/axis2/services/StatisticsService/" + getRequestParameters();
      connThread.get(url);
      while (connThread.sending) {
        try {
          Status.show( sb.append(".").toString() );
          Thread.sleep(100);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }

      if (connThread.sendResult) {
        Status.show("Transmission Successful");
        xmlResponse.setText( connThread.responseContent );
        parseResults( connThread.responseContent );
      } else {
        Status.show("Transmission Failed");
      }
    }
  }
  
}

Connection Thread:
Code:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.microedition.io.Connector;
import javax.microedition.io.HttpConnection;

public class ConnectionThread extends Thread {

  private boolean start = false;
  private boolean stop = false;
  private String url;
  private String data;
  public boolean sendResult = false;
  public boolean sending = false;
  private String requestMode = HttpConnection.POST;
  public String responseContent;

  public void run() {
    while (true) {
      if (start == false && stop == false) {
        try {
          sleep(200);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      } else if (stop) {
        return;
      } else if (start) {
        http();
      }
    }
  }

  private void getResponseContent( HttpConnection conn ) throws IOException {
    responseContent = "";
    
    InputStream is = null;
    is = conn.openInputStream();

    byte[] data = new byte[10240];
    int bytesread = 0;
    try {
      bytesread = is.read(data);
      responseContent = new String(data);
    } catch (Exception e) {
      responseContent = e.getMessage();
    }
    
    
  }

  private void http() {
    System.out.println( url );
    HttpConnection conn = null;
    OutputStream out = null;
    int responseCode;

    try {
      conn = (HttpConnection) Connector.open(url);
      conn.setRequestMethod(requestMode);
      out = conn.openOutputStream();
      out.write(data.getBytes());
      out.flush();
      responseCode = conn.getResponseCode();

      if (responseCode != HttpConnection.HTTP_OK) {
        sendResult = false;
        responseContent = null;
      } else {
        sendResult = true;
        getResponseContent( conn );
      }
      start = false;
      sending = false;
    } catch (IOException e) {
      start = false;
      sendResult = false;
      sending = false;
    }
  }

  public void get(String url) {
    this.url = url;
    this.data = "";
    requestMode = HttpConnection.GET;
    sendResult = false;
    sending = true;
    start = true;
  }

  public void post(String url, String data) {
    this.url = url;
    this.data = data;
    requestMode = HttpConnection.POST;
    sendResult = false;
    sending = true;
    start = true;
  }

  public void stop() {
    stop = true;
  }

}

I'm not using any third party library like kSOAP2. As far as possible I would like to keep it that way, but please do suggest if any third party library (including kSOAP2) would make life easier?


Thanks,
Aniket
Offline  
Old 05-27-2008, 11:51 PM   #2
JSanders
Crimson Tide Moderator
 
JSanders's Avatar
 
Join Date: Oct 2004
Location: North of the moss line
Model: Z30
OS: 7.0sumtin
PIN: t low
Carrier: Verizon
Posts: 41,921
Default

bump for this user
Offline  
Old 05-28-2008, 03:08 AM   #3
simon.hain
CrackBerry Addict
 
Join Date: Apr 2005
Location: hamburg, germany
Model: 8900
Carrier: o2
Posts: 838
Default

maybe this thread from the ksoap2 forum can help you.

p.s. i answered despite your pushy PM
__________________
java developer, Devinto, hamburg/germany

Last edited by simon.hain; 05-28-2008 at 03:10 AM..
Offline  
Old 05-28-2008, 04:25 AM   #4
jfisher
CrackBerry Addict
 
Join Date: Jun 2005
Location: Manchester, UK
Model: BOLD
Carrier: t-mobile
Posts: 714
Default

got that too - i ignore those emails usually - maybe we should get a mod to add a sticky about not doing that....
__________________
new job doesn't allow a public profile - please do not contact this user with questions, you will not get a response. good luck!
Offline  
Old 05-28-2008, 06:26 AM   #5
AniketAnikhindi
New Member
 
Join Date: Apr 2008
Location: Pune, India
Model: 8830
PIN: N/A
Carrier: Sprint
Posts: 12
Default regarding PMs for this thread..

being new to the forum, i'm still learning the etiquette here. sorry for the spam.

a few things that i did before sending around 6 people the same PM:

a) waited for a week for a reply - time was running out for me.
b) searched for people who had responded to SOAP related queries in the past (except for JSanders - that was a mistake)

many thanks to JSanders and simon.

Regards,
Aniket

Last edited by AniketAnikhindi; 05-30-2008 at 10:16 AM..
Offline  
Old 05-30-2008, 10:15 AM   #6
AniketAnikhindi
New Member
 
Join Date: Apr 2008
Location: Pune, India
Model: 8830
PIN: N/A
Carrier: Sprint
Posts: 12
Question

On querying the web service from which I expect to download binary content using SOAP with Attachments, I get the following XML response at the client end:

Code:
<swa:getStatsResponse xmlns:swa="http://service.sample/xsd">
  <swa:projectName>Apache Axis2</swa:projectName>
  <swa:month>2007 January</swa:month>
  <swa:downloads>34000</swa:downloads>
  <swa:graph href="cid:urn:uuid:F12ADB3500A9B80EDE1211954919086" />
</swa:getStatsResponse>
From the above XML Response, I can extract the attachment id from the 'href' part of the swa:graph tag.

The binary attachment needs this attachmentId for identification, to be pulled out of the SwA response.

I have 2 questions at this stage:
1) I used SmartSniff, and saw that all I was getting at my client end was the above XML Response when I queried the server. If I am not able to get the entire response, how do I even extract the attachment out of it?

2) If I manage to get the attachment part of the response, how exactly would I be able to retrieve it?


I referred to the J2SE Apache Axis Client code that gets the binary attachment using SwA. Doing it on the BlackBerry is the task at hand..

For reference, the J2SE code of the Apache Axis client which is used to download the attachment, is as follows:

Code:
import java.io.File;
import java.io.FileOutputStream;

import javax.activation.DataHandler;
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.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
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.MessageContext;
import org.apache.axis2.wsdl.WSDLConstants;

public class StatisticsServiceClient {
  private static EndpointReference targetEPR = new EndpointReference(
    "http://localhost:8080/axis2/services/StatisticsService");

  public static void main(String[] args) throws Exception {
    if (args.length == 1) {
      System.out.println(args[0]);
      getMonthlyDownloadStats(args[0]);
    } else {
      throw new IllegalArgumentException("Please provide the project name as an argument.");
    }
  }

  public static void getMonthlyDownloadStats(String projectName) throws Exception {
    Options options = new Options();
    options.setTo(targetEPR);
    options.setAction("urn:getStats");
    options.setSoapVersionURI(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
    
    
    // Increase the time out to receive large attachments
    options.setTimeOutInMilliSeconds(10000);
    
    ServiceClient sender = new ServiceClient();
    sender.setOptions(options);
    OperationClient mepClient = sender.createClient(ServiceClient.ANON_OUT_IN_OP);
        
    MessageContext mc = new MessageContext();
    SOAPEnvelope env = createEnvelope(projectName);
    mc.setEnvelope(env);
        
    mepClient.addMessageContext(mc);
    mepClient.execute(true);
    
    // Let's get the message context for the response
    MessageContext response = mepClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
    SOAPBody body = response.getEnvelope().getBody();
    OMElement element = body.getFirstChildWithName(new QName("http://service.sample/xsd","getStatsResponse"));
    if (element!=null) {
      processResponse(response, element);
    } else {
      throw new Exception("Malformed response.");
    }
  }

  private static void processResponse(MessageContext response, OMElement element) throws Exception {
    System.out.println("Project Name : " + element.getFirstChildWithName(new QName("http://service.sample/xsd","projectName")).getText());
    System.out.println("Month : " + element.getFirstChildWithName(new QName("http://service.sample/xsd","month")).getText());
    System.out.println("Downloads : " + element.getFirstChildWithName(new QName("http://service.sample/xsd","downloads")).getText());

    OMElement graphElement = element.getFirstChildWithName(new QName("http://service.sample/xsd","graph"));
    //retrieving the ID of the attachment
    String graphImageID = graphElement.getAttributeValue(new QName("href"));
    //remove the "cid:" prefix
    graphImageID = graphImageID.substring(4);
    //Accesing the attachment from the response message context using the ID
    System.out.println(graphImageID);
    DataHandler dataHandler = response.getAttachment(graphImageID);
    if (dataHandler!=null){
      // Writing the attachment data (graph image) to a file
      File graphFile = new File("responseGraph.png");
      FileOutputStream outputStream = new FileOutputStream(graphFile);
      dataHandler.writeTo(outputStream);
      outputStream.flush();
      System.out.println("Download statistics graph saved to :" + graphFile.getAbsolutePath());
    } else {
      throw new Exception("Cannot find the data handler.");
    }
  }

  private static SOAPEnvelope createEnvelope(String destinationFile) {
    SOAPFactory fac = OMAbstractFactory.getSOAP11Factory();
    SOAPEnvelope env = fac.getDefaultEnvelope();
    OMNamespace omNs = fac.createOMNamespace("http://service.sample/xsd", "swa");
    OMElement statsElement = fac.createOMElement("getStats", omNs);
    OMElement nameEle = fac.createOMElement("projectName", omNs);
    nameEle.setText(destinationFile);
    statsElement.addChild(nameEle);
    env.getBody().addChild(statsElement);
    return env;
  }
}
Offline  
Old 06-03-2008, 06:17 AM   #7
AniketAnikhindi
New Member
 
Join Date: Apr 2008
Location: Pune, India
Model: 8830
PIN: N/A
Carrier: Sprint
Posts: 12
Thumbs up Eureka..

Got things to work guys!

Thanks for all the support and standing by. Very soon will post a detailed article on what I learnt in the process and will put up a tutorial..

Yeah, feels great to get that roadblock outta my way. Now for some fun!

Cheers,
Aniket
Offline  
Closed Thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


New Sealed Allen Bradley 1766-MM1 Ser B MicroLogix 1400 Memory Module AB 1766MM1 picture

New Sealed Allen Bradley 1766-MM1 Ser B MicroLogix 1400 Memory Module AB 1766MM1

$135.00



Voice Activated Listening Device Audio 150 Day Battery Spy Recorder 16 GB picture

Voice Activated Listening Device Audio 150 Day Battery Spy Recorder 16 GB

$109.00



1766-MM1 AB MicroLogix 1400 Memory Module 1766-MM1 Spot Goods #XG2 picture

1766-MM1 AB MicroLogix 1400 Memory Module 1766-MM1 Spot Goods #XG2

$160.99



New Factory Sealed AB 1756-L61 SER B ControlLogix 2MB Memory Controller 1756L61 picture

New Factory Sealed AB 1756-L61 SER B ControlLogix 2MB Memory Controller 1756L61

$304.69



1PCS Memory iButton IC DALLAS/MAXIM DS1994L-F5 DS1994L+F5 DS1994L-F5+ picture

1PCS Memory iButton IC DALLAS/MAXIM DS1994L-F5 DS1994L+F5 DS1994L-F5+

$183.20



AVNET ULTRAZED SOM ZYNQ ULTRASCALE+ XCZU3EG SYSTEM ON MODULE -  picture

AVNET ULTRAZED SOM ZYNQ ULTRASCALE+ XCZU3EG SYSTEM ON MODULE -

$98.67







Copyright © 2004-2016 BlackBerryForums.com.
The names RIM © and BlackBerry © are registered Trademarks of BlackBerry Inc.