Showing posts with label Axis2. Show all posts
Showing posts with label Axis2. Show all posts

Tuesday, May 29, 2012

Writing a Apache Axis2 Module

As intern at WSO2 we learn lot about Apache Axis 2, because my team at WSO2 works on a product called Application Server  which is based on Axis2. So we have to play a lot with Axis2. The most interesting thing I have done with Axis2 is extending by writing a module to it. Here I am going to talk about how to do it. I will explain how I did it.

Before read this article about Writing a Module, Better you read these articles to get a better picture about Apache Axis 2 and it's underlining architecture,

What is Apache Axis2 :
http://axis.apache.org/axis2/java/core/

How to write a Apache Axis2 Web Service :
http://wso2.org/library/95

What is a Apache Axis2 Module :
http://axis.apache.org/axis2/java/core/docs/Axis2ArchitectureGuide.html

Also there is a interesting book written by Mr Afkham Azeez and Mr Deepal Jayasinghe. It explain all about Apache Axis2. Please read it to have 100% understanding about Axis 2. The book is Apache Axis2 Web Services, 2nd Edition.

If you have read those articles or had prior knowledge you can understand that a module will add some functionality to the execution chain of axis2 handlers. Single module can have more than one handler. So here in this example I will explain how I wrote my simple axis2 module 2 print the SOAP message content to the info log.

To follow this article you need to have a web services hosted in the simple axis2 server provided by the axis2 distribution. I have add a simple web service to my axis2 server and it is up and running when I start writing the module.  Here are the steps I followed to create and run my web Service.

Definition of My Web Services :

package org.wso2.testws;
public class TestWebService {
    public String sayHello(String name) {
        return "Hello " + name;
    }
    public int add(int x,int y){
        return x+y;
    }
}


My services.xml file :

<service name="TestWebService" >
    <Description>
        This web Service is written for test the functionlity of a AXIS2 Module
    </Description>
    <messageReceivers>
        <messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver" />
        <messageReceiver  mep="http://www.w3.org/2004/08/wsdl/in-out"  class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
    </messageReceivers>
    <parameter name="ServiceClass" locked="false">org.wso2.testws.TestWebService</parameter>
</service>


My Folder Stricture :

TestWebService >
      TestWebService.java
      Temp>
           META-INF>
                services.xml
           org>
                wso2>
                     testws>
                          TestWebService.class

After having all these I build my TestWebService.aar file using this command,

jar -cvf TestWebService.aar *

Then I copied that archive to the repository/services folder of the axis2 home folder. Then I run the axis2server.sh script to run the simple server. Then you can see that my new service is successfully deployed.

After that we can start the development of the Axis2 Module. For that purpose I use the Eclipse IDE. Create a new java project in Eclipse and have the following structure in your project.

Here you can see that Axis2 has been added as a library to the project. To do it, right click on the project and got to Build Path > Configure Build Path. There you can find a button called Add Library, click on it and select User Library in the appearing screen. There go to new and add all the jar files in the lib folder in the axis2 home folder.

Then the definition of the TestModule.java is this,

package org.wso2.testa2m;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.description.AxisDescription;
import org.apache.axis2.description.AxisModule;
import org.apache.axis2.modules.Module;
import org.apache.neethi.Assertion;
import org.apache.neethi.Policy;

public class TestModule implements Module{

    public void init(ConfigurationContext configContext, AxisModule module) throws AxisFault {
    }

    public void engageNotify(AxisDescription axisDescription) throws AxisFault {
    }

    public void shutdown(ConfigurationContext configurationContext) throws AxisFault {
    }
    
    public String[] getPolicyNamespaces() {
        return null;    
    }

    public void applyPolicy(Policy policy, AxisDescription axisDescription) throws AxisFault {
    }
           
    public boolean canSupportAssertion(Assertion assertion) {
        return true;
    }
}

The definition of the TestHandler.java is this,

package org.wso2.testa2m;

