Developing web services, Part 3: File uploading web service built with Apache CFX

This tutorial demonstrates how to develop a CXF web service which can upload a submitted file from the user and store it in a specific directory. The example is built with widely used Eclipse IDE.

Share:

Kuntal Ganguly, Jr. Developer, Protech Infosystems Pvt. Ltd

Kuntal GangulyCurrently associated as a Junior Developer at Protech Infosystems Pvt. Ltd, Kolkata. Kuntal has expertise in using a wide range of open source and commercial tools (WAS CE, Eclipse, Mule ESB, EZlegacy , Active MQ , Birt , and DB2 express C) and technologies(GWT and Android).



Partha Goswami, Jr. Developer, Protech Infosystems Pvt. Ltd

Partha GoswamiB.Tech with more than 13 months experience in developing J2EE, Web Service (JAX-WS), J2ME and Android application.Currently associated with Protech Infosystems, Kolkata as Junior Consultant.Has expertise in using a wide range of open source and commercial tools (WASCE, Eclipse, Oracle SOA Suite11g, EZlegacy , BIRT and DB2 express C) . Apart from his passion for Latest Technology, he has numerous other interests including Cricket and Tabla.



17 June 2011

Also available in Chinese Japanese

Before you start

Binary data with SOAP messages is send in Base64 format because SAOP messages are based on plain text, so when binary data is converted into Base64 than its size is increased. And, in case of large attachment this kills the application and brings down the server with memory problems. MTOM (SOAP Message Transmission Optimization Mechanism) which encodes binary data in base64Binary and sends the data as binary attachment rather than keeping it with actual SOAP message MTOM provides an elegant mechanism to transfer binary data such as PDF, Doc, images, and other document types. MTOM uses XML-binary Optimized Packaging (XOP) packages for transmitting binary data. CXF provides support of MTOM with XOP implementation.

This tutorial, the last of a three-part series, explains how to develop a File uploading web service using Apache CXF.

About this series

This tutorial series teaches the basic concepts of web services using different SOAP engines like Apache AXIS2, Apache CXF and JAX-WS. This tutorial series also provides a solution for sending large attachment with SOAP messages by using MTOM (SOAP Message Transmission Optimization Mechanism) which encodes binary data in base64Binary and sends the data as binary attachment rather than keeping it with actual SOAP message. This series also shows that by simply making method calls using the SAAJ API, you can read and write SOAP-based XML messages, and you can optionally send and receive such messages over the Internet.

Part 1 starts simply, explaining the basic concepts behind web services and showing you how to develop web service with Axis2 using Different Approach (Code First and Contract First).

Part 2 starts simply by developing a Hello User web Service with JAX-WS and then takes things a step further by showing an example of File Download web service(where client can download file from web service and store in its location)using MTOM with JAX-WS. It also shows how to invoke web service from SAAJ Client.

Part 3 simply shows how to develop a File uploading web service(where client can Upload file/attachment to Web service) using Apache CXF supports for MTOM with XOP implementation.

About this tutorial

This tutorial demonstrates how to develop web service that can upload a file from client machine to the server. The client application submits a file location and invokes the web service which receives the file byte by byte and stores in a fixed specified location.

Objectives

In this tutorial, you will learn how to:

  • Build a web service using CXF and deploy it in the tomcat server.
  • Learn how to send large binary attachments using the MTOM standard.

Prerequisites

This tutorial assumes familiarity with some basic concepts of the Eclipse IDE, including views, editors, panels, and so on, along with basic programming concept in Java™ and web services. For an introduction to Eclipse, Java and Web Services, view the Resources.

Software required

  • CXF-bin
  • Tomcat
  • Eclipse(optional)

Introduction

What is a web service?

A web service is a network accessible interface to application functionality, built using standard Internet technologies.

The fundamental concept behind web services is the SOA (service-oriented architecture), where an application is no longer a large monolithic program, but is divided into smaller, loosely coupled programs, and provided services are loosely coupled together with standardized and well-defined interfaces. These loosely coupled programs make the architecture very extensible, as it acquires the ability to add or remove services with limited costs. Therefore, new services can be created by combining and reusing existing services.

Because of the abstraction provided by the standards-based interfaces, it does not matter whether the application services are written in Java and the browser written in C++, or the application services deployed on a UNIX box while the browser is deployed on Windows. Web services allow for cross-platform interoperability in a way that makes the platform irrelevant. Interoperability is one of the key benefits gained from implementing web services. See the basic web service architecture shown in figure A.

