2012/10/28
28 Oct, 2012

How to develop CXF based JAX-WS with WSO2 Developer Studio

  • Melan Jayasingha
  • Software Engineer - WSO2

Introduction

Java API for XML-Based Web Services (JAX-WS), which is also known as JSR-224, is the next generation Web services programming model that extends the foundation provided by the Java API for XML-based RPC (JAX-RPC) programming model. Using JAX-WS, developing Web services and clients is simplified with greater platform independence for Java applications by the use of dynamic proxies and Java annotations.

Apache CXF is an open source web service framework that provides an easy to use, standard-based programming model for developing web services. Web services can be implemented using different application protocols like SOAP, XML, JSON, RESTful HTTP, and supports various transport protocols like HTTP or JMS.

WSO2 Developer Studio (formerly named WSO2 Carbon Studio) is a complete Eclipse-based SOA development environment for the award-winning WSO2 Carbon platform. WSO2 Developer Studio supports the development of Web applications, gadgets, services, business processes and more, enabling a developer to first build an application and then deploy and debug it from the IDE itself

In this article I will use the following software:

Software Version Required
WSO2 Developer Studio 2.0.0
Java Development Kit (JDK) JDK 6 Update 32
WSO2 Application Server 4.5.0 M3
Apache CXF 2.5.4

Contents

  1. Creating a Web Service
    1. Creating a Web Service Project
    2. Creating a Web Service from a Java Class
  2. Deploying the Web Service
  3. Testing the Web Service
  4. Consuming the Web Service
  5. Samples

1. Creating a Web Service

1.1 Creating a Web Service Project

First, we create an empty JAX-WS service Project, to create a JAX-WS Service Project,

  1. Go to the J2EE perspective

  2. Select File->New->Project and select WSO2 category

  3. Under WSO2 category select Service Hosting->Project Types->JAX-WS Service Project from the new project wizard dialog

  4. There are two ways to create a JAX-WS project. "Create a JAX-WS Project" and "Create a JAX-WS Project using WSDL", to create a empty project we select  "Create a JAX-WS Project"

  5. Name the project AccountServiceProject. Select a location for the project. Click Finish.

  1. Right-click the AccountServiceProject project and choose New > JAX-WS Service Class

  2. Name the web service class 'AccountServiceImpl' and type "org.example.webservice" (or any other qualified package name) in package name field
  3. In Service Interface section, name the web service interface class 'AccountService' and type "org.example.webservice" (or any other qualified package name) in package name field
  4. Deselect "Add sample web service method to new class".
  5. Click Finish. The Projects Explore view displays the structure of the project and the source code is shown in the java editor area.

  6. Open service interface class (AccountService.java)  that you generated in the previous steps and add following method to the interface

    public int createAccount(boolean print);
    public boolean checkAccount(int accountNo);
    public int checkAccountBalance(int accountNo);
    public boolean creditAccount(int accountNo, int amount);
    public boolean debitAccount(int accountNo, int amount);

    AccountService interface would look like this

    package org.example.webservice;
    
    import javax.jws.WebService;
    
    @WebService
    public interface AccountService {
    
     public int createAccount(boolean print);
    
     public boolean checkAccount(int accountNo);
    
     public int checkAccountBalance(int accountNo);
    
     public boolean creditAccount(int accountNo, int amount);
    
     public boolean debitAccount(int accountNo, int amount);
    
    }
    
  7. Open web service implementation class (AccountServiceImpl.java) and implement missing methods as below
    package org.example.webservice;
    
    import java.util.Hashtable;
    import java.util.Random;
    
    import javax.jws.WebMethod;
    import javax.jws.WebParam;
    import javax.jws.WebService;
    
    @WebService(serviceName = "AccountServiceImpl")
    public class AccountServiceImpl implements AccountService {
    
     // Account no list of the customers
     static Hashtable<integer, integer> accountStore = new Hashtable<integer, integer>();
    
     /**
      * Generates the random account no at registration
      * 
      * @return the random account number integer
      */
     private int randomAccountGenerate() {
      Random randomGenerator = new Random();
      return randomGenerator.nextInt(1000);
     }
    
     /**
      * create a new account and store
      * 
      * @return accountNo
      * 
      */
    @WebMethod(operationName = "createAccount")
     public int createAccount(@WebParam(name = "printOnConsole") boolean print) {
    
      int accountNo = 0;
      // Generate the random account no
      accountNo = randomAccountGenerate();
      // create the entry in the account store
      accountStore.put(accountNo, 0);
      if(print){
       System.out.println("New account created, No= " + accountNo);
      }
      return accountNo;
     }
    
     /**
      * Check whether the account is available
      * 
      * @param accountNo
      * @return isAvailable
      * 
      */
     @WebMethod(operationName = "checkAccount")
     public boolean checkAccount(@WebParam(name = "accountNo") int accountNo) {
      if (accountStore.containsKey(accountNo)) {
       return true;
      }
      return false;
     }
    
     /**
      * @param accountNo
      * @return balance
      */
     @WebMethod(operationName = "checkAccountBalance")
     public int checkAccountBalance(@WebParam(name = "accountNo") int accountNo) {
      if (checkAccount(accountNo)) {
       return accountStore.get(accountNo);
      }
      return 0;
     }
    
     /**
      * Increase the balance by credit amount
      * 
      * @param accountNo
      * @param amount
      * @return success
      * 
      */
     @WebMethod(operationName = "creditAccount")
     public boolean creditAccount(@WebParam(name = "accountNo") int accountNo,
       @WebParam(name = "amount") int amount) {
      if (checkAccount(accountNo)) {
       accountStore.put(accountNo,
         (accountStore.remove(accountNo) + amount));
       return true;
      }
      return false;
     }
    
     /**
      * Decrease the balance by the debit amount
      * 
      * @param accountNo
      * @param amount
      * @return Operation successfulness
      * 
      */
     @WebMethod(operationName = "debitAccount")
     public boolean debitAccount(@WebParam(name = "accountNo") int accountNo,
       @WebParam(name = "amount") int amount) {
      if (checkAccount(accountNo) && (accountStore.get(accountNo) >= amount)) {
       accountStore.put(accountNo,
         (accountStore.remove(accountNo) - amount));
       return true;
      }
      return false;
     }
    
    }
    