import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.engine.Handler;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TestHandler extends AbstractHandler implements Handler{
    private static final Log log = LogFactory.getLog(TestHandler.class);
    private String name;

    public String getName() {
        return name;
    }

    public InvocationResponse invoke(MessageContext msgContext) throws AxisFault {
        log.info("The web service "+msgContext.getAxisService().toString()+".");
        log.info("The operation is "+msgContext.getAxisOperation().toString()+".");
        log.info("This is the SOAP envelop : "+msgContext.getEnvelope().toString());
        return InvocationResponse.CONTINUE;        
    }

    public void revoke(MessageContext msgContext) {
        log.info("The web service "+msgContext.getAxisService().toString()+".");
        log.info("The operation is "+msgContext.getAxisOperation().toString()+".");
        log.info("This is the SOAP envelop : "+msgContext.getEnvelope().toString());
    }

    public void setName(String name) {
        this.name = name;
    }
}


After doing these, go the eclipse project folder in your machine, then in the TestModule folder you can find a folder called bin which has the generated class files of the project. Go inside it and create a folder called META-INF. In side it create the module.xml file. This is the definition of that file,

<module name="TestModule" class="org.wso2.testa2m.TestModule">
    <InFlow>
        <handler name="InFlowLogHandler" class="org.wso2.testa2m.TestHandler">
            <order phase="TestPhase"/>
        </handler>
    </InFlow>

    <OutFlow>
        <handler name="OutFlowLogHandler" class="org.wso2.testa2m.TestHandler">
            <order phase="TestPhase"/>
        </handler>
    </OutFlow>

    <OutFaultFlow>
        <handler name="FaultOutFlowLogHandler" class="org.wso2.testa2m.TestHandler">
            <order phase="TestPhase"/>
        </handler>
    </OutFaultFlow>

    <InFaultFlow>
        <handler name="FaultInFlowLogHandler" class="org.wso2.testa2m.TestHandler">
            <order phase="TestPhase"/>
        </handler>
    </InFaultFlow>
</module>

After doing that your now in a position to create your module archive file. Go to bin folder of your project using terminal and execute foll wing command,

jar -cvf TestModule.mar *

It will create the archive file needed. Copy it to the repository/modules folder of your axis2 home folder. Now your module is ready to be deployed. Now you have to do some configuration to execute your module. Conceptually Apache Axis2 modules can be executed in two ways,
  • Globally for all the services hosted in Axis2. To do this you have to edit the axis2.xml file
  • Per Service. To do this you have to edit the services.xml file also.
