Sunday, September 11, 2011

Remote Debugging Apache Axis2 with IntelliJ Idea

Environment: OS - Ubuntu-10.04(Lucid Lynx)
                       IDE - IntelliJ Idea 10.0.2

Are you a new contributor to Apache Axis2 ? If yes then you will need to run Axis2 in debug mode to perform remote debugging to understand the source code at the beginning. It is easy to run Axis2 in debug mode. In this post I am going to explain how to do remote debugging Apache Axis2 source code with IntelliJ idea.

checkout and build the Axis2 trunk

First thing we need to do is checkout Axis2 source code from trunk.  Then you can build it, and if you have any difficulty of building Axis2 trunk read my previous post Apache Axis2 Server: A Developer Guide To New Contributors .


Open Axis2 in IntelliJ Idea

Go to the root directory of your Axis2 source code and type "mvn idea:idea" now you can open it in IntelliJ Idea by going to File--> Open Project.

Configure Idea for remote debug

In Idea go to Run-->Edit Configurations or click the drop down menu icon  in between Run and Makefile icons and select Edit Configurations.
Figure 1: select Edit Configurations

Then Run/Debug Configuration window will display,
Figure 2: Run/Debug Configurations
 
Now press the + button in top left corner of the window to create a new configuration based on default settings. Then select Remote in "Add New Configuration" window as shown in Figure 3.
Figure 3: Add New Configuration
 
Provide a name to the remote debug session. In here you have to configure a few parameters
host : localhost
port : 8000 - Axis2 default debug port

module : module to remote debug or select <no module> to search across the whole project.
In here i have selected axis2-adb module.

Figure 4: set configuration 


Remote Debug

Great! now you are ready to do remote debugging in axis2-adb module,  run "sh axis2server.sh -xdebug" in terminal  then click debug icon in Idea. Before that make sure you have selected Axis2-adb in debug configuration, If so it will show "connected to the target vm address. 'localhost:8080' transport,'socket'" in debug console which means you have successfully connected :)
Figure 5: select Axis2-adb

Now mark a break point inside invokeBusinessLogic method in RPCMessageReceiver class in adb module. Run your client code to invoke deployed Pojo service. The IDE hits and stops in that break point so you can debug step by step.

Note: If you get 'x' mark in debug point that means the source code is differ from your running code. In this case you should build adb module and replace axis2-adb-<version>.SNAPSHOT.jar and start debugging again. 

You can find how to build and where to replace axis2 jars in "Run Axis2 with changes we have done to the source code" section in Apache Axis2 Server: A Developer Guide To New Contributors  post.

Introducing Enum Support With Apache Axis2

Now you can find java Enum support with Axis2 1.7.0 version (Not yet released, you can download trunk and build it). It is a new feature to Axis2 as previous versions didn't support a java Enum as a service method parameter. But with this new feature you can use java Enum constants as a service method parameter in your service. Not only in java level it supports wsdl level too. Therefore we can use this new feature in code-first approach as well as in contract-first approach. The following example explains about how to use Enum support in code-first approach and contract-first approach in pojo service.

Deploying a Service which uses Enum in method parameter.

Here is the simple pojo service class. This service class have three methods and two enum classes Day and Status, where Day is a simple enum constant and Status has a user defined constructor which gets an int and a String as its parameters.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
 * @author shameera
 */
public class EnumService {

    public Day testDay(Day day) {
        System.out.println(day.getDeclaringClass());
        System.out.println(day.toString());
        return day;
    }

    public Event callEvent(Event newEvent) {
        Day eventDay = newEvent.getStartingDay();
        System.out.println("Event Starting day is : " + eventDay.toString());
        return newEvent;
    }

    public Status testStatus(Status status) {
        return status;
    }

    public enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    }

    public enum Status {
        START(0, "start"), ACTIVE(1, "active"), STOP(2, "stop");

        private final int val;
        private final String desc;

        Status(int val, String desc) {
            this.val = val;
            this.desc = desc;
        }

        public int value() {
            return this.val;
        }

        public String description() {
            return this.desc;
        }
    }
}
Methods :

1. testDay - get and return Day enum constant.

2. testStatus - get and return Status enum constant.

3. callEvent - get and return Event pojo object which use Day enum constant.