Figure 1. The web service architecture
The web service architecture

In the web services architecture, the service provider publishes a description of the service(s) it offers via the service registry. The service consumer searches the service registry to find a service that meets their needs. The service consumer could be a person or a program.

The service provider offers business processes in the form of services. The services offered by the provider are called by the consumer to achieve certain sets of business goals. The process of services being provided and consumed is achieved by using directory services that lie between the provider and the consumer, in the form of broker. The service to be made available to the consumer is published to the directory services in the broker. The consumer wanting to achieve the set of business goal(s) will discover the service from the broker. If the service is found, it will bind to the service and execute the processing logic.

What is CXF?

Apache CXF is an open source framework that provides a robust infrastructure for conveniently building and developing web services. It lets you create high-performance and extensible services, which you can deploy in the Tomcat and Spring-based lightweight containers as well as on a more advanced server infrastructure, such as JBoss, IBM® WebSphere®, or Oracle WebLogic.

CXF provides you with many options to build services. CXF support all three major types of services:

  • SOAP - this page summarizes the options for creating SOAP services.
  • REST-ful - REST support
  • CORBA

Configuration and development

This example will show how to configure and develop a CXF based webservice running on a server that would perform uploading of files submitted by the client. See below the following specifications.

Tomcat web server 5.5 or above: The Tomcat servlet engine is an open-source package developed as part of the Apache Software Foundation's Jakarta project. It is the official reference implementation for both the servlet and JSP specifications. Tomcat can act as a stand-alone Web server and also as a servlet/JSP engine. We can download the latest release of Tomcat from http://tomcat.apache.org/download-60.cgi.

Apache-cxf-2.3. or above: Apache CXF is an open source services framework. CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI.You can download the lates version from http://cxf.apache.org/download.html.

Eclipse IDE: An integrated development environment (IDE) is an all-in-one tool for writing, editing, compiling, and running computer programs. And Eclipse provides an excellent integrated development environment. You can find the latest release of eclipse in www.eclipse.org.

Set up the Environment

  1. Install Jdk 1.5 or above in your system.
  2. After downloading apache-cxf distribution set the CXF_HOME environment variable.
  3. Download latest version of Tomcat and set the TOMCAT_HOME environment variable.

Create web service

  1. Start Eclipse in JavaEE perspective and select File > New > Other > Dynamic web Project named 'CxfService'.
  2. Expand the CxfService Project tab, select Java Resource: src and create a package 'com.ibm.uploadbean'.
  3. The package 'com.ibm.uploadbean' will contain a simple java bean class which will get and set the name of the file, the type of the file and the DataHandler type. The bean will be passed as a parameter to invoke this service. So create a class under that package and name it as 'FileUploader'. The code listing for this class is given below in Listing 1 and figure 2.
Figure 2. File Uploader bean class
File Uploader bean class
Listing 1. FileUploader.java
package com.ibm.uploadbean;

       import javax.activation.DataHandler;

public class FileUploader
{
  private String Name;
  private String FileType;
  private DataHandler Dfile;

  public String getName()
  {
    return this.Name;
  }

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

  public DataHandler getDfile()
  {
    return this.Dfile;
  }

  public void setDfile(DataHandler Dfile)
  {
    this.Dfile = Dfile;
  }

public String getFileType() {
    return FileType;
}

public void setFileType(String FileType) {
    this.FileType = FileType;
}
}
  1. Every web service requires a Service Endpoint Interface (SEI), through which the client can invoke the implementation class. Now select Java Resource: src and create another package named 'com.ibm.uploadservice'.
  2. Create an interface named 'UploadSEI' containing a method named 'uploadFile' as shown in the listing 2 and figure 3.
Figure 3. UploadSEI - Service Endpoint Interface
UploadSEI--Service Endpoint Interface
Listing 2. UploadSEI.java
package com.ibm.uploadservice;

import javax.jws.WebParam;
import javax.jws.WebService;
import com.ibm.uploadbean.FileUploader;

	
	@WebService
	public interface UploadSEI {
	    
	    void uploadFile(@WebParam(name="Dfile") FileUploader Dfile);
	}
  1. Create a service implementation class named 'UploadServiceImpl' implementing the interface inside the same package 'com.ibm.uploadservice'. This class defines the implementation method uploadFile which uses the FileUploader bean as its parameter. See the figure 4 below and the listing 3.