You can find axis2.xml file in the conf folder of axis2 home folder. Edit it like this to add your custom phases to the configuration. In the phases section add the entries which are highlighted to add your definition of custom phase called "TestPhase",

    <!-- ================================================= -->
    <!-- Phases  -->
    <!-- ================================================= -->
    <phaseOrder type="InFlow">
        <!--  System predefined phases       -->
        <phase name="Transport">
            <handler name="RequestURIBasedDispatcher"
                     class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher">
                <order phase="Transport"/>
            </handler>
            <handler name="SOAPActionBasedDispatcher"
                     class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher">
                <order phase="Transport"/>
            </handler>
        </phase>
        <phase name="Addressing">
            <handler name="AddressingBasedDispatcher"
                     class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
                <order phase="Addressing"/>
            </handler>
        </phase>
        <phase name="Security"/>
    <!-- +++++++Cutome Pahse I have Added+++++++  -->
     <phase name="TestPhase"/>
    <!-- +++++++++++++++++++++++++++++++++++++++ -->
        <phase name="PreDispatch"/>
        <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
            <handler name="RequestURIBasedDispatcher"
                     class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
            <handler name="SOAPActionBasedDispatcher"
                     class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
            <handler name="RequestURIOperationDispatcher"
                     class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
            <handler name="SOAPMessageBodyBasedDispatcher"
                     class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
            <handler name="HTTPLocationBasedDispatcher"
                     class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
            <handler name="GenericProviderDispatcher"
                     class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
            <handler name="MustUnderstandValidationDispatcher"
                     class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
        </phase>
        <phase name="RMPhase"/>
        <!--  System predefined phases       -->
        <!--   After Postdispatch phase module author or service author can add any phase he want      -->
        <phase name="OperationInPhase">
            <handler name="MustUnderstandChecker"
                     class="org.apache.axis2.jaxws.dispatchers.MustUnderstandChecker">
                <order phase="OperationInPhase"/>
            </handler>
        </phase>
        <phase name="soapmonitorPhase"/>
    </phaseOrder>
    <phaseOrder type="OutFlow">
        <!--      user can add his own phases to this area  -->
        <phase name="soapmonitorPhase"/>
        <phase name="OperationOutPhase"/>
        <!--system predefined phase-->
        <!--these phase will run irrespective of the service-->
        <phase name="RMPhase"/>
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
        <phase name="Security"/>
    <!-- +++++++Cutome Pahse I have Added+++++++  -->
     <phase name="TestPhase"/>
    <!-- +++++++++++++++++++++++++++++++++++++++ -->
    </phaseOrder>
    <phaseOrder type="InFaultFlow">
        <phase name="Addressing">
            <handler name="AddressingBasedDispatcher"
                     class="org.apache.axis2.dispatchers.AddressingBasedDispatcher">
                <order phase="Addressing"/>
            </handler>
        </phase>
        <phase name="Security"/>
    <!-- +++++++Cutome Pahse I have Added+++++++  -->
     <phase name="TestPhase"/>
    <!-- +++++++++++++++++++++++++++++++++++++++ -->
        <phase name="PreDispatch"/>
        <phase name="Dispatch" class="org.apache.axis2.engine.DispatchPhase">
            <handler name="RequestURIBasedDispatcher"
                     class="org.apache.axis2.dispatchers.RequestURIBasedDispatcher"/>
            <handler name="SOAPActionBasedDispatcher"
                     class="org.apache.axis2.dispatchers.SOAPActionBasedDispatcher"/>
            <handler name="RequestURIOperationDispatcher"
                     class="org.apache.axis2.dispatchers.RequestURIOperationDispatcher"/>
            <handler name="SOAPMessageBodyBasedDispatcher"
                     class="org.apache.axis2.dispatchers.SOAPMessageBodyBasedDispatcher"/>
            <handler name="HTTPLocationBasedDispatcher"
                     class="org.apache.axis2.dispatchers.HTTPLocationBasedDispatcher"/>
            <handler name="GenericProviderDispatcher"
                     class="org.apache.axis2.jaxws.dispatchers.GenericProviderDispatcher"/>
            <handler name="MustUnderstandValidationDispatcher"
                     class="org.apache.axis2.jaxws.dispatchers.MustUnderstandValidationDispatcher"/>
        </phase>
        <phase name="RMPhase"/>
        <!--      user can add his own phases to this area  -->
        <phase name="OperationInFaultPhase"/>
        <phase name="soapmonitorPhase"/>
    </phaseOrder>
    <phaseOrder type="OutFaultFlow">
        <!--      user can add his own phases to this area  -->
        <phase name="soapmonitorPhase"/>
        <phase name="OperationOutFaultPhase"/>
        <phase name="RMPhase"/>
        <phase name="PolicyDetermination"/>
        <phase name="MessageOut"/>
        <phase name="Security"/>
    <!-- +++++++Cutome Pahse I have Added+++++++  -->
     <phase name="TestPhase"/>
    <!-- +++++++++++++++++++++++++++++++++++++++ -->
    </phaseOrder>

After doing that you are successfully introduced the phase you have created manually, Now it is time to define the execution type of your module,
To excute it globally, add the <module ref="TestModule"/> entry to to the Global section of the axis2.xml.

    <!-- ================================================= -->
    <!-- Global Modules  -->
    <!-- ================================================= -->
    <!-- Comment this to disable Addressing -->
    <module ref="addressing"/>
    <module ref="TestModule"/>
    <!--Configuring module , providing parameters for modules whether they refer or not-->
    <!--<moduleConfig name="addressing">-->
    <!--<parameter name="addressingPara">N/A</parameter>-->
    <!--</moduleConfig>--> 