Here is the Event pojo class.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
 * @author shameera
 */
public class Event {

    private EnumService.Day startingDay;
    private String eventDesc ;
    private String eventName;

    public EnumService.Day getStartingDay() {
        return startingDay;
    }

    public void setStartingDay(EnumService.Day startingDay) {
        this.startingDay = startingDay;
    }

    public String getEventDesc() {
        return eventDesc;
    }

    public void setEventDesc(String eventDesc) {
        this.eventDesc = eventDesc;
    }

    public String getEventName() {
        return eventName;
    }

    public void setEventName(String eventName) {
        this.eventName = eventName;
    }
}

Using these two classes and services.xml create .aar file and deploy it in Axis2. After successfully deploy it you can see it in axis2 services page.

You can see generated wsdl of EnumService service by clicking it. Here are some parts of the wsdl file of Enumservice service.
NOTE: make sure that you are using Axis2 1.7.0 if not generated wsdl for this service is not a validated wsdl.

In wsdl file you can see that for the enum constants it has a new schema generated "http://ws.apache.org/namespaces/axis2/enum" as targetNamespace.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
    <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ws.apache.org/namespaces/axis2/enum">
    <xs:simpleType name="Status">
        <xs:restriction base="xs:string">
            <xs:enumeration value="START"/>
            <xs:enumeration value="ACTIVE"/>
            <xs:enumeration value="STOP"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="Day">
        <xs:restriction base="xs:string">
            <xs:enumeration value="MONDAY"/>
            <xs:enumeration value="TUESDAY"/>
            <xs:enumeration value="WEDNESDAY"/>
            <xs:enumeration value="THURSDAY"/>
            <xs:enumeration value="FRIDAY"/>
            <xs:enumeration value="SATURDAY"/>
            <xs:enumeration value="SUNDAY"/>
        </xs:restriction>
    </xs:simpleType>
    </xs:schema>

This is the generated schema part for testDay method
1
2
3
4
5
6
7
    <xs:element name="testDay">
    <xs:complexType>
        <xs:sequence>
            <xs:element minOccurs="0" name="day" nillable="true" type="ax21:Day"/>
        </xs:sequence>
    </xs:complexType>
    </xs:element>

This is the generated schema part for testDayResponse
1
2
3
4
5
6
7
    <xs:element name="testDayResponse">
    <xs:complexType>
        <xs:sequence>
            <xs:element minOccurs="0" name="return" nillable="true" type="ax21:Day"/>
        </xs:sequence>
    </xs:complexType>
    </xs:element>

Here is the main generated schema for this service
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    <xs:schema xmlns:ax24="http://axis2userguide.axis2.apache.org/xsd" xmlns:ax22="http://ws.apache.org/namespaces/axis2/enum" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://axis2userguide.axis2.apache.org">
    <xs:import namespace="http://ws.apache.org/namespaces/axis2/enum"/>
    <xs:import namespace="http://axis2userguide.axis2.apache.org/xsd"/>
    <xs:element name="testStatus">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" name="status" nillable="true" type="ax21:Status"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="testStatusResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" name="return" nillable="true" type="ax21:Status"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="testDay">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" name="day" nillable="true" type="ax21:Day"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="testDayResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" name="return" nillable="true" type="ax21:Day"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="callEvent">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" name="newEvent" nillable="true" type="ax23:Event"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="callEventResponse">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" name="return" nillable="true" type="ax23:Event"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    </xs:schema>

Here is the generated schema for Event Pojo object.
1
2
3
4
5
6
7
8
9
    <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://axis2userguide.axis2.apache.org/xsd">
    <xs:complexType name="Event">
        <xs:sequence>
            <xs:element minOccurs="0" name="eventDesc" nillable="true" type="xs:string"/>
            <xs:element minOccurs="0" name="eventName" nillable="true" type="xs:string"/>
            <xs:element minOccurs="0" name="startingDay" nillable="true" type="ax21:Day"/>
        </xs:sequence>
    </xs:complexType>
    </xs:schema>

Enum schema generation process is intelligent enough to generate only one schema type for each enum class.

You can write a schema for Enum support now which means now you can use contract-first approach too.

