Wednesday, January 25, 2012

Hibernate: Dealing with Optimistic Locking

Overview:
This article looks at ways of you can deal with optimistic locking in Hibernate.

Optimistic Locking:
Technique used to avoid concurrent access to change a persistant entity. For long transactions or invocations that span several database transactions, it is useful to store versioned data to ensure that if the same entity is updated by two conversations, the last to commit changes will be informed and not override the other conversation's work.

There are two ways to achieve this.
  • Version numbers
  • Timestamp
Version numbers
To use version numbers, you need to define a numeric field in the entity class to enable this as follows,
 public class Person {
private int version;
. . .
}
Then, in the Hibernate mapping file you need to designate this field as the versioning field as follows,
 <hibernate-mapping>
<class name="Person" table="PERSON">
<version name="version" column="VERSION_ID" access="field" />
. . .
</class>
</hibernate-mapping>
Hibernate will handle the versioning each time the persistent entity is loaded.

NOTE
: Here, we limit the access to 'field'. The reason being, we don't want this to be exposed using getters/setters because this is ONLY for the purpose of versioning but nothing to do with the application's logic. Since we don't have getters/setters, we need to tell Hibenate to access this using the field.

Timestamp
Here, for the field you use a Date field in the entity class.
 import java.util.Date; 
public class Person {
private Date lastUpdatedTimestamp;
. . .
}
Following is the corresponding Hibernate mapping file,
 <hibernate-mapping>  
<class name="Person" table="PERSON">
<timestamp name="lastUpdatedTimestamp" column="LASTUPDATED_TIMESTAMP" access="field" />
. . .
</class>
</hibernate-mapping>

Hibernate : Identifiers

Overview:
In Hibernate there are various ways of defining identifiers for table mapping. However, the following two are the most commonly and widely used strategies based on the underlying database.
identity

  • supported by DB2, MySQL, MS SQL Server, Sybase and HypersonicSQL.

  • The returned identifier is of type long, short or int.
sequence
  • supported by DB2, PostgreSQL, Oracle.

  • The returned identifier is of type long, short or int.

Hibernate : Component Mapping

Overview:
This article looks at how you can map data in a given table across several POJOs treated as components of another POJO.

Association Diagram
__________
|Person |
----------
|
____|_____
|Address |
----------

The above relationship corresponds into the following Class Diagram, which indicates that a given Person has a single Address associated.
 
----------------
|Person |
|----------------|
|id:long |
|name:String |
|address:Address |
----------------

----------------
|Address |
|----------------|
|line1:String |
|line2:String |
|city:String |
|state:String |
|zipCode:String |
----------------
However, we will store both the above entities in a single table. And the database structure is as follows,
 CREATE TABLE PERSON (
person_id INTEGER NOT NULL,
name VARCHAR(50),
line1 VARCHAR(50),
line2 VARCHAR(50),
city VARCHAR(25),
state VARCHAR(25),
zip-code VARCHAR(25),
);
Lets look at the Hibernate mapping that involves in mapping both the entities into a single table.
 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.fazlan.Person" table="PERSON">
<id name="id" column="person_id">
<generator class="increment" />
</id>
<property name="name"/>
<component name="address" class="org.fazlan.Address">
<proeprty name="line1" />
<proeprty name="line2" />
<proeprty name="city" />
<proeprty name="state" />
<proeprty name="zipCode" column="zip-code"/>
</component>
</class>
</hibernate-mapping>


That's all about it!

Monday, January 23, 2012

Hibernate: Mapping Many-to-Many Associations

Overview:
This article will look at different ways of how you can map many-to-many associations in Hibernate.

Approach1: Mapping as many-to-one associations without an association entity.
Approach2: Mapping as many-to-one associations with an association entity as many-to-one.
Approach3: Mapping as many-to-one associations using composite-elements.

Approach1:
Mapping as many-to-one associations without an association entity. This approach is one of the most common ways of mapping a many-to-many association, there will be NO separate entity class to model the association between a Player and a Club.
Association Diagram
__________
|    Club         |
-----------------
       |*
       |
