Monday, October 8, 2012

How to create a SOAP Web Services with Apache CXF


Create new Dynamic Web Project


Choose Dynamic web module version to 2.5, and Configuration template to CFX Web Services Project v2.5. And click Modify (If you haven't already)






Make sure you already download Apache CXF and extract it in your favorite folder. Manage your Apache CXF Configuration, and locate it to your Apache CXF location.


Click Configure installed runtime.. And click Add. Browse to your copy of Apache CXF runtime.



Click OK and Finish.



  
Project structure generated by Eclipse.



Now, Lets start by modifying the web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
          <display-name>HrmsWS</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:com/company/hr/service/cxf.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
 Then we create our employee object, Employee.java, in package com.company.hr.bean
package com.company.hr.bean;

import java.io.Serializable;
import java.util.Set;

public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String gid;
private String lastName;
private String firstName;
private Set<String> privileges;
public Employee() {}
public Set<String> getPrivileges() {
return privileges;
}
public void setPrivileges(Set<String> privileges) {
this.privileges = privileges;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getGid() {
return gid;
}
public void setGid(String gid) {
this.gid = gid;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public boolean isUserInRole(String role) {
if(privileges == null) { return false; }
else { return privileges.contains(role); }
}
}
Lets assume we have a Data Access Object, EmployeeDAO.java, we can always replace this with an actual access to database. Put this in package com.company.hr.dao.
package com.company.hr.dao;

import com.company.hr.bean.Employee;

public class EmployeeDAO
{
public EmployeeDAO() {
// TODO Auto-generated constructor stub
}
public Employee getEmployee(String gid)
{
Employee bleh = new Employee(); // from database or SAP
bleh.setFirstName("Panji");
bleh.setLastName("Pratomo");
return bleh;
}
}

Next we create an interface that will be accessed by the SOAP Web services, HrmsService.java. Lets put it in com.company.hr.service. The @WebService is a declaration to be used by SOAP WSDL, the @WebParam will maintain the parameter name in WSDL the same as the parameter name in java interface.

package com.company.hr.service;

import java.util.List;
import javax.jws.WebService;
import javax.jws.WebParam;
import com.company.hr.bean.Employee;

@WebService
public interface HrmsService {
Employee getEmployee(@WebParam(name="gid") String gid);
List<Employee> getAllEmployee(@WebParam(name="status") String status);
}

Then we need a class for implementing the interface above, HrmsServiceImpl.java, lets put it in the same package as HrmsService,  com.company.hr.service.
The @WebService require the definition of an EndPointInterface and ServiceName. This will define the WSDL contract for our purposes.

package com.company.hr.service;

import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
import com.company.hr.bean.Employee;
import com.company.hr.dao.EmployeeDAO;

@WebService(endpointInterface = "com.company.hr.service.HrmsService", serviceName = "hrmsService")
public class HrmsServiceImpl implements HrmsService {
public Employee getEmployee(String gid) {
EmployeeDAO dao = new EmployeeDAO();
return dao.getEmployee(gid);
}

public List<Employee> getAllEmployee(String status) {
List<Employee> employees = new ArrayList<Employee>();
Employee emp1 = new Employee();
emp1.setFirstName("Panji");
emp1.setLastName("Pratomo");
Employee emp2 = new Employee();
emp2.setFirstName("Fahmi");
emp2.setLastName("Satrio");
Employee emp3 = new Employee();
emp3.setFirstName("Said");
emp3.setLastName("Hafiz");
employees.add(emp1);
employees.add(emp2);
employees.add(emp3);
return employees;
}
}

Next, we will need to manage our CXF configuration, cxf.xml, lets put this configuration file in the same package as HrmsService, com.company.hr.service.
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
xmlns:jaxws="http://cxf.apache.org/jaxws" 
xmlns:clustering="http://cxf.apache.org/clustering"  
xmlns:cxf="http://cxf.apache.org/core"  
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/clustering http://cxf.apache.org/schemas/clustering.xsd
http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
<!-- 
xmlns:util="http://www.springframework.org/schema/util"
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd 
-->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint id="authEnd"
implementor="com.company.hr.service.HrmsServiceImpl" 
address="/hrmsService" >
</jaxws:endpoint>
<!-- ONLY USE THIS IN DEVELOPMENT -->
<bean id="abstractLoggingInterceptor" abstract="true">
   <property name="prettyLogging" value="true"/>
</bean>
<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" parent="abstractLoggingInterceptor"/>
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" parent="abstractLoggingInterceptor"/>
 
<cxf:bus>
   <cxf:inInterceptors>
       <ref bean="loggingInInterceptor"/>
   </cxf:inInterceptors>
   <cxf:outInterceptors>
       <ref bean="loggingOutInterceptor"/>
   </cxf:outInterceptors>
   <cxf:outFaultInterceptors>
       <ref bean="loggingOutInterceptor"/>
   </cxf:outFaultInterceptors>
   <cxf:inFaultInterceptors>
       <ref bean="loggingInInterceptor"/>
   </cxf:inFaultInterceptors>
</cxf:bus>
<!-- ONLY USE THIS IN DEVELOPMENT -->
</beans>

The structure of the project would look like this,



Thats it, now we are ready to try our web service. Type the URL :
http://localhost:8080/Hrms/services/hrmsService?WSDL

The Hrms is the name of your project (If you have different project name, change accordingly), the /services/ comes from servlet settings in your web.xml, the hrmsService is your WSDL contract that you define previously in interface HrmsService.


Congratulations, you have created a SOAP Web service using Apache Cxf.

Next time, once I got the time, I will try to cover all about Enterprise Service Bus from one of Open Source products.

Why open source?

Because I dont have time to install WebSphere or Oracle SOA Suite.

No comments:

Post a Comment