If you want to add a module specially for a service, add <module ref="TestModule"/> to the service.xml file. Then it will only executed only for that service.
Now your custom module is sucessfully deployed. Now you can start your axis2server again. It will show following log message if your module is successfully loaded. 

[INFO] Deploying module: TestModule - file:/home/andunslg/My_Works/Axis2_Code/modules/distribution/target/axis2-1.7.0-SNAPSHOT/repository/modules/TestModule.mar

After that to check it's functionality use the soapUI. Copy your web service's WSDL files link and create a soapUI project using that. If you are successful you will have a project which looks like this,


Double click on add,  it will show you are SOAP message. Add parameters to the add function and send it. The web service will reply to your message if you have successfully did all the things. If it is this kind of reply will come,


To see what your module to you have to see in to your terminal where you run the axis2server. In that you can see that following log entries are shown. Those are generated by the module you have created.

[INFO] The web service TestWebService.
[INFO] The operation is org.apache.axis2.description.InOutAxisOperation@2ce99681.
[INFO] This is the SOAP envelop : <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tes="http://testws.wso2.org"><soapenv:Body>
      <tes:add>
         <tes:args0>3</tes:args0>
         <tes:args1>2</tes:args1>
      </tes:add>
   </soapenv:Body></soapenv:Envelope>
[INFO] The web service TestWebService.
[INFO] The operation is org.apache.axis2.description.InOutAxisOperation@2ce99681.
[INFO] This is the SOAP envelop : <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns:addResponse xmlns:ns="http://testws.wso2.org"><ns:return>5</ns:return></ns:addResponse></soapenv:Body></soapenv:Envelope>


Up to now you have added custom module to AXIS2 to extend it. You can define any task in side your handler definition to o in your module. If you have any problem please contact me.

Saturday, May 26, 2012

What is Remote Debugging - Java, Eclipse,IntelliJ IDEA, AXIS2

Now I am working as a Software Engineering Intern at WSO2. At the first week of internship with the WSO2 Application Server team, I have learned a pretty cool concept in software development called Remote Debugging of application. I feel that is a pretty strong concept which I should talk about. To learn about remote debugging I have gone through lot of articles all around the Internet. So I thought that getting all those information to one place.
If we look at to the Remote Debugging scenario it will look like this,


Some times you have to debug a application which is not running from it's source code in a IDE. So to do it we use this remote debug concept. In the scenario which is shown above the application runs in a remote machine, but when it runs it will broadcast debug information via a socket deployed. The IDE running locally will capture those broadcast debug information through that socket and it will do the debug through the source code.

JAVA language provides this in its JVM. We can use commands like this to run a application in the remote debug mode in java.

java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,suspend=n,server=y -jar Name_of_Your_Jar.jar

Then it will broadcast some debug information and will wait until some IDE capture those debug information and start debugging the source code. When Some IDE connects to the Socket specified it will start the debugging process.

Configuring the IDEs will depend on them. The links given below will give you a good understanding about those concepts. Hope you learn some thing from this post. Following links are really interesting to learn about remote debugging.

What is Remote Debugging :
http://www.javabeat.net/2010/12/what-is-remote-debugging-in-java/

Remote Debugging with Eclipse :
http://www.eclipsezone.com/eclipse/forums/t53459.html
http://java.dzone.com/articles/how-debug-remote-java-applicat
http://www.myeclipseide.com/documentation/quickstarts/remotedebugging/

Remote Debugging with IntelliJ IDEA :
http://www.javaranch.com/journal/200408/DebuggingServer-sideCode.html

Remote Debugging Web Services, Apache Axis 2 :
http://wso2.org/library/225
http://wso2.org/library/3851
http://amilamanoj.blogspot.com/2011/09/running-debugging-apache-axis2-inside.html
http://shameerarathnayaka.blogspot.com/2011/09/remote-debugging-apache-axis2-with.html

Friday, February 24, 2012

Accessing Apache Axis2 Web service inside a Android Application - Part 2 - Apache Axis 2, Android API 8, phpmyadmin, Eclipse Indigo, VMware Player

Part 2