2. Deploying the Web Service

There are two method to deploy our JAX-WS service into WSO2 Application Server.

We can export JAX-WS project as a web application (war) file and deploy it on WSO2 Appliation Server via web console.
To create a deployable archive (WAR) and deploy on WSO2 Application Server

  1. Right-click on project, 
  2. Select Export Project as Deployable Archive
  3. Then choose destination location.
  4. Log into WSO2 Application server
  5. In the navigator, under Manage/JAX-WS/JAX-RS, click Add .
  6. Click Browse to locate the file you want to upload. If you want to add multiple JAX-WS/JAX-RS apps at the same time, click on the '+' sign at the right side, and new additional entry to upload a JAX-WS/JAX-RS archive will appear each time you click. So you can select all the archives you want and deploy them at the same time.
  7. Click Upload. The Running JAX-WS/JAX-RS Applications page appears. Subsequently, if the deployment is successful, it will appear in the list. If the application is faulty, a Faulty JAX-WS/JAX-RS Application link will appear. You can click the link to view the errors

We can add it as dependency of Carbon Application project which can deploy on WSO2 Application Server. 

To do this,

  1. Select File->New->Project...
  2. Select "Carbon Application Project" under WSO2 category
  3. Name the project as "CappProject" and select "AccountServiceProject" under dependencies and click Finish.  
  4. Go to Servers view, Right-click on the blank space -> New-> Server
  5. Select WSO2 Carbon 4.0 based server under WSO2 category
  6. Provide name for server name (e.g. WSO2 Application Server 4.5) and click next
  7. You will need to specify location of the WSO2 Application Server instance and click next. 
  8. In the Next window, you can change configuration setting for server instance such as Carbon server port, server offset, etc.. You can change ports if you want. If the default ports are not used by any other application, you can keep them as they are. After setting the ports click  next. 
  9. In theNext window, You will able to view available carbon application project in left panel, select   "CappProject" and click Add, then click finish 

 

3. Testing the Web Service

We can test our web service using the WSO2 Application Server's web console

Log into WSO2 Application Server console, in the navigator, under Manage/JAX-WS/JAX-RS, click List. The Running JAX-WS/JAX-RS Applications page appears.

Click on "Find Services", It will list all SOAP and RESTful services deployed through our web service project.

We can copy WSDL's of the services  (e.g. https://10.100.3.42:9763/AccountServiceProject-1.0.0/services/account_service?wsdl) and try those services using the external Try-It tool which can be found under Tools/Try-It menu of WSO2 Application server.

We can try out "createAccount" method, it will return the account number of newly created account.

 

4. Consuming the Web Service

To consume our web service, we need to create a web service client. CXF provides us with many options to build clients for our services. You can use CXF wsdl2java tool to generate web service client stubs. Make sure you have installed and configured the Apache CXF runtime environment in your system and CXF Tools available in your system path.

wsdl2java -client <wsdl-path>

e.g.
wsdl2java -client https://10.100.3.42:9763/AccountServiceProject-1.0.0/services/account_se...

You will need to endorse the JAX-WS API 2.2 jar, otherwise run wsdl2java with "-frontend jaxws21" to generate JAX-WS 2.1 compliant code instead.

wsdl2java tool  generates all of the code needed to consume our web service including sample client with main(), would look like this (AccountService_AccountServicePort_Client)
package org.example.webservice;

/**
 * Please modify this class to meet your needs
 * This class is not complete
 */

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

/**
 * This class was generated by Apache CXF 2.5.2
 * 2012-06-12T17:33:20.094+05:30
 * Generated source version: 2.5.2
 * 
 */