Figure 4. Upload Service Implementation
Upload Service Implementation
Listing 3. UploadServiceImpl.java
package com.ibm.uploadservice;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.activation.DataHandler;
import javax.jws.WebService;

import com.ibm.uploadbean.FileUploader;

@WebService(endpointInterface = "com.ibm.uploadservice.UploadSEI",
		serviceName = "UploadService")


public class UploadServiceImpl implements UploadSEI{
	
	public void uploadFile(FileUploader Dfile) {

		DataHandler handler = Dfile.getDfile();
		try {
		    InputStream is = handler.getInputStream();

		    OutputStream os = new FileOutputStream(new File("E:/uploads/"
			    + Dfile.getName() +"."+ 
			    Dfile.getFileType()));
		    byte[] b = new byte[100000];
		    int bytesRead = 0;
		    while ((bytesRead = is.read(b)) != -1) {
			os.write(b, 0, bytesRead);
		    }
		    os.flush();
		    os.close();
		    is.close();

		} catch (IOException e) {
		    e.printStackTrace();
		}

	    }
	  }
  1. The "OutputStream" will save the file in desired location as provided.
  2. Next is to create a configuration file 'cxf.xml' that would create a JAX-WS endpoint based on our implementation class 'UploadServiceImpl'. Make sure that the file is in the root 'src' folder, otherwise edit the web.xml according to your path of the file. See figure 5 and listing 4.
Figure 5. CXF configuration file
CXF configuration file
Listing 4. cxf.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:jaxws="http://cxf.apache.org/jaxws"
      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">

  <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="uploadfile"
                  implementor="com.ibm.uploadservice.UploadServiceImpl"
                  address="/UploadWS">
                  <jaxws:properties>
      <entry key="mtom-enabled" value="true"/>
    </jaxws:properties>	
    </jaxws:endpoint>
</beans>
  1. Edit the 'web.xml' file in the WEB-INF folder. See listing 5.