As I explained in my earlier post,  Accessing Apache Axis2 Web service inside a Android Application - Part 1 you can create a web service. In this post I will explain how to create a android application use this web service. In my example's web service, it can give you details about cities and places in Sri Lanka. So we will query that service to get those data,

Step 1 - Create a new android project in Eclipse.
Step 2 - Add internet permission to the Android Application by editing AndroidManifest.xml file like this.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.web.frontend.calculator"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AndroidFrontendActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Step 3 - Edit the main.xml file like this.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
    <TextView
        android:id="@+id/txtCityLongitude"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtCityLatitude"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtIMLon"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtIMLat"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtIMCat"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
    <TextView
        android:id="@+id/txtIMDes"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

</LinearLayout>


Step 3 - I use KSOAP as my connection between web service and Android App. So download it from here. 

kSOAP2 - An efficient, lean, Java SOAP library for constrained devices

Add it to your android project. Right click on your project go to Java Build Path > Add External Jar
and select kSOAP.

Step 4 - Edit the java activity file like this.

package org.web.frontend.calculator;

import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class AndroidFrontendActivity extends Activity {

    private String METHOD_NAME = "";
    // our webservice method name
    private String NAMESPACE = "http://ws.travel_ceylon.web.org";
    // Here package name in webservice with reverse order.
    private String SOAP_ACTION = NAMESPACE + METHOD_NAME;
    // NAMESPACE + method name
    private static final String URL = "http://192.168.177.130:8080/Travel_Ceylon_Central_Web_Service/services/Travel_Ceylon_Web_Service?wsdl";

    // you must use ipaddress here, don’t use Hostname or localhost

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        String city = "Matara";
        String im = "Galle Face";

        METHOD_NAME = "getLongitude_City";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("city", city);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtCityLongitude)).setText(city
                    + " Longitude is : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtCityLongitude)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }
        METHOD_NAME = "getLatitude_City";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("city", city);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtCityLatitude)).setText(city
                    + " Latitude : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtCityLatitude)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }

        METHOD_NAME = "getLongitude_Im_Place";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("place", im);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtIMLon)).setText(im
                    + " Longitude : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtIMLon)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }

        METHOD_NAME = "getLatitude_Im_Place";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("place", im);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtIMLat)).setText(im
                    + " Latitude : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtIMLat)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }

        METHOD_NAME = "getCategory_Im_Place";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("place", im);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtIMCat)).setText(im
                    + " Category : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtIMCat)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }

        METHOD_NAME = "getDescription_Im_Place";
        try {
            SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
            request.addProperty("place", im);
            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                    SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(request);
            HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
            androidHttpTransport.call(SOAP_ACTION, envelope);
            Object result = envelope.getResponse();
            ((TextView) findViewById(R.id.txtIMDes)).setText(im
                    + " Description : " + result.toString());

        } catch (Exception E) {
            E.printStackTrace();
            ((TextView) findViewById(R.id.txtIMDes)).setText("ERROR:"
                    + E.getClass().getName() + ":" + E.getMessage());
        }
    }
}


I will explain this code like this, Here are the variable assignments,


    private String METHOD_NAME = "";
    // Here you have to put your method you are calling
    // I am calling float getLongitude_City(String city) so I assign this variable like this. METHOD_NAME = "getLongitude_City";
    private String NAMESPACE = "http://ws.travel_ceylon.web.org";
    // Here package name in webservice with reverse order.
    private String SOAP_ACTION = NAMESPACE + METHOD_NAME;
    // NAMESPACE + method name
    private static final String URL = "http://192.168.177.130:8080/Travel_Ceylon_Central_Web_Service/services/Travel_Ceylon_Web_Service?wsdl";

    // you must use ipaddress here, don’t use Hostname or localhost
    // That is why I used a virtual machine to have a small network inside my machine.