If you have any problem regarding enum support in Axis2 you can ask it here or Axis2-user mailing list.

Apache Axis2 Server: A Developer Guide To New Contributors

Env : OS - Ubuntu 10.04(Lucid Lynx)
        
Apache Axis2 is an open source web service / soap / wsdl engine. There are two implementations Axis2/java and Axis2/C. In here I'm talking about Axis2/java. There are three ways we can run Axis2 as,
  1. Axis2 binary distribution 
  2. Axis2 source distribution 
  3. Axis2 war(Web archive) distribution
But If you need to contribute to Axis2 development, you need to checkout the source code of Axis2 trunk and build it.Here I will talk on how to build Axis2 trunk, how to up the Axis2 server and deploy a simple service in Axis2. Then I am going to talk on how we can run Axis2 Server with our changes what we have done to source code.

Checkout Axis2 trunk


Axis2 project uses subversion as its version control system therefore we need to have subversion installed in our machine (If not you can install latest subversion by typing "sudo apt-get install subversion" in terminal).

Now you can checkout Axis2 trunk to your machine by typing "svn co <url_to_trunk>  <directory_name>".
eg: svn co http://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/ axis2_trunk 
This will checkout Axis2 trunk to the axis2_trunk directory in our local machine.

Build Axis2 trunk

Axis2 uses Maven2 as its building tool, which means we need install maven2 in our machine to build axis2 source code. You can install maven2 by typing "sudo apt-get install maven2" .

Lets assume  you have checked out trunk to the directory called axis2_trunk, go to that directory and type "mvn install" it will build Axis2 by default. Then go to distribution module typing "cd modules/distribution/"  and again type "mvn install". It will build the distribution module as in default profile, it doesn't build this module. That's all and now you have build latest Axis2 trunk in your machine.


Up the Axis2 server and deploy a new service

Lets see how to up Axis2 server. After building process is finished it will create a target directory in distribution module. Now type cd target/axis2-1.7.0-SNAPSHOT/bin/  to navigate to bin directory. In bin directory you can see several .sh files, to run Axis2 server run "sh axis2server.sh" command in terminal.




















 It will up axis2server in default port 8080. Now go to you browser and type http://localhost:8080/axis2/services/ you can see axis2 services list and available operations.























You have built Axis2 trunk and up the Axis2 server in localhost. Now you can deploy your services in Axis2. It is a simple thing in Axis2 as it supports hot deployment which means you can deploy a service while Axis2 is up and running as it doesn't need to down the server and up it again after adding a new service. You just need to add <service_name>.aar file to repository/serivces/ directory in  axis2-1.7.0-SNAPSHOT .

However as developers we may need to deploy the same service again and again. Then you need to create new .aar file for each attempt and this is cumbersome. No need to worry , you can deploy a service by putting a directory which has content same as .aar file.

Run Axis2 with changes we have done to the source code

If you are a new contributor to Axis2 project then you need to run Axis2 server which new changes  you have done to the source code of Axis2. There are two ways you can accomplish this.
  • Go to the axis2_trunk directory and run "mvn clean install" then go to the distribution module and run "mvn clean install" commands in terminal. Now you have built Axis2 with modifications what you have done to the source. Go to the bin directory and run "sh axis2server.sh" to up the modified Axis2 server.
  •  If you have done changes to a few modules then you don't need to build all modules. Hence you just need to build those modules as we built distribution module in previous method. Lets say you have done modifications to kernel module, then you can build kernel module running "mvn clean install" inside the kernel module, copy axis2-kernel-<version>.SNAPSHOT.jar which was created in target directory of kernel module to the target/axis2-1.7.0-SNAPSHOT/lib/ directory in distribution module. Thats all and now you can up the Axis2 server by running sh axis2server.sh command inside the bin directory of distribution module.

Saturday, September 3, 2011

First Post

Hi ,
This blog will be used to post some technical stuff and i would like share my knowledge in open source projects like open office( java API ), Axis2 , Cassandra , Hector , Subversion ... etc through this . And i also wish to talk about some knowledge base stuff and share some code snippets. I appreciate  blogging cause i have learned lot of technical and non technical things following other's blogs. Hope this blog will help you to improve your technical knowledge.

Sample Text

Website counter

Categories