Full web service: connect to DB and using complex data type

Objective

In this tutorial, we will study how to create a standalone web service application at the client side in which, the remote service from the server has to connect to the database and the remote method has complex data type in its input/output parameters.

  • At the server side, we create a web application which contains the CustomerDAO class to provide two method: searchCustomer() and editCustomer().
  • Build the web application as a web service at the server side (generate the WSDL file)
  • At the client side, we will generate the classes from the WSDL file of the service
  • Create a standalone client application to invoke the remote web service with two function: search customer by name and edit a customer.

Create server web application

In Eclipse, create a new dynamic web application named wsCustomer which has two packages in the /src folder:

  • model: This has an entity class Customer
  • webservices: This has two classes: DAO and CustomerDAO

Note that:

  • The /WebContent/wsdl/CustomerDAO.wsdl will automatically appear after the step of generating web service
  • We have to copy the mysql connector driver into the directory of /WebContent/WEB-INF/lib
Customer.java
package model;

import java.io.Serializable;

public class Customer implements Serializable{
	private static final long serialVersionUID = 20210811004L;
	private int id;
	private String name;
	private String idCard;
	private String address;
	private String tel;
	private String email;
	private String note;
	
	public Customer() {
		super();
	}
	
	public Customer(String name, String idCard, String address, String tel, String email, String note) {
		super();
		this.name = name;
		this.idCard = idCard;
		this.address = address;
		this.tel = tel;
		this.email = email;
		this.note = note;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public String getIdCard() {
		return idCard;
	}

	public void setIdCard(String idCard) {
		this.idCard = idCard;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getNote() {
		return note;
	}

	public void setNote(String note) {
		this.note = note;
	}
}
DAO.java
package webservices;

import java.sql.Connection;
import java.sql.DriverManager;

public class DAO {
	public static Connection con;
	
	public DAO(){
		if(con == null){
			String dbUrl = "jdbc:mysql://localhost:3307/hotel?autoReconnect=true&useSSL=false";
			String dbClass = "com.mysql.jdbc.Driver";

			try {
				Class.forName(dbClass);
				con = DriverManager.getConnection (dbUrl, "root", "Cnpm@2020?");
			}catch(Exception e) {
				e.printStackTrace();
			}
		}
	}
}
CustomerDAO.java
 package webservices;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import model.Customer;

public class CustomerDAO extends DAO{
		
	/**
	 * search all clients in the tblClient whose name contains the @key
	 * using PreparedStatement - recommended for professional coding
	 * @param key
	 * @return list of client whose name contains the @key
	 */
	public Customer[] searchCustomer(String key){
		Customer[] result = null;
		String sql = "SELECT * FROM tblclient WHERE name LIKE ?";
		try{
			PreparedStatement ps = con.prepareStatement(sql);
			ps.setString(1, "%" + key + "%");
			ResultSet rs = ps.executeQuery();
			
			if(rs.last()) {
				result = new Customer[rs.getRow()];
				rs.beforeFirst();
				
				int index = 0;
				while(rs.next()){					
					result[index] = new Customer();
					result[index].setId(rs.getInt("id"));
					result[index].setName(rs.getString("name"));
					result[index].setIdCard(rs.getString("idcard"));
					result[index].setAddress(rs.getString("address"));
					result[index].setTel(rs.getString("tel"));
					result[index].setEmail(rs.getString("email"));
					result[index].setNote(rs.getString("note"));
					index++;
				}
			}

			
		}catch(Exception e){
			e.printStackTrace();
		}	
		return result;
	}
		
	
	/**
	 * update the @client
	 * @param client
	 */
	public boolean editCustomer(Customer client){
		String sql = "UPDATE tblclient SET name=?, idcard =?, address=?, tel=?, email=?, note=? WHERE id=?";
		try{
			PreparedStatement ps = con.prepareStatement(sql);
			ps.setString(1, client.getName());
			ps.setString(2, client.getIdCard());
			ps.setString(3, client.getAddress());
			ps.setString(4, client.getTel());
			ps.setString(5, client.getEmail());
			ps.setString(6, client.getNote());
			ps.setInt(7, client.getId());

			ps.executeUpdate();
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}
		return true;
	}	
}

Exporting the web application as a web service

  • In Eclipse, select new -> Web service
  • In the winzard: select the class from the wsCustomer: webservice.CustomerDAO
  • It will automatically create a CustomerDAO.wsdl file in the directory of /WebContent/wsdl/
The CustomerDAO.wsdl file
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://webservices" xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://webservices" xmlns:intf="http://webservices" xmlns:tns1="http://model" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!--WSDL created by Apache Axis version: 1.4
Built on Apr 22, 2006 (06:55:48 PDT)-->
 <wsdl:types>
  <schema elementFormDefault="qualified" targetNamespace="http://webservices" xmlns="http://www.w3.org/2001/XMLSchema">
   <import namespace="http://model"/>
   <element name="editCustomer">
    <complexType>
     <sequence>
      <element name="client" type="tns1:Customer"/>
     </sequence>
    </complexType>
   </element>
   <element name="editCustomerResponse">
    <complexType>
     <sequence>
      <element name="editCustomerReturn" type="xsd:boolean"/>
     </sequence>
    </complexType>
   </element>
   <element name="searchCustomer">
    <complexType>
     <sequence>
      <element name="key" type="xsd:string"/>
     </sequence>
    </complexType>
   </element>
   <element name="searchCustomerResponse">
    <complexType>
     <sequence>
      <element maxOccurs="unbounded" name="searchCustomerReturn" type="tns1:Customer"/>
     </sequence>
    </complexType>
   </element>      
  </schema>
  <schema elementFormDefault="qualified" targetNamespace="http://model" xmlns="http://www.w3.org/2001/XMLSchema">
   <import namespace="http://webservices"/>
   <complexType name="Customer">
    <sequence>
     <element name="address" nillable="true" type="xsd:string"/>
     <element name="email" nillable="true" type="xsd:string"/>
     <element name="id" type="xsd:int"/>
     <element name="idCard" nillable="true" type="xsd:string"/>
     <element name="name" nillable="true" type="xsd:string"/>
     <element name="note" nillable="true" type="xsd:string"/>
     <element name="tel" nillable="true" type="xsd:string"/>
    </sequence>
   </complexType>
  </schema>
 </wsdl:types>   

   <wsdl:message name="editCustomerResponse">

      <wsdl:part element="impl:editCustomerResponse" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="editCustomerRequest">

      <wsdl:part element="impl:editCustomer" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="searchCustomerResponse">

      <wsdl:part element="impl:searchCustomerResponse" name="parameters">

      </wsdl:part>

   </wsdl:message>

   <wsdl:message name="searchCustomerRequest">

      <wsdl:part element="impl:searchCustomer" name="parameters">

      </wsdl:part>

   </wsdl:message>   

   <wsdl:portType name="CustomerDAO">

      <wsdl:operation name="editCustomer">

         <wsdl:input message="impl:editCustomerRequest" name="editCustomerRequest">

       </wsdl:input>

         <wsdl:output message="impl:editCustomerResponse" name="editCustomerResponse">

       </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="searchCustomer">

         <wsdl:input message="impl:searchCustomerRequest" name="searchCustomerRequest">

       </wsdl:input>

         <wsdl:output message="impl:searchCustomerResponse" name="searchCustomerResponse">

       </wsdl:output>

      </wsdl:operation>      

   </wsdl:portType>

   <wsdl:binding name="CustomerDAOSoapBinding" type="impl:CustomerDAO">

      <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>

      <wsdl:operation name="editCustomer">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="editCustomerRequest">

            <wsdlsoap:body use="literal"/>

         </wsdl:input>

         <wsdl:output name="editCustomerResponse">

            <wsdlsoap:body use="literal"/>

         </wsdl:output>

      </wsdl:operation>

      <wsdl:operation name="searchCustomer">

         <wsdlsoap:operation soapAction=""/>

         <wsdl:input name="searchCustomerRequest">

            <wsdlsoap:body use="literal"/>

         </wsdl:input>

         <wsdl:output name="searchCustomerResponse">

            <wsdlsoap:body use="literal"/>

         </wsdl:output>

      </wsdl:operation>

   </wsdl:binding>

   <wsdl:service name="CustomerDAOService">

      <wsdl:port binding="impl:CustomerDAOSoapBinding" name="CustomerDAO">

         <wsdlsoap:address location="http://localhost:8080/wsCustomer/services/CustomerDAO"/>

      </wsdl:port>

   </wsdl:service>

</wsdl:definitions>

Generating classes at from the WSDL file at the client side

There are some methods to generate the necessary file at the client side from a given WSDL file:

  • Create a client application from a web service in Eclipse (see simple tutorial)
  • Using wsimport tool
  • Using cmd line: WSDL2Java CustomerDAO.wsdl
  • Using WSDL2Java in Eclipse:
package view;
import org.apache.axis.wsdl.WSDL2Java;
public class GenerateJavaFromWSDL {
	public static void main(String[] args) {		
		// generate java classes from wsdl file
		String[] ss = new String[2];
		ss[0] = "-w1.4";
		ss[1] = "CustomerDAO.wsdl";		
		WSDL2Java.main(ss);
}

It will generate two directories (by using the 4th method):

  • model: This contains a class of Customer.java
  • webservices: This contains some classes:
    • CustomerDAO.java (Interface)
    • CustomerDAOService.java (Interface)
    • CustomerDAOServiceLocator.java
    • CustomerDAOSoapBindingStub.java
Customer.java
/**
 * Customer.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */

package model;

public class Customer  implements java.io.Serializable {
    private java.lang.String address;

    private java.lang.String email;

    private int id;

    private java.lang.String idCard;

    private java.lang.String name;

    private java.lang.String note;

    private java.lang.String tel;

    public Customer() {
    }

    public Customer(
           java.lang.String address,
           java.lang.String email,
           int id,
           java.lang.String idCard,
           java.lang.String name,
           java.lang.String note,
           java.lang.String tel) {
           this.address = address;
           this.email = email;
           this.id = id;
           this.idCard = idCard;
           this.name = name;
           this.note = note;
           this.tel = tel;
    }


    /**
     * Gets the address value for this Customer.
     * 
     * @return address
     */
    public java.lang.String getAddress() {
        return address;
    }


    /**
     * Sets the address value for this Customer.
     * 
     * @param address
     */
    public void setAddress(java.lang.String address) {
        this.address = address;
    }


    /**
     * Gets the email value for this Customer.
     * 
     * @return email
     */
    public java.lang.String getEmail() {
        return email;
    }


    /**
     * Sets the email value for this Customer.
     * 
     * @param email
     */
    public void setEmail(java.lang.String email) {
        this.email = email;
    }


    /**
     * Gets the id value for this Customer.
     * 
     * @return id
     */
    public int getId() {
        return id;
    }


    /**
     * Sets the id value for this Customer.
     * 
     * @param id
     */
    public void setId(int id) {
        this.id = id;
    }


    /**
     * Gets the idCard value for this Customer.
     * 
     * @return idCard
     */
    public java.lang.String getIdCard() {
        return idCard;
    }


    /**
     * Sets the idCard value for this Customer.
     * 
     * @param idCard
     */
    public void setIdCard(java.lang.String idCard) {
        this.idCard = idCard;
    }


    /**
     * Gets the name value for this Customer.
     * 
     * @return name
     */
    public java.lang.String getName() {
        return name;
    }


    /**
     * Sets the name value for this Customer.
     * 
     * @param name
     */
    public void setName(java.lang.String name) {
        this.name = name;
    }


    /**
     * Gets the note value for this Customer.
     * 
     * @return note
     */
    public java.lang.String getNote() {
        return note;
    }


    /**
     * Sets the note value for this Customer.
     * 
     * @param note
     */
    public void setNote(java.lang.String note) {
        this.note = note;
    }


    /**
     * Gets the tel value for this Customer.
     * 
     * @return tel
     */
    public java.lang.String getTel() {
        return tel;
    }


    /**
     * Sets the tel value for this Customer.
     * 
     * @param tel
     */
    public void setTel(java.lang.String tel) {
        this.tel = tel;
    }

    private java.lang.Object __equalsCalc = null;
    public synchronized boolean equals(java.lang.Object obj) {
        if (!(obj instanceof Customer)) return false;
        Customer other = (Customer) obj;
        if (obj == null) return false;
        if (this == obj) return true;
        if (__equalsCalc != null) {
            return (__equalsCalc == obj);
        }
        __equalsCalc = obj;
        boolean _equals;
        _equals = true && 
            ((this.address==null && other.getAddress()==null) || 
             (this.address!=null &&
              this.address.equals(other.getAddress()))) &&
            ((this.email==null && other.getEmail()==null) || 
             (this.email!=null &&
              this.email.equals(other.getEmail()))) &&
            this.id == other.getId() &&
            ((this.idCard==null && other.getIdCard()==null) || 
             (this.idCard!=null &&
              this.idCard.equals(other.getIdCard()))) &&
            ((this.name==null && other.getName()==null) || 
             (this.name!=null &&
              this.name.equals(other.getName()))) &&
            ((this.note==null && other.getNote()==null) || 
             (this.note!=null &&
              this.note.equals(other.getNote()))) &&
            ((this.tel==null && other.getTel()==null) || 
             (this.tel!=null &&
              this.tel.equals(other.getTel())));
        __equalsCalc = null;
        return _equals;
    }

    private boolean __hashCodeCalc = false;
    public synchronized int hashCode() {
        if (__hashCodeCalc) {
            return 0;
        }
        __hashCodeCalc = true;
        int _hashCode = 1;
        if (getAddress() != null) {
            _hashCode += getAddress().hashCode();
        }
        if (getEmail() != null) {
            _hashCode += getEmail().hashCode();
        }
        _hashCode += getId();
        if (getIdCard() != null) {
            _hashCode += getIdCard().hashCode();
        }
        if (getName() != null) {
            _hashCode += getName().hashCode();
        }
        if (getNote() != null) {
            _hashCode += getNote().hashCode();
        }
        if (getTel() != null) {
            _hashCode += getTel().hashCode();
        }
        __hashCodeCalc = false;
        return _hashCode;
    }

    // Type metadata
    private static org.apache.axis.description.TypeDesc typeDesc =
        new org.apache.axis.description.TypeDesc(Customer.class, true);

    static {
        typeDesc.setXmlType(new javax.xml.namespace.QName("http://model", "Customer"));
        org.apache.axis.description.ElementDesc elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("address");
        elemField.setXmlName(new javax.xml.namespace.QName("http://model", "address"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("email");
        elemField.setXmlName(new javax.xml.namespace.QName("http://model", "email"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("id");
        elemField.setXmlName(new javax.xml.namespace.QName("http://model", "id"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"));
        elemField.setNillable(false);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("idCard");
        elemField.setXmlName(new javax.xml.namespace.QName("http://model", "idCard"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("name");
        elemField.setXmlName(new javax.xml.namespace.QName("http://model", "name"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("note");
        elemField.setXmlName(new javax.xml.namespace.QName("http://model", "note"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
        elemField = new org.apache.axis.description.ElementDesc();
        elemField.setFieldName("tel");
        elemField.setXmlName(new javax.xml.namespace.QName("http://model", "tel"));
        elemField.setXmlType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"));
        elemField.setNillable(true);
        typeDesc.addFieldDesc(elemField);
    }

    /**
     * Return type metadata object
     */
    public static org.apache.axis.description.TypeDesc getTypeDesc() {
        return typeDesc;
    }

    /**
     * Get Custom Serializer
     */
    public static org.apache.axis.encoding.Serializer getSerializer(
           java.lang.String mechType, 
           java.lang.Class _javaType,  
           javax.xml.namespace.QName _xmlType) {
        return 
          new  org.apache.axis.encoding.ser.BeanSerializer(
            _javaType, _xmlType, typeDesc);
    }

    /**
     * Get Custom Deserializer
     */
    public static org.apache.axis.encoding.Deserializer getDeserializer(
           java.lang.String mechType, 
           java.lang.Class _javaType,  
           javax.xml.namespace.QName _xmlType) {
        return 
          new  org.apache.axis.encoding.ser.BeanDeserializer(
            _javaType, _xmlType, typeDesc);
    }
}

CustomerDAO.java
/**
 * CustomerDAO.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */

package webservices;

public interface CustomerDAO extends java.rmi.Remote {
    public boolean editCustomer(model.Customer client) throws java.rmi.RemoteException;
    public model.Customer[] searchCustomer(java.lang.String key) throws java.rmi.RemoteException;
    public model.Customer[] getAllCustomer() throws java.rmi.RemoteException;
}
CustomerDAOService.java
/**
 * CustomerDAOService.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */

package webservices;

public interface CustomerDAOService extends javax.xml.rpc.Service {
    public java.lang.String getCustomerDAOAddress();

    public webservices.CustomerDAO getCustomerDAO() throws javax.xml.rpc.ServiceException;

    public webservices.CustomerDAO getCustomerDAO(java.net.URL portAddress) throws javax.xml.rpc.ServiceException;
}

CustomerDAOServiceLocator.java
/**
 * CustomerDAOServiceLocator.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */

package webservices;

public class CustomerDAOServiceLocator extends org.apache.axis.client.Service implements webservices.CustomerDAOService {

    public CustomerDAOServiceLocator() {
    }


    public CustomerDAOServiceLocator(org.apache.axis.EngineConfiguration config) {
        super(config);
    }

    public CustomerDAOServiceLocator(java.lang.String wsdlLoc, javax.xml.namespace.QName sName) throws javax.xml.rpc.ServiceException {
        super(wsdlLoc, sName);
    }

    // Use to get a proxy class for CustomerDAO
    private java.lang.String CustomerDAO_address = "http://localhost:8080/wsCustomer/services/CustomerDAO";

    public java.lang.String getCustomerDAOAddress() {
        return CustomerDAO_address;
    }

    // The WSDD service name defaults to the port name.
    private java.lang.String CustomerDAOWSDDServiceName = "CustomerDAO";

    public java.lang.String getCustomerDAOWSDDServiceName() {
        return CustomerDAOWSDDServiceName;
    }

    public void setCustomerDAOWSDDServiceName(java.lang.String name) {
        CustomerDAOWSDDServiceName = name;
    }

    public webservices.CustomerDAO getCustomerDAO() throws javax.xml.rpc.ServiceException {
       java.net.URL endpoint;
        try {
            endpoint = new java.net.URL(CustomerDAO_address);
        }
        catch (java.net.MalformedURLException e) {
            throw new javax.xml.rpc.ServiceException(e);
        }
        return getCustomerDAO(endpoint);
    }

    public webservices.CustomerDAO getCustomerDAO(java.net.URL portAddress) throws javax.xml.rpc.ServiceException {
        try {
            webservices.CustomerDAOSoapBindingStub _stub = new webservices.CustomerDAOSoapBindingStub(portAddress, this);
            _stub.setPortName(getCustomerDAOWSDDServiceName());
            return _stub;
        }
        catch (org.apache.axis.AxisFault e) {
            return null;
        }
    }

    public void setCustomerDAOEndpointAddress(java.lang.String address) {
        CustomerDAO_address = address;
    }

    /**
     * For the given interface, get the stub implementation.
     * If this service has no port for the given interface,
     * then ServiceException is thrown.
     */
    public java.rmi.Remote getPort(Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
        try {
            if (webservices.CustomerDAO.class.isAssignableFrom(serviceEndpointInterface)) {
                webservices.CustomerDAOSoapBindingStub _stub = new webservices.CustomerDAOSoapBindingStub(new java.net.URL(CustomerDAO_address), this);
                _stub.setPortName(getCustomerDAOWSDDServiceName());
                return _stub;
            }
        }
        catch (java.lang.Throwable t) {
            throw new javax.xml.rpc.ServiceException(t);
        }
        throw new javax.xml.rpc.ServiceException("There is no stub implementation for the interface:  " + (serviceEndpointInterface == null ? "null" : serviceEndpointInterface.getName()));
    }

    /**
     * For the given interface, get the stub implementation.
     * If this service has no port for the given interface,
     * then ServiceException is thrown.
     */
    public java.rmi.Remote getPort(javax.xml.namespace.QName portName, Class serviceEndpointInterface) throws javax.xml.rpc.ServiceException {
        if (portName == null) {
            return getPort(serviceEndpointInterface);
        }
        java.lang.String inputPortName = portName.getLocalPart();
        if ("CustomerDAO".equals(inputPortName)) {
            return getCustomerDAO();
        }
        else  {
            java.rmi.Remote _stub = getPort(serviceEndpointInterface);
            ((org.apache.axis.client.Stub) _stub).setPortName(portName);
            return _stub;
        }
    }

    public javax.xml.namespace.QName getServiceName() {
        return new javax.xml.namespace.QName("http://webservices", "CustomerDAOService");
    }

    private java.util.HashSet ports = null;

    public java.util.Iterator getPorts() {
        if (ports == null) {
            ports = new java.util.HashSet();
            ports.add(new javax.xml.namespace.QName("http://webservices", "CustomerDAO"));
        }
        return ports.iterator();
    }

    /**
    * Set the endpoint address for the specified port name.
    */
    public void setEndpointAddress(java.lang.String portName, java.lang.String address) throws javax.xml.rpc.ServiceException {
        
if ("CustomerDAO".equals(portName)) {
            setCustomerDAOEndpointAddress(address);
        }
        else 
{ // Unknown Port Name
            throw new javax.xml.rpc.ServiceException(" Cannot set Endpoint Address for Unknown Port" + portName);
        }
    }

    /**
    * Set the endpoint address for the specified port name.
    */
    public void setEndpointAddress(javax.xml.namespace.QName portName, java.lang.String address) throws javax.xml.rpc.ServiceException {
        setEndpointAddress(portName.getLocalPart(), address);
    }

}

CustomerDAOSoapBindingStub.java
/**
 * CustomerDAOSoapBindingStub.java
 *
 * This file was auto-generated from WSDL
 * by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
 */

package webservices;

public class CustomerDAOSoapBindingStub extends org.apache.axis.client.Stub implements webservices.CustomerDAO {
    private java.util.Vector cachedSerClasses = new java.util.Vector();
    private java.util.Vector cachedSerQNames = new java.util.Vector();
    private java.util.Vector cachedSerFactories = new java.util.Vector();
    private java.util.Vector cachedDeserFactories = new java.util.Vector();

    static org.apache.axis.description.OperationDesc [] _operations;

    static {
        _operations = new org.apache.axis.description.OperationDesc[3];
        _initOperationDesc1();
    }

    private static void _initOperationDesc1(){
        org.apache.axis.description.OperationDesc oper;
        org.apache.axis.description.ParameterDesc param;
        oper = new org.apache.axis.description.OperationDesc();
        oper.setName("editCustomer");
        param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://webservices", "client"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://model", "Customer"), model.Customer.class, false, false);
        oper.addParameter(param);
        oper.setReturnType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "boolean"));
        oper.setReturnClass(boolean.class);
        oper.setReturnQName(new javax.xml.namespace.QName("http://webservices", "editCustomerReturn"));
        oper.setStyle(org.apache.axis.constants.Style.WRAPPED);
        oper.setUse(org.apache.axis.constants.Use.LITERAL);
        _operations[0] = oper;

        oper = new org.apache.axis.description.OperationDesc();
        oper.setName("searchCustomer");
        param = new org.apache.axis.description.ParameterDesc(new javax.xml.namespace.QName("http://webservices", "key"), org.apache.axis.description.ParameterDesc.IN, new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "string"), java.lang.String.class, false, false);
        oper.addParameter(param);
        oper.setReturnType(new javax.xml.namespace.QName("http://model", "Customer"));
        oper.setReturnClass(model.Customer[].class);
        oper.setReturnQName(new javax.xml.namespace.QName("http://webservices", "searchCustomerReturn"));
        oper.setStyle(org.apache.axis.constants.Style.WRAPPED);
        oper.setUse(org.apache.axis.constants.Use.LITERAL);
        _operations[1] = oper;
    }

    public CustomerDAOSoapBindingStub() throws org.apache.axis.AxisFault {
         this(null);
         try {
         super.cachedEndpoint = new java.net.URL("http://localhost:8080/wsCustomer/services/CustomerDAO");
         }catch(Exception e) {
        	 e.printStackTrace();
         }
    }

    public CustomerDAOSoapBindingStub(java.net.URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
         this(service);
         super.cachedEndpoint = endpointURL;
    }

    public CustomerDAOSoapBindingStub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {
        if (service == null) {
            super.service = new org.apache.axis.client.Service();
        } else {
            super.service = service;
        }
        ((org.apache.axis.client.Service)super.service).setTypeMappingVersion("1.2");
            java.lang.Class cls;
            javax.xml.namespace.QName qName;
            javax.xml.namespace.QName qName2;
            java.lang.Class beansf = org.apache.axis.encoding.ser.BeanSerializerFactory.class;
            java.lang.Class beandf = org.apache.axis.encoding.ser.BeanDeserializerFactory.class;
            java.lang.Class enumsf = org.apache.axis.encoding.ser.EnumSerializerFactory.class;
            java.lang.Class enumdf = org.apache.axis.encoding.ser.EnumDeserializerFactory.class;
            java.lang.Class arraysf = org.apache.axis.encoding.ser.ArraySerializerFactory.class;
            java.lang.Class arraydf = org.apache.axis.encoding.ser.ArrayDeserializerFactory.class;
            java.lang.Class simplesf = org.apache.axis.encoding.ser.SimpleSerializerFactory.class;
            java.lang.Class simpledf = org.apache.axis.encoding.ser.SimpleDeserializerFactory.class;
            java.lang.Class simplelistsf = org.apache.axis.encoding.ser.SimpleListSerializerFactory.class;
            java.lang.Class simplelistdf = org.apache.axis.encoding.ser.SimpleListDeserializerFactory.class;
            qName = new javax.xml.namespace.QName("http://model", "Customer");
            cachedSerQNames.add(qName);
            cls = model.Customer.class;
            cachedSerClasses.add(cls);
            cachedSerFactories.add(beansf);
            cachedDeserFactories.add(beandf);

    }

    protected org.apache.axis.client.Call createCall() throws java.rmi.RemoteException {
        try {
            org.apache.axis.client.Call _call = super._createCall();
            if (super.maintainSessionSet) {
                _call.setMaintainSession(super.maintainSession);
            }
            if (super.cachedUsername != null) {
                _call.setUsername(super.cachedUsername);
            }
            if (super.cachedPassword != null) {
                _call.setPassword(super.cachedPassword);
            }
            if (super.cachedEndpoint != null) {
                _call.setTargetEndpointAddress(super.cachedEndpoint);
            }
            if (super.cachedTimeout != null) {
                _call.setTimeout(super.cachedTimeout);
            }
            if (super.cachedPortName != null) {
                _call.setPortName(super.cachedPortName);
            }
            java.util.Enumeration keys = super.cachedProperties.keys();
            while (keys.hasMoreElements()) {
                java.lang.String key = (java.lang.String) keys.nextElement();
                _call.setProperty(key, super.cachedProperties.get(key));
            }
            // All the type mapping information is registered
            // when the first call is made.
            // The type mapping information is actually registered in
            // the TypeMappingRegistry of the service, which
            // is the reason why registration is only needed for the first call.
            synchronized (this) {
                if (firstCall()) {
                    // must set encoding style before registering serializers
                    _call.setEncodingStyle(null);
                    for (int i = 0; i < cachedSerFactories.size(); ++i) {
                        java.lang.Class cls = (java.lang.Class) cachedSerClasses.get(i);
                        javax.xml.namespace.QName qName =
                                (javax.xml.namespace.QName) cachedSerQNames.get(i);
                        java.lang.Object x = cachedSerFactories.get(i);
                        if (x instanceof Class) {
                            java.lang.Class sf = (java.lang.Class)
                                 cachedSerFactories.get(i);
                            java.lang.Class df = (java.lang.Class)
                                 cachedDeserFactories.get(i);
                            _call.registerTypeMapping(cls, qName, sf, df, false);
                        }
                        else if (x instanceof javax.xml.rpc.encoding.SerializerFactory) {
                            org.apache.axis.encoding.SerializerFactory sf = (org.apache.axis.encoding.SerializerFactory)
                                 cachedSerFactories.get(i);
                            org.apache.axis.encoding.DeserializerFactory df = (org.apache.axis.encoding.DeserializerFactory)
                                 cachedDeserFactories.get(i);
                            _call.registerTypeMapping(cls, qName, sf, df, false);
                        }
                    }
                }
            }
            return _call;
        }
        catch (java.lang.Throwable _t) {
            throw new org.apache.axis.AxisFault("Failure trying to get the Call object", _t);
        }
    }

    public boolean editCustomer(model.Customer client) throws java.rmi.RemoteException {
        if (super.cachedEndpoint == null) {
            throw new org.apache.axis.NoEndPointException();
        }
        org.apache.axis.client.Call _call = createCall();
        _call.setOperation(_operations[0]);
        _call.setUseSOAPAction(true);
        _call.setSOAPActionURI("");
        _call.setEncodingStyle(null);
        _call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
        _call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
        _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
        _call.setOperationName(new javax.xml.namespace.QName("http://webservices", "editCustomer"));

        setRequestHeaders(_call);
        setAttachments(_call);
 try {        java.lang.Object _resp = _call.invoke(new java.lang.Object[] {client});

        if (_resp instanceof java.rmi.RemoteException) {
            throw (java.rmi.RemoteException)_resp;
        }
        else {
            extractAttachments(_call);
            try {
                return ((java.lang.Boolean) _resp).booleanValue();
            } catch (java.lang.Exception _exception) {
                return ((java.lang.Boolean) org.apache.axis.utils.JavaUtils.convert(_resp, boolean.class)).booleanValue();
            }
        }
  } catch (org.apache.axis.AxisFault axisFaultException) {
  throw axisFaultException;
}
    }

    public model.Customer[] searchCustomer(java.lang.String key) throws java.rmi.RemoteException {
        if (super.cachedEndpoint == null) {
            throw new org.apache.axis.NoEndPointException();
        }
        org.apache.axis.client.Call _call = createCall();
        _call.setOperation(_operations[1]);
        _call.setUseSOAPAction(true);
        _call.setSOAPActionURI("");
        _call.setEncodingStyle(null);
        _call.setProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
        _call.setProperty(org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);
        _call.setSOAPVersion(org.apache.axis.soap.SOAPConstants.SOAP11_CONSTANTS);
        _call.setOperationName(new javax.xml.namespace.QName("http://webservices", "searchCustomer"));

        setRequestHeaders(_call);
        setAttachments(_call);
 try {        java.lang.Object _resp = _call.invoke(new java.lang.Object[] {key});

        if (_resp instanceof java.rmi.RemoteException) {
            throw (java.rmi.RemoteException)_resp;
        }
        else {
            extractAttachments(_call);
            try {
                return (model.Customer[]) _resp;
            } catch (java.lang.Exception _exception) {
                return (model.Customer[]) org.apache.axis.utils.JavaUtils.convert(_resp, model.Customer[].class);
            }
        }
  } catch (org.apache.axis.AxisFault axisFaultException) {
  throw axisFaultException;
}
    }
}

Create standalone client application

Beside the classes generated from the WSDL file, we need to create some other classes (some relationship among classes are omitted):

  • SearchCustomerFrm: the interface to search all customer whose name contains the input keyword
  • EditCustomerFrm: the interface to update information of the chosen customer.

The operation of these classes is follow:

  • Steps 1-9 are to search all customers whose name contains the input keyword. The SearchCustomerFrm calls the Stub (3), and the Stub binds the remote service by using SOAP message and protocol (5-7).
  • Steps 10-14 are to call the EditCustomerFrm when selecting a customer from the search results list.
  • Steps 15-26 are to edit the information of the chosen customer. The EditCustomerFrm calls the Stub (20), and the Stub binds the remote service by using SOAP message (22-24).
SearchCustomer.java
package view;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

import org.apache.axis.wsdl.WSDL2Java;

import control.CustomerWS;
import model.Customer;
import webservices.CustomerDAOSoapBindingStub;

public class SearchCustomerFrm extends JFrame implements ActionListener{
	private Customer[] listCustomer=null;
	private JTextField txtKey;
	private JButton btnSearch;
	private JTable tblResult;
	
	public SearchCustomerFrm(){
		super("Search customer to edit");
		//listCustomer = new ArrayList<Customer>();
		
		JPanel pnMain = new JPanel();
		pnMain.setSize(this.getSize().width-5, this.getSize().height-20);		
		pnMain.setLayout(new BoxLayout(pnMain,BoxLayout.Y_AXIS));
		pnMain.add(Box.createRigidArea(new Dimension(0,10)));
		
		JLabel lblHome = new JLabel("Search a customer to edit");
		lblHome.setAlignmentX(Component.CENTER_ALIGNMENT);	
		lblHome.setFont (lblHome.getFont ().deriveFont (20.0f));
		pnMain.add(lblHome);
		pnMain.add(Box.createRigidArea(new Dimension(0,20)));
		
		JPanel pn1 = new JPanel();
		pn1.setLayout(new BoxLayout(pn1,BoxLayout.X_AXIS));
		pn1.setSize(this.getSize().width-5, 20);
		pn1.add(new JLabel("Client name: "));
		txtKey = new JTextField();
		pn1.add(txtKey);
		btnSearch = new JButton("Search");
		btnSearch.addActionListener(this);
		pn1.add(btnSearch);
		pnMain.add(pn1);
		pnMain.add(Box.createRigidArea(new Dimension(0,10)));

		JPanel pn2 = new JPanel();
		pn2.setLayout(new BoxLayout(pn2,BoxLayout.Y_AXIS));		
		tblResult = new JTable();
		JScrollPane scrollPane= new  JScrollPane(tblResult);
		tblResult.setFillsViewportHeight(false); 
		scrollPane.setPreferredSize(new Dimension(scrollPane.getPreferredSize().width, 250));
		
		tblResult.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				int column = tblResult.getColumnModel().getColumnIndexAtX(e.getX()); // get the coloum of the button
				int row = e.getY() / tblResult.getRowHeight(); // get the row of the button

				// *Checking the row or column is valid or not
				if (row < tblResult.getRowCount() && row >= 0 && column < tblResult.getColumnCount() && column >= 0) {
					(new EditCustomerFrm(listCustomer[row])).setVisible(true);
					dispose();
				}
			}
		});

		pn2.add(scrollPane);
		pnMain.add(pn2);	
		this.add(pnMain);
		this.setSize(600,300);				
		this.setLocation(200,10);
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		JButton btnClicked = (JButton)e.getSource();
		if(btnClicked.equals(btnSearch)){
			if((txtKey.getText() == null)||(txtKey.getText().length() == 0))
				return;
			
			try {
				listCustomer = (new CustomerDAOSoapBindingStub()).searchCustomer(txtKey.getText().trim());
				//System.out.println("list length: " + listCustomer.length);

				String[] columnNames = {"Id", "Name", "idCard", "Address", "Email", "Tel", "Note"};
				String[][] value = new String[listCustomer.length][columnNames.length];
				for(int i=0; i<listCustomer.length; i++){
					value[i][0] = listCustomer[i].getId() +"";
					value[i][1] = listCustomer[i].getName();
					value[i][2] = listCustomer[i].getIdCard();
					value[i][3] = listCustomer[i].getAddress();
					value[i][4] = listCustomer[i].getEmail();
					value[i][5] = listCustomer[i].getTel();
					value[i][6] = listCustomer[i].getNote();
				}
				DefaultTableModel tableModel = new DefaultTableModel(value, columnNames) {
					@Override
					public boolean isCellEditable(int row, int column) {
						//unable to edit cells
						return false;
					}
				};
				tblResult.setModel(tableModel);
			}catch(Exception ex) {
				ex.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) {
		SearchCustomerFrm view = new SearchCustomerFrm();
		view.setVisible(true);
	}	
}
EditCustomerFrm.java
package view;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import control.CustomerWS;
import model.Customer;
import webservices.CustomerDAOSoapBindingStub;

public class EditCustomerFrm extends JFrame implements ActionListener{
	private Customer customer;
	private JTextField txtId, txtName, txtIdcard, txtAddress, txtEmail, txtTel, txtNote;
	private JButton btnUpdate, btnReset;
	
	
	public EditCustomerFrm(Customer client){
		super("Edit a customer");
		this.customer = client;
		
		JPanel pnMain = new JPanel();
		pnMain.setSize(this.getSize().width-5, this.getSize().height-20);		
		pnMain.setLayout(new BoxLayout(pnMain,BoxLayout.Y_AXIS));
		pnMain.add(Box.createRigidArea(new Dimension(0,10)));
		
		JLabel lblHome = new JLabel("Edit a customer information");
		lblHome.setAlignmentX(Component.CENTER_ALIGNMENT);	
		lblHome.setFont (lblHome.getFont ().deriveFont (20.0f));
		pnMain.add(lblHome);
		pnMain.add(Box.createRigidArea(new Dimension(0,20)));
		
		txtId = new JTextField(15);
		txtId.setEditable(false);
		txtName = new JTextField(15);
		txtIdcard = new JTextField(15);
		txtAddress = new JTextField(15);
		txtEmail = new JTextField(15);
		txtTel = new JTextField(15);
		txtNote = new JTextField(15);
		btnUpdate = new JButton("Update");
		btnReset = new JButton("Reset");
		
		JPanel content = new JPanel();
		content.setLayout(new GridLayout(8,2));
		content.add(new JLabel("Customer ID:")); 	content.add(txtId);
		content.add(new JLabel("Name:")); 	content.add(txtName);
		content.add(new JLabel("Idcard:")); 	content.add(txtIdcard);
		content.add(new JLabel("Address:")); 	content.add(txtAddress);
		content.add(new JLabel("Email:")); 	content.add(txtEmail);
		content.add(new JLabel("Tel:")); 	content.add(txtTel);
		content.add(new JLabel("Note:")); 	content.add(txtNote);
		content.add(btnUpdate); 	content.add(btnReset);
		pnMain.add(content);		  
		btnUpdate.addActionListener(this);
		btnReset.addActionListener(this);
		
		initForm();		
		this.setContentPane(pnMain);
		this.setSize(600,300);				
		this.setLocation(200,10);
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	}
	
	private void initForm(){
		if(customer != null){
			txtId.setText(customer.getId()+"");
			txtName.setText(customer.getName());
			txtIdcard.setText(customer.getIdCard());
			txtAddress.setText(customer.getAddress());
			txtEmail.setText(customer.getEmail());
			txtTel.setText(customer.getTel());
			txtNote.setText(customer.getNote());
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		JButton btnClicked = (JButton)e.getSource();
		if(btnClicked.equals(btnReset)){
			initForm();
			return;
		}
		if(btnClicked.equals(btnUpdate)){
			customer.setName(txtName.getText());
			customer.setIdCard(txtIdcard.getText());
			customer.setAddress(txtAddress.getText());
			customer.setEmail(txtEmail.getText());
			customer.setTel(txtTel.getText());
			customer.setNote(txtNote.getText());
			try {
				boolean ok = (new CustomerDAOSoapBindingStub()).editCustomer(customer);
				if(ok) {
					JOptionPane.showMessageDialog(this, "Update succesfully!");
					this.dispose();
				}
				else {
					JOptionPane.showMessageDialog(this, "Error when updating!");
				}
			}catch(Exception ex) {
				ex.printStackTrace();
			}
		}
	}
}