Next I will explain the other part of the source,

  METHOD_NAME = "getLongitude_City";

  try {
   SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
   request.addProperty("city", city);
   // Here we bind parmeters to our SOAP packet.
   // in my getLongitude_City"it has a argument called city of Stirng
   // type. This is the way I assigen value to it.

   SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
   SoapEnvelope.VER11);
   envelope.dotNet = true;
   envelope.setOutputSoapObject(request);
   HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
   androidHttpTransport.call(SOAP_ACTION, envelope);
   Object result = envelope.getResponse();
   // Here we get the reposnse from the SOAP object.
   ((TextView) findViewById(R.id.txtCityLongitude)).setText(city
   + " Longitude is : " + result.toString());
  } catch (Exception E) {
   E.printStackTrace();
   ((TextView) findViewById(R.id.txtCityLongitude)).setText("ERROR:"
   + E.getClass().getName() + ":" + E.getMessage());
  }


After doing all these editing. Go to the virtual machine and run the web service. Check the connectivity between virtual machine and your machine. Then run the Android app. then you can see these information come from the web service.


Hope this article helped you. Please put comments about my article. It will help me to improve my articles in the future.

Accessing Apache Axis2 Web service inside a Android Application - Part 1 - Apache Axis 2, Android API 8, phpmyadmin, Eclipse Indigo, VMware Player

Part 1