____|*____
|    Player     |
----------------
Class Diagram
___________
|Player             |
-------------------
|id:long            |
|name:String    |
|clubs:Set         |
-------------------
__________________
|Club                             |
------------------------------
|id:long                          |
|name:String                  |
|contractedPlayers:Set   |
------------------------------
Following is the database structure,
CREATE TABLE CLUB (
  club_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE PLAYER (
  player_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE CONTRACT (
  club_id,
  player_id,
  PRIMARY KEY (club_id, player_id),
  FOREIGN KEY (club_id) REFERENCES CLUB(club_id),
  FOREIGN KEY (player_id) REFERENCES PLAYER(player_id),
);  
Following is the hibernate mapping involved,
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="org.fazlan.beans.Club">
     <id name="id" column="club_id">
        <generator class="increment" />
     </id>
     <property name="name" />
     <set name="contractedPlayers" table="contract" inverse="true">
        <key column="club_id" />
        <many-to-many class="Player" column="player_id"/>
     </set>
  </class>
  <class name="org.fazlan.beans.Player">
     <id name="id" column="player_id">
        <generator class="increment" />
     </id>
     <property name="name" />
     <set name="clubs" table="contract">
        <key column="player_id" />
        <many-to-many class="Club" column="club_id" />
     </set>
  </class>
</hibernate-mapping>
However, with this approach, we cannot model data specific to the association with the contract(e.i: start-date and end-date of the contract). The next approach will look at how we can model such many-to-many associations.

Approach2:
Mapping as many-to-one associations with an association entity. With this way, we can easily model additional data related to the association. This is achieved by having an entity class to model the association as many-to-one.

Association Diagram
_______________
|    Club       |
-----------------
|
______|*_______
|    Contract   |
-----------------
|*
______|________
|    Player     |
-----------------

Class Diagram
_______________
|Player         |
-----------------
|id:long        |
|name:String    |
-----------------
_______________
|Club           |
-----------------
|id:long        |
|name:String    |
-----------------
______________________________
|Contract                      |
--------------------------------
|contract_id:long              |
|club:Club                     |
|player:Player                 |
|startDate:Date                |
|endDate:Date                  |
--------------------------------
Here, the association between a Player and a Club will be represented using an association entity, namely Contract. Following is the database structure,
CREATE TABLE CLUB (
  club_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE PLAYER (
  player_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE CONTRACT (
  contract_id INTEGER NOT NULL,
  club_id,
  player_id,
  start_date Date,
  end_date Date,
  PRIMARY KEY (contract_id),
  FOREIGN KEY (club_id) REFERENCES CLUB(club_id),
  FOREIGN KEY (player_id) REFERENCES PLAYER(player_id),
); 
Following is the Hibernate mapping involved,
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="org.fazlan.beans.Club">
     <id name="id" column="club_id">
        <generator class="increment" />
     </id>
     <property name="name" />
  </class>
  <class name="org.fazlan.beans.Player">
     <id name="id" column="club_id">
        <generator class="increment" />
     </id>
    <property name="name" />
  </class>
  <class name="org.fazlan.beans.Contract">
     <id name="id" column="contract_id">
        <generator class="increment" />
     </id>
     <property name="startDate" column="start_date"/>
     <property name="endDate" column="end_date"/>
     <many-to-one name="club" column="club_id" not-null="true" />
     <many-to-one name="player" column="player_id" not-null="true" />
  </class>
</hibernate-mapping>
Alternatively, you can model the many-to-many relationship using an composite-element. The next section looks at this.

Approach3:
Mapping as many-to-one associations using composite-elements.
Association Diagram
_______________
|    Club       |
-----------------
    |
______|*_______
|    Contract   |
-----------------
    |*
______|________
|    Player     |
-----------------

Class Diagram
_______________
|Player         |
-----------------
|id:long        |
|name:String    |
-----------------
_______________
|Club           |
-----------------
|id:long        |
|name:String    |
|contracts:List |
-----------------
______________________________
|Contract                      |
--------------------------------
|id:long              |
|player:Player                 |
|startDate:Date                |
|endDate:Date                  |
--------------------------------
Following is the database structure,
CREATE TABLE CLUB (
  club_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE PLAYER (
  player_id INTEGER NOT NULL,
  name VARCHAR(50),
  PRIMARY KEY (id)
);
CREATE TABLE CONTRACT (
  contract_id INTEGER NOT NULL,
  club_id,
  player_id,
  start_date Date,
  end_date Date,
  PRIMARY KEY (contract_id),
  FOREIGN KEY (club_id) REFERENCES CLUB(club_id),
  FOREIGN KEY (player_id) REFERENCES PLAYER(player_id),
);
Following is the Hibernate mapping involved,
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
  <class name="org.fazlan.beans.Club">
     <id name="id" column="club_id">
        <generator class="increment" />
     </id>
     <property name="name" />
     <list name="contracts" table="contract">
        <key column="club_id" />
        <index-column column="contract_id" />        
        <composite-element class="org.fazlan.beans.Contract">
             <property name="startDate" column="start_date"/>
             <property name="endDate" column="end_date"/>
             <many-to-one name="player" column="player_id">
        </composite-element>
     </list>
  </class>
  <class name="org.fazlan.beans.Player">
     <id name="id" column="player_id">
        <generator class="increment" />
     </id>
     <property name="name" />
  </class>
</hibernate-mapping>
Summary:
This article looked at how you can map many-to-many associations in different ways depending on the data you need to capture.

Thursday, January 19, 2012

Hibernate: Mapping Parent/Child Relationship

Overview:
This post will look at how you map bi-directional one-to-many association. It's one of the most common association types that exists, and the semantics in mapping the association with cascade the parent/child relationship.

Relationship:

1 0..m
| Parent | ----------------- | Child |

Database tables:

CREATE TABLE Parent(
parent_id INTEGER NOT NULL,
PRIMARY KEY (parent_id)
);
CREATE TABLE Child(
child_id INTEGER NOT NULL,
parent_id INTEGER NOT NULL,
PRIMARY KEY (child_id),
FOREIGN KEY (parent_id) REFERENCES Parent
);

POJOs:

package org.fazlan;

public class Parent {
private long id;
private Set children = new HashSet();
// getters and setters
}

package org.fazlan;

public class Child {
private long id;
private Parent parent;
// getters and setters
}

Hibernate Mapping:
Lets look at the basic mapping the parent and child entities,


<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.fazlan">
<class name="Parent" table="parent">
. . .
<set name="children" inverse="true">
  <key column="parent_id" />
  <one-to-many class"Child" />
</set>
</class>

<class name="Child" table="child">
. . .
<many-to-one name="parent" column="parent_id" not-null="true"/>
</class>
</hibernate-mapping>
Now that the Child entity is managing the state of the link(parent_id), and we declare the Child entity is the one that manages the relationship. We use the 'inverse' attribute to do this.

The following code is used to add a Parent,
Parent p1 = new Parent();  session.save(p1);  session.flush();
SQL generated by Hibernate,
Hibernate: select max(parent_id) from hibernatedb.Parent
Hibernate: insert into hibernatedb.Parent (parent_id) values (?)
The following code is used to add a Child,
Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();
c.setParent(p);
p.getChildren().add(c);
session.save(c);
session.flush();
Alternatively, you can add the following method to parent.

public void addChild(Child c) {
c.setParent(this);
getChildren().add(c);
}
Updated code will look like this,
Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();
p.addChild(c);
session.save(c);
session.flush();
NOTE:
  • When inverse="false" (default), Hibernate will generate TWO SQL statements: INSERT to create the child. UPDATE to create the link between parent and child.
<set name="children" inverse="false" >
<key column="parent_id" />
<one-to-many class"Child" />
</set>
SQL generated by Hibernate,
Hibernate: insert into hibernatedb.Child (parent_id, child_id) values (?, ?)
Hibernate: update hibernatedb.Child set parent_id=? where child_id=?
  • When inverse="true", Hibernate generates ONLY ONE SQL statement: INSERT the child and the parent's id.
<set name="children" inverse="true" >
<key column="parent_id" />
<one-to-many class"Child" />
</set>
SQL generated by Hibernate,
Hibernate: insert into hibernatedb.Child (parent_id, child_id) values (?, ?)
Using Cascade associations:
You can get rid of the explicit call to the save() by using cascase attribute to the collection mapping.
<set name="children" inverse="true" cascase="all">
<key column="parent_id" />
<one-to-many class"Child" />
</set>
Simplified code,
Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();
p.addChild(c);
session.flush();
This will insert the new child to the database. Also, the following code will now delete the parent and all it's children.
Parent p = (Parent) session.load(Parent.class, pid);
session.delete(p);
session.flush();
However, the following will not remove c from the database. In this case, it will only remove the link to p and cause a NOT NULL constraint violation.
Parent p = (Parent) session.load(Parent.class, pid);
Child c = (Child) p.getChildren().iterator().next();
p.getChildren().remove(c); // remove link
c.setParent(null); // NOT NULL constraint violation
session.flush(); 
to achieve this, you need to explicitly call the delete() on the Child.
Parent p = (Parent) session.load(Parent.class, pid);
Child c = (Child) p.getChildren().iterator().next();
p.getChildren().remove(c);
session.delete(c);
session.flush();
But, a Child cannot exist without its parent. So if we remove a Child from the collection, we do want it to be deleted. To do this, we must use cascade="all-delete-orphan".
<set name="children" inverse="true" cascade="all-delete-orphan">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
Updated code, Now, removing the child from the collection would also will result in removing the child from the database
Parent p1 = (Parent) session.get(Parent.class,1l);
Child c1 = p1.getChildren().iterator().next();
p1.getChildren().remove(c1);
session.flush();
Summary:
This post looked at how you can map Parent/Child relationship efficiently in Hibernate, and also briefly looked at the 'inverse' and 'cascade' features.

Sunday, January 8, 2012

Creating Java and Web Project with Maven3

Overview
This post shows how to create a Java and Web application project with Maven3.

Creating a Java project

mvn archetype:generate -DarchetypeArtifactId=maven-archetyp-quickstart -DgroupId=org.fazlan -DartifactId=org.fazlan.sample.java.project -Dversion=1.0.0-SNAPSHOT -DinteractiveMode=false

Creating a Web application project

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=org.fazlan -DartifactId=org.fazlan.sample.webapp.project -Dversion=1.0.0-SNAPSHOT -DinteractiveMode=false

Developing a Web Service Client using Axis2

Overview:
This article looks at how to create a service stub using Axis2 from a WSDL also know as a Web Service contract(refer here).

Pre-requisite:
Apache Axis2 1.6.1
Apache Tomcat
Apache Maven3

Sample code used can be found here.
Steps:
1. Create a project using the following,
mvn archetype:generate -DgroupId=org.fazlan -DartifactId=org.fazlan.employee.service.stub -DarchetypeArtifactId=maven-archetype-quickstart -Dversion=1.0.0-SNAPSHOT -DinteractiveMode=false

2. Now, access the WSDL file (http://localhost:8080/axis2/services/EmployeeService?wsdl) and save as org.fazlan.employee.service.stub/src/main/resources/EmployeeService.wsdl.

3. Update the pom.xml to include the axis2 dependencies and plug-ins to generate the artifacts from the WSDL file as follows,

1: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2: xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3: <modelVersion>4.0.0</modelVersion>
4: <groupId>org.fazlan</groupId>
5: <artifactId>org.fazlan.employee.service.stub</artifactId>
6: <packaging>jar</packaging>
7: <version>1.0-SNAPSHOT</version>
8: <name>org.fazlan.employee.service.stub</name>
9: <url>http://maven.apache.org</url>
10: <dependencies>
11: <dependency>
12: <groupId>org.apache.axis2</groupId>
13: <artifactId>axis2</artifactId>
14: <version>${axis2.version}</version>
15: </dependency>
16: <dependency>
17: <groupId>wsdl4j</groupId>
18: <artifactId>wsdl4j</artifactId>
19: <version>${wsdl4j.version}</version>
20: </dependency>
21: <dependency>
22: <groupId>org.apache.ws.commons.axiom</groupId>
23: <artifactId>axiom-api</artifactId>
24: <version>${axiom.api.version}</version>
25: </dependency>
26: <dependency>
27: <groupId>commons-logging</groupId>
28: <artifactId>commons-logging</artifactId>
29: <version>${commons-logging.version}</version>
30: </dependency>
31: <dependency>
32: <groupId>org.apache.neethi</groupId>
33: <artifactId>neethi</artifactId>
34: <version>${neethi.version}</version>
35: </dependency>
36: <dependency>
37: <groupId>org.apache.ws.commons.schema</groupId>
38: <artifactId>XmlSchema</artifactId>
39: <version>${XmlSchema.version}</version>
40: </dependency>
41: <dependency>
42: <groupId>org.apache.ws.commons.axiom</groupId>
43: <artifactId>axiom-impl</artifactId>
44: <version>${axiom-impl.version}</version>
45: </dependency>
46: <dependency>
47: <groupId>org.apache.axis2</groupId>
48: <artifactId>axis2-transport-local</artifactId>
49: <version>${axis2.version}</version>
50: </dependency>
51: <dependency>
52: <groupId>org.apache.axis2</groupId>
53: <artifactId>axis2-transport-http</artifactId>
54: <version>${axis2.version}</version>
55: </dependency>
56: </dependencies>
57: <build>
58: <plugins>
59: <plugin>
60: <groupId>org.apache.maven.plugins</groupId>
61: <artifactId>maven-antrun-plugin</artifactId>
62: <version>1.1</version>
63: <executions>
64: <execution>
65: <id>source-code-generation</id>
66: <phase>process-resources</phase>
67: <goals>
68: <goal>run</goal>
69: </goals>
70: <configuration>
71: <tasks>
72: <java classname="org.apache.axis2.wsdl.WSDL2Java" fork="true">
73: <arg line="-uri src/main/resources/EmployeeService.wsdl -u -uw -o target/generated-code
74: -p org.fazlan.employee.service.stub
75: -ns2p http://service.employee.fazlan.org=org.fazlan.employee.service.stub,http://beans.service.employee.fazlan.org/xsd=org.fazlan.employee.service.stub.beans.xsd,http://exceptions.service.employee.fazlan.org/xsd=org.fazlan.employee.service.stub.exceptions.xsd"/>
76: <classpath refid="maven.dependency.classpath"/>
77: <classpath refid="maven.compile.classpath"/>
78: <classpath refid="maven.runtime.classpath"/>
79: </java>
80: </tasks>
81: </configuration>
82: </execution>
83: </executions>
84: </plugin>
85: <plugin>
86: <groupId>org.codehaus.mojo</groupId>
87: <artifactId>build-helper-maven-plugin</artifactId>
88: <executions>
89: <execution>
90: <id>add-source</id>
91: <phase>generate-sources</phase>
92: <goals>
93: <goal>add-source</goal>
94: </goals>
95: <configuration>
96: <sources>
97: <source>
98: target/generated-code/src
99: </source>
100: </sources>
101: </configuration>
102: </execution>
103: </executions>
104: </plugin>
105: </plugins>
106: </build>
107: <properties>
108: <axis2.version>1.6.1</axis2.version>
109: <wsdl4j.version>1.6.2</wsdl4j.version>
110: <commons-logging.version>1.1.1</commons-logging.version>
111: <neethi.version>2.0.4</neethi.version>
112: <axiom.api.version>1.2.12</axiom.api.version>
113: <axiom-impl.version>1.2.12</axiom-impl.version>
114: <XmlSchema.version>1.4.7</XmlSchema.version>
115: </properties>
116: </project>

4. Build the project to generate the artifacts required,

mvn clean install

The generated artifacts will be packaged in the org.fazlan.employee.service.stub-1.0-SNAPSHOT.jar. You then add this jar as a dependency to the client project that needs to access the Employee Web Service.

5. Write a simple Java client (You may need to include all the axis2 dependencies to run this client).

1: import org.apache.axis2.AxisFault;
2: import org.fazlan.employee.service.stub.beans.xsd.Employee;
3: public class Main {
4: public static void main(String... args) throws Exception {
5: EmployeeServiceStub service = new EmployeeServiceStub();
6: Employee e = new Employee();
7: e.setId(1);
8: e.setFirstName("Fazlan");
9: e.setLastName("Sabar");
10: int id = service.addEmployee(e);
11: System.out.println(id);
12: Employee[] employees = service.getAllEmployees();
13: for(Employee em : employees) {
14: System.out.println(em.getId());
15: System.out.println(em.getFirstName());
16: System.out.println(em.getLastName());
17: System.out.println("---------------");
18: }
19: }
20: }

6. Sample output.

0
Fazlan
Sabar
---------------
1
Fazlan
Sabar
---------------
Summary:
This articles looked at how to generate artifacts using Axis2 with Maven3 to interact with the Web Service contract (WSDL).

Saturday, January 7, 2012

Develop Code-First Web Services using Axis2


Overview:
This article is simple, but provides a good foundation of creating a Web Service from an existing Java code using Apache Axi2 and Maven3.

Pre-requisites:
Apache Axis2 1.6.x
Apache Tomcat
Apache Maven3

Sample code used for this can be found here.
Steps:
1. Create a Maven project,

mvn archetype:generate -DgroupId=org.fazlan -DartifactId=org.fazlan.employee.service -DarchetypeArtifactId=maven-archetype-quickstart -Dversion=1.0.0-SNAPSHOT -DinteractiveMode=false

Now, the project structure should be like the following,

org.fazlan.employee.service
`-- src
     |-- main
     |    `-- java
     |         `-- org
     |             `-- fazlan
     |                 `-- employee
     |                     `-- service
     |     
     `-- test 
          `-- java
               `-- org
                   `-- fazlan

2. Update the pom.xml to add the 'axis2-aar-maven-plugin' plugin.
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  
  <modelVersion>4.0.0</modelVersion>  
  <groupId>org.fazlan</groupId>  
  <artifactId>org.fazlan.employee.service</artifactId>  
  <packaging>aar</packaging>  
  <version>1.0-SNAPSHOT</version>  
  <name>org.fazlan.employee.service</name>  
  <url>http://maven.apache.org</url>  
  <build>  
     <plugins>  
       <plugin>  
         <groupId>org.apache.axis2</groupId>  
         <artifactId>axis2-aar-maven-plugin</artifactId>  
         <version>1.6.1</version>  
         <!--<version>${orbit.version.axis2}</version>-->  
         <extensions>true</extensions>  
         <configuration>  
           <aarName>org.fazlan.employee.service</aarName>  
         </configuration>  
       </plugin>  
     </plugins>  
   </build>  
 </project>  


3. I have a service class to manage employee details, and the classes looks like this,
 POJO to model employee,  
 //org.fazlan.employee.service.beans.Employee.java  
 public class Employee {  
   private int id;  
   private String firstName;  
   private String lastName;  
   // getter and setter methods  
 }  
 POJO to model the employee exception,  
 //org.fazlan.employee.service.exceptions.EmployeeException.java  
 public class EmployeeException extends java.lang.Exception {  
 }  
 The service class with the logic to manage employees,  
 //org.fazlan.employee.service.EmployeeService.java  
 public class EmployeeService {  
   private static final Map employeeMap = new HashMap();  
   private static int index = 0;  
   public int addEmployee(Employee employee) throws EmployeeException {  
    employee.setId(++index);  
    employeeMap.put(index, employee);  
    return index;  
   }  
   public Employee getEmployee(int employeeId) throws EmployeeException {  
    return employeeMap.get(employeeId);  
   }  
   public Employee[] getAllEmployees() throws EmployeeException{  
    return employeeMap.values().toArray(new Employee[employeeMap.size()]);  
   }  
 }  


4. Create the service descriptor src/main/resources/META-INF/services.xml as follows,
 <service name="EmployeeService" scope="application">  
 <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">  
     org.fazlan.employee.service.EmployeeService  
   </parameter>  
 </service>  

5. Now the project structure should look like the following,
org.fazlan.employee.service
`-- src
|-- main
|   |-- java
|   |    `-- org
|   |         `-- fazlan
|   |              `-- employee
|   |                   `-- service
|   |                       |-- beans
|   |                       |-- exceptions
|   |                       `-- util
|   `-- resources
|       `-- META-INF
`-- test
     `-- java
         `-- org
             `-- fazlan

6. Build the project and pack the aar file.

mvn clean install

7. Deploy the axis2.war from the Axis2 distribution to Tomcat. After deploying you can verify by accessing http://localhost:8080/axis2/

8. Now, deploy the org.fazlan.employee.service.aar via the Axis2 administrator's console. (default username/password is admin/axis2).

9. After successfully deploying the service, you can access the WSDL via http://localhost:8080/axis2/services/EmployeeService?wsdl


Summary:

This article looked at how you can create a Web Service using Axis2 in a nutshell.