public final class AccountService_AccountServicePort_Client {

    private static final QName SERVICE_NAME = new QName("https://webservice.example.org/", "AccountServiceService");

    private AccountService_AccountServicePort_Client() {
    }

    public static void main(String args[]) throws java.lang.Exception {
        URL wsdlURL = AccountServiceService.WSDL_LOCATION;
        if (args.length > 0 && args[0] != null && !"".equals(args[0])) { 
            File wsdlFile = new File(args[0]);
            try {
                if (wsdlFile.exists()) {
                    wsdlURL = wsdlFile.toURI().toURL();
                } else {
                    wsdlURL = new URL(args[0]);
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }
      
        AccountServiceService ss = new AccountServiceService(wsdlURL, SERVICE_NAME);
        AccountService port = ss.getAccountServicePort();  
        
        {
        System.out.println("Invoking debitAccount...");
        int _debitAccount_arg0 = 0;
        int _debitAccount_arg1 = 0;
        boolean _debitAccount__return = port.debitAccount(_debitAccount_arg0, _debitAccount_arg1);
        System.out.println("debitAccount.result=" + _debitAccount__return);


        }
        {
        System.out.println("Invoking checkAccount...");
        int _checkAccount_arg0 = 0;
        boolean _checkAccount__return = port.checkAccount(_checkAccount_arg0);
        System.out.println("checkAccount.result=" + _checkAccount__return);


        }
        {
        System.out.println("Invoking creditAccount...");
        int _creditAccount_arg0 = 0;
        int _creditAccount_arg1 = 0;
        boolean _creditAccount__return = port.creditAccount(_creditAccount_arg0, _creditAccount_arg1);
        System.out.println("creditAccount.result=" + _creditAccount__return);


        }
        {
        System.out.println("Invoking createAccount...");
        boolean _createAccount_arg0 = false;
        int _createAccount__return = port.createAccount(_createAccount_arg0);
        System.out.println("createAccount.result=" + _createAccount__return);


        }
        {
        System.out.println("Invoking checkAccountBalance...");
        int _checkAccountBalance_arg0 = 0;
        int _checkAccountBalance__return = port.checkAccountBalance(_checkAccountBalance_arg0);
        System.out.println("checkAccountBalance.result=" + _checkAccountBalance__return);


        }

        System.exit(0);
    }

}

We modify this class to meet our requirements as below

package org.example.webservice;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;

public final class AccountService_AccountServicePort_Client {

 private static final QName SERVICE_NAME = new QName(
   "https://webservice.example.org/", "AccountServiceService");

 private AccountService_AccountServicePort_Client() {
 }

 public static void main(String args[]) throws java.lang.Exception {
  URL wsdlURL = AccountServiceService.WSDL_LOCATION;
  if (args.length > 0 && args[0] != null && !"".equals(args[0])) {
   File wsdlFile = new File(args[0]);
   try {
    if (wsdlFile.exists()) {
     wsdlURL = wsdlFile.toURI().toURL();
    } else {
     wsdlURL = new URL(args[0]);
    }
   } catch (MalformedURLException e) {
    e.printStackTrace();
   }
  }

  AccountServiceService ss = new AccountServiceService(wsdlURL,
    SERVICE_NAME);
  AccountService port = ss.getAccountServicePort();
  int accountNo = 0;
  int accountBalance = 0;

  // Invoke the create account service.
  boolean printOnConsole = false; // print details on server's console
  accountNo = port.createAccount(printOnConsole);
  System.out.println(String.format(
    "Account Created Under Account Number :%d", accountNo));

  // Invoke the check account service
  System.out.println("Verifying Account Existence......");
  System.out.println("Account Existence Verifyied : "
    + port.checkAccount(accountNo));

  // Invoke the credit account service.
  boolean creditAccountResponse = port.creditAccount(accountNo, 20000);
  System.out.println("Account Credited by US$ 20000 : "
    + creditAccountResponse);

  // Invoke the check account balance service.
  accountBalance = port.checkAccountBalance(accountNo);
  System.out.println(String.format("Current Account Balance (US$): %d",
    accountBalance));

  // Invoke the debit account service.
  boolean debitAccountResponse = port.debitAccount(accountNo, 8000);
  System.out.println("Account Debited by  US$ 8000 : "
    + debitAccountResponse);

  // Invoke the check account balance service.
  accountBalance = port.checkAccountBalance(accountNo);
  System.out.println(String.format("Current Account Balance (US$): %d",
    accountBalance));

  System.exit(0);
 }

}

Output of client program would look like this

 

5. Samples

Web server project
Client sample

 

Summary

In this articale we demonstrate how we use WSO2 Developer Studio to develop, test and deploy Apache CXF JAX Web Services for WSO2 Application Server and consuming the JAX web service using java client program. All the important points were discussed where you can try out the above scenario using given source resources.

Author
Melan Nimesh Jayasingha, Software Engineer

 

About Author

  • Melan Jayasingha
  • Software Engineer
  • WSO2