Engineering Full Stack Apps with Java and JavaScript
We will create a simple soap web service with richer data types ( List and a user defined class) using wsimport we will generate the client side stubs.
We will create an employee service that will return employee details based on employee numbers. We will have three methods
one that takes an employee number (int) and return an Employee object (Employee.java),
another method that takes a list of employee numbers and return a list of employee objects (List<Employee>) and
one that return all employee details. We will use a utility class to populate sample values.
When we use programmer defined types and collections we need to follow certain guidelines for correct results.
One such guideline that we follow here is: The JavaBean properties are of types String and int with getters and setters, and collections like List should have a toArray() method.
Package and import statements are not shown in examples, you can add them manually or an IDE like eclipse will do most of them for you.
We will not be using any server like Glassfish for this example, but will be using Java SE endpoint publisher. You can skip step 4 if you are deploying in an application server like Glassfish. You can then assume the wsdl url according to the service class name.
Create an employee class Employee.java with two fields – number and name.
Code:
public class Employee {
String empName;
int empNumber;
Employee(String name, int number) {
this.empName = name;
this.empNumber = number;
}
//You should give a default constructor
Employee() {}
//setters and getters should be present
}
Create a utility class EmployeeUtils.java that has following methods:
void createEmployees() that creates a sample list of employees.
Employee findEmployee(int empNum)
List<Employee> findEmployees(List<Integer> empNums)
List<Employee> getAllEmployees()
The createEmployees() method can be called by the constructor of SIB or EmployeeUtils itself, and findEmployees() and getAllEmployees() will be called by corresponding web methods in the SIB.
Code:
public class EmployeeUtils {
List<Employee> empList;
EmployeeUtils() {
empList = new ArrayList<Employee>();
createEmployees();
}
public void createEmployees() {
Employee emp1 = new Employee();
emp1.setEmpName("Sneha");
emp1.setEmpNumber(1);
empList.add(emp1);
Employee emp2 = new Employee();
emp2.setEmpName("Heartin");
emp2.setEmpNumber(2);
empList.add(emp2);
}
public Employee findEmployee(int empNum) {
for (Employee e : empList) {
if (e.getEmpNumber() == empNum)
return e;
}
return null;
}
public List<Employee> findEmployees(List<Integer> empNums) {
List<Employee> employeeList = new ArrayList<Employee>();
for (Integer i : empNums) {
employeeList.add(findEmployee(i));
}
return employeeList;
}
public List<Employee> getAllEmployees() {
return this.empList;
}
}
Employee findEmployee(int empNum)
List<Employee> findEmployees(List<Integer> empNums)
List<Employee> getAllEmployees()
The findEmployees() and getAllEmployees() will call corresponding methods in the utility class and return values.
Code:
EmployeeService.java
@WebService
@SOAPBinding(style=Style.DOCUMENT,use=Use.LITERAL, parameterStyle=ParameterStyle.WRAPPED)
public interface EmployeeService
{
@WebMethod
public Employee findEmployee(int empNum);
@WebMethod
public List<Employee> findEmployees(List<Integer> empNums);
@WebMethod
public List<Employee> getAllEmployees();
}
EmployeeServiceImpl.java
@WebService(endpointInterface = "com.javajee.ws.example4.EmployeeService")
public class EmployeeServiceImpl implements EmployeeService {
EmployeeUtils empUtils = new EmployeeUtils();
public Employee findEmployee(int empNum) {
return empUtils.findEmployee(empNum);
}
public List<Employee> findEmployees(List<Integer> empNums) {
return empUtils.findEmployees(empNums);
}
public List<Employee> getAllEmployees() {
return empUtils.getAllEmployees();
}
}
You can skip this step if you are deploying in an application server like Glassfish. You can then assume the wsdl url according to the service class name.
The wsdl and xsd generated are attached at the end.
Code:
public class EmployeeServicePublisher {
public static void main(String[] args)
{
Endpoint endpoint = Endpoint.create(new EmployeeServiceImpl());
endpoint.publish("http://127.0.0.1:8888/ex4");
}
}
wsimport -keep -p client.generated http://127.0.0.1:8888/ex4?wsdl
This command will create a set of java files and their corresponding class files in client/generated folder which we can use for writing the client. Without –keep option only class files will be generated.
Files generated in my case are package-info.java, ObjectFactory.java, Employee.java, EmployeeService.java, EmployeeServiceImpleService.java. FindEmployee.java, FindEmployeeResponse.java, FindEmployees.java, FindEmployeesResponse.java, GetAllEmployees.java, GetAllEmployeesResponse.java and their corresponsing .class files.
Before using wsimport, you needed to first pass the wsdl url into the URL constructor to create an URL object. Then you needed to create a QName object using QName constructor passing the service url and the service name. The Service.create() method accepts url and QName and then create a factory for the service of type Service. The service.getPort() then returns a reference to a java object of the SEI type. However using the wsimport generated files, we can easily get the port.
Code:
EmployeeServiceImplService service = new EmployeeServiceImplService();
EmployeeService port = service.getEmployeeServiceImplPort();
This is different from previous code because the url and QName details are there in the wsimport generated EmployeeServiceImplService.java class.
Previous code (without using wsimport):
URL url = new URL("http://127.0.0.1:8888/ts?wsdl");
QName qname = new
QName("http://tsexample1.ws.javajee.com/","TimeServiceImplService");
Service service = Service.create(url,qname);
TimeService port = service.getPort(TimeService.class);
Complete Client Code (with package and import statements):
package client;
import client.generated.*;
import java.util.List;
import java.util.ArrayList;
public class EmployeeServiceClient {
public static void main(String[] args) {
EmployeeServiceImplService service = new EmployeeServiceImplService();
EmployeeService port = service.getEmployeeServiceImplPort();
System.out.println("\nAll Employees:");
List<Employee> allEmps = port.getAllEmployees();
for (Employee e : allEmps) {
System.out.println("Emp Number= " + e.getEmpNumber() + ". Emp Name= "
+ e.getEmpName());
}
System.out.println("\nFind employee with empnumber:");
Employee emp = port.findEmployee(2);
System.out.println("Emp Number= " + emp.getEmpNumber() + ". Emp Name= "
+ emp.getEmpName());
System.out.println("\nAll Employees From a List:");
List<Integer> inputList = new ArrayList<Integer>();
inputList.add(1);
inputList.add(2);
List<Employee> selectEmps = port.findEmployees(inputList);
for (Employee e : selectEmps) {
System.out.println("Emp Number= " + e.getEmpNumber() + ". Emp Name= "
+ e.getEmpName());
}
}
}
The client executed fine with expected output:
Summary Of steps
Step 1: Create the user defined class Employee.java
Step 2: Create the utility class EmployeeUtils.java
Step 3: Create SEI and SIB with required web methods
Step 4: Create the publisher and execute
Step 5: Create the client support code using wsimport
Step 6: Create the client file and execute