In this series of articles I am going to show you the complete set of steps to access a web service inside Android application. I am expecting you to have knowledge about following,
  • Create a web service using Apache Axis 2 and Eclipse. (If you don't know here are some useful links : Link1 , Link 2)
  • Create a simple web service client using Axis2 plug in and Eclipse. (If you don't know here are some useful links : Link1)
  • Create a simple android project with text fields to show some texts. (If you don't know here are some useful links : Link1)
  • More importantly you have to have a working virtual machine inside  your machine using something like VMware player. Also you have to have a host only private network with this virtual machine and you machine. Also you have to install Eclipse,Apache axis 2 and tomcat server in this virtual machine.
So having those prerequisites I will continue like this.I am going to create a simple web service which is capable to give data to it users by querying a local database it has.

Step 1- In my example I use a database called travel_ceylon. So In side your virtual machine create a database using phpmyadmin. and import following sql file to that database,

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";

CREATE TABLE IF NOT EXISTS `category` (
  `Category` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `category` (`Category`) VALUES
('History'),
('Religon - Buddhisum'),
('Religon - Catholic'),
('Religon - Islam'),
('Religon - Hindu'),
('Technology'),
('Nature');

CREATE TABLE IF NOT EXISTS `city` (
  `City_Name` varchar(100) NOT NULL,
  `Latitude` float NOT NULL,
  `Longitude` float NOT NULL,
  PRIMARY KEY (`City_Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;


INSERT INTO `city` (`City_Name`, `Latitude`, `Longitude`) VALUES
('Aluthgama', 6.59991, 79.9568),
('Ambalangoda', 6.2367, 80.0544),
('Matara', 5.94413, 80.5494),
('Monaragala', 6.87268, 81.3506),
('Moratuwa', 6.77453, 79.8826),
('Wellawaya', 6.73203, 81.1019);

CREATE TABLE IF NOT EXISTS `close_to` (
  `City_Name` varchar(100) NOT NULL,
  `Place_Name` varchar(100) NOT NULL,
  `Distance` float NOT NULL,
  KEY `City_Name` (`City_Name`,`Place_Name`),
  KEY `Place_Name` (`Place_Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;

CREATE TABLE IF NOT EXISTS `important_places` (
  `Place_Name` varchar(100) NOT NULL,
  `Category` varchar(200) NOT NULL,
  `Description` varchar(500) NOT NULL,
  `Latitude` float NOT NULL,
  `Longitude` float NOT NULL,
  PRIMARY KEY (`Place_Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;

INSERT INTO `important_places` (`Place_Name`, `Category`, `Description`, `Latitude`, `Longitude`) VALUES
('Galle Face', 'Lesuire,History', 'Park', 6.92496, 79.8446),
('Gangaramya Temple', 'Buddhisum,History,Religon', 'A Big Temple in Colombo', 6.91625, 79.8563),
('Viharamahadevia Park', 'Lesuire', 'Park', 6.91379, 79.8626),
('Weherahena Temple', 'Buddhisum,History,Religon', 'Weherahena Temple with a hugh Buddha Satchive', 5.95313, 80.5759);

CREATE TABLE IF NOT EXISTS `important_places_for_approval` (
  `Place_Name` varchar(100) NOT NULL,
  `Category` varchar(150) NOT NULL,
  `Description` varchar(500) NOT NULL,
  `Longitude` float NOT NULL,
  `Latitude` float NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

ALTER TABLE `close_to`
  ADD CONSTRAINT `close_to_ibfk_1` FOREIGN KEY (`City_Name`) REFERENCES `city` (`City_Name`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `close_to_ibfk_2` FOREIGN KEY (`Place_Name`) REFERENCES `important_places` (`Place_Name`) ON DELETE CASCADE ON UPDATE CASCADE;

Step 2 - Create a Dynamic Web Project using Eclipse inside your virtual machine. Put this as your web service definition,

package org.web.travel_ceylon.ws;

import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;

public class Travel_Ceylon_Web_Service {
 private String url;
 private Connection con;
 private Statement stmt;

 public void connectToDB() {
  url = "jdbc:mysql://localhost:3306/travel_ceylon";
  try {
   Class.forName("com.mysql.jdbc.Driver");
   con = (Connection) DriverManager.getConnection(url, "root", "");
  } catch (Exception e) {
   System.out.println("Error - Unable to Connect to the Database" + e);

  }
 }

 public float getLongitude_City(String city) {
  connectToDB();
  float lngt = 0;
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Longitude FROM city WHERE City_Name='"
       + city + "'");
   rs.next();
   lngt = rs.getFloat("Longitude");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get longitude of " + city
     + " :" + e);
  }
  return lngt;
 }

 public float getLatitude_City(String city) {
  connectToDB();
  float latt = 0;
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Latitude FROM city WHERE City_Name='"
       + city + "'");
   rs.next();
   latt = rs.getFloat("Latitude");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get latitude of " + city
     + " :" + e);
  }
  return latt;
 }

 public float getLongitude_Im_Place(String place) {
  connectToDB();
  float lngt = 0;
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Longitude FROM important_places WHERE Place_Name='"
       + place + "'");
   rs.next();
   lngt = rs.getFloat("Longitude");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get longitude of " + place
     + " :" + e);
  }
  return lngt;
 }

 public float getLatitude_Im_Place(String place) {
  connectToDB();
  float latt = 0;
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Latitude FROM important_places WHERE Place_Name='"
       + place + "'");
   rs.next();
   latt = rs.getFloat("Latitude");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get latitude of " + place
     + " :" + e);
  }
  return latt;
 }

 public String getCategory_Im_Place(String place) {
  connectToDB();
  String cat = "";
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Category FROM important_places WHERE Place_Name='"
       + place + "'");
   rs.next();
   cat = rs.getString("Category");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get  Category of " + place
     + " :" + e);
  }
  return cat;
 }

 public String getDescription_Im_Place(String place) {
  connectToDB();
  String des = "";
  try {
   stmt = (Statement) con.createStatement();
   ResultSet rs = stmt
     .executeQuery("SELECT Description FROM important_places WHERE Place_Name='"
       + place + "'");
   rs.next();
   des = rs.getString("Description");
  } catch (SQLException e) {
   System.out.println("Error - Unable to get Description of " + place
     + " :" + e);
  }
  return des;
 }
} 

Step 3 - Run your web service project in the tomcat server on eclipse. Yo will get your WSDL file like this


You know that this web service running inside the virtual machine you have. Also As I explained earlier you have host only network between virtual machine and your machine. So this web service can be access via your original machine. To verify that please enter this in your web browserhttp://Virtual Machines IP address:8080/Travel_Ceylon_Central_Web_Service/services/Travel_Ceylon_Web_Service?wsdl. In my example it was this. http://192.168.177.130:8080/Travel_Ceylon_Central_Web_Service/services/Travel_Ceylon_Web_Service?wsdl  Then you can see this in your web browser.



So know you have a web service which can be accessible through a network. So lets proceed to the part of creating 
Android Client which use this web service. I will explain it in my next post.