Listing 5. web.xml
<?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>CxfService</display-name>
   <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath: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>/*</url-pattern>
  </servlet-mapping>  
</web-app>
  1. Create a folder named 'lib' under WebContent > WEB-INF (see figure 5) and include the following .jar files in the lib folder. You can find all these jars in the CXF distribution library which you have already downloaded.

aopalliance-1.0.jar
asm-2.2.3.jar
commons-lang-2.4.jar
commons-logging-1.1.jar
cxf-api-2.1.5.jar
cxf-common-schemas-2.1.5.jar
cxf-common-utilities-2.1.5.jar
cxf-rt-bindings-soap-2.1.5.jar
cxf-rt-bindings-xml-2.1.5.jar
cxf-rt-core-2.1.5.jar
cxf-rt-databinding-jaxb-2.1.5.jar
cxf-rt-frontend-jaxws-2.1.5.jar
cxf-rt-frontend-simple-2.1.5.jar
cxf-rt-transports-http-2.1.5.jar
cxf-rt-ws-addr-2.1.5.jar
cxf-tools-common-2.1.5.jar
FastInfoset-1.2.2.jar
geronimo-activation_1.1_spec-1.0.2.jar
geronimo-annotation_1.0_spec-1.1.1.jar
geronimo-javamail_1.4_spec-1.3.jar
geronimo-jaxws_2.1_spec-1.0.jar
geronimo-stax-api_1.0_spec-1.0.1.jar
geronimo-ws-metadata_2.0_spec-1.1.2.jar
jaxb-api-2.1.jar
jaxb-impl-2.1.9.jar
neethi-2.0.4.jar
saaj-api-1.3.jar
saaj-impl-1.3.2.jar
spring-beans-2.0.8.jar
spring-context-2.0.8.jar
spring-core-2.0.8.jar
spring-web-2.0.8.jar
wsdl4j-1.6.2.jar
wstx-asl-3.2.6.jar
xml-resolver-1.2.jar
XmlSchema-1.4.5.jar

Your errors will now disappear. Check in the below figure 6.

Figure 6. CXF configuration file
CXF configuration file
  1. Right click the project select Export > WAR file (see figure 7). Copy the WAR file and paste it in the webapps directory under Tomcat_Home. Start the Tomcat server.
Figure 7. WAR creation
WAR creation
  1. On starting the tomcat server the Web service gets deployed in it. Go to the Tomcat Manager, enter username, password and log into it. You will find the deployed service named 'CxfService', click onto it and you will find the available service with its WSDL location. Click on the location hyperlink to see the WSDL. See figure 8.
Figure 8. Tomcat Console
Tomcat Console

Service Endpoint - http://localhost:8080/CxfService/UploadWS
WSDL location - http://localhost:8080/CxfService/UploadWS?wsdl

Generate the Stubs

In order to invoke the service the client must know the Service Endpoint Interface and the bean file which is to be invoked as a parameter. In order to get the things the client can create stubs from the WSDL of the service.

CXF distribution provides a tool called 'wsdl2java.bat' which can create the stubs for a particular service when provided the WSDL location with some additional parameters.

Go to the bin directory of $(CXF_HOME) from the command prompt and type the following command.

wsdl2java –client –verbose http://localhost:8080/CxfService/UploadWS?wsdl

This is going to run the wsdl2java.bat file present in the bin directory. The '-client' option generates starting point code for a client mainline. The '–verbose' option displays comments during the code generation process. See figure 9.

On successful execution of the command you will find the stubs created under the package 'com.ibm.uploadservice' in the $(CXF_HOME)/bin directory.

Figure 9. Stub Generation Command
Stub Generation Command

Create The Client

Now we are going to create the client project so that the web service can be consumed. In this example the client is a POJO client, you can also make a web client which would require a web container to run. Follow the below steps to develop a client.

  1. In Eclipse select File > New > Other > Dynamic web project and create a new project named 'CxfClient'.
  2. Create a package named 'com.ibm.uploadservice' (as in the stubs) and copy-paste all the generated stubs in it.
  3. Create another package named 'com.ibm.client'. Create a new class named 'Client' in the package. This class is going to invoke the developed service through the generated stubs. This class will contain the main() method so execution will start from here. See the code listing 6 for this class.
Figure 10. Client invoking service java class
Client invoking service java class
Listing 6. Client.java
package com.ibm.client;
import java.io.File;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

import com.ibm.uploadservice.*;


public final class Client {

  

    public static void main(String args[]) throws Exception {

    	JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();

    	factory.getInInterceptors().add(new LoggingInInterceptor());
    	factory.getOutInterceptors().add(new LoggingOutInterceptor());
    	factory.setServiceClass(UploadSEI.class);
    	factory.setAddress
    	("http://localhost:8080/CxfService/UploadWS");
    	UploadSEI client =(UploadSEI) factory.create();

    	FileUploader file=new FileUploader();
    	    	
    	file.setName("Partha");
    	file.setFileType("doc");
    	
    	DataSource source = new FileDataSource(new File("D:/my_upload_doc.doc"));
    	file.setDfile(new DataHandler(source));
    	client.uploadFile(file);
    	System.exit(0);

       }
    }
  1. Do not forget to include the previously mentioned .jar files in the WebContent > WEB-INF > lib.
  2. The 'DataSource' object source will contain the desired location of your uploading file. Here it is 'D:/my_upload_doc.doc' change it according to your file.
  3. The setName("Partha") will be the saving name of the uploaded file. Set the file type accordingly by modifying the setFileType("doc") parameter.
  4. You still might get a type mis-match error in 'file.setDfile', this might be because the generated stub 'FileUploade.java' has been having a 'byte[]' variable instead of having a 'DataHandler' variable .Change the byte[] to DataHander to resolve this problem. You should also import 'javax.activation.DataHandler' in it. In any inconvenience refer to the bean class used during the service creation in Listing 1.
  5. To run the client right-click on the Client.java file and select Run as > Java Application. If everything is perfect then you will find your file in saved by the given name in the location specified in the service.

Conclusion and Resource

In today's world, where interoperability between systems is so important, web services can be the foundation of your service-oriented architecture. These web service engines give application developers a powerful set of tools to integrate the applications of an enterprise business and to build the newest breed of applications that span multiple enterprises.


Download

DescriptionNameSize
Sample code for this tutorialcode.zip10KB

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into SOA and web services on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=SOA and web services
ArticleID=680526
ArticleTitle=Developing web services, Part 3: File uploading web service built with Apache CFX
publish-date=06172011