Apache CXF: JAX-RS Restful web service for uploading/downloading Image file + Java client

In this article, we will learn and implement JAX-RS Restful web service which is exposed to upload/download image files such as .png, .jpeg, .gif, etc formats. In this example, we will just cover one format i.e.; .png file. Similarly, we can replace @Produces for .jpeg and .gif formats


  • Annotate download image method with @Produces(“image/png”) or @Produces(“image/jpeg”) or @Produces(“image/gif”) depending on the image format you would allow the user to download
  • Set “Content-Disposition” in the ResponseBuilder to allow downloading users to select path to download image[.png, .jpeg, .gif] file
  • Finally, build() the ResponseBuilder and return Response object with “download success” message


  • Annotate upload method with @Consumes(“multipart/form-data”)
  • Get the List<Attachment> and process the attachments to get headers and inputstreams
  • Finally, write the steams to the upload file server using basic file handling operations
  • Return “upload success” message within Response object

Annotation Used

  • @Path (javax.ws.rs.Path)
  • @GET (javax.ws.rs.GET)
  • @POST (javax.ws.rs.POST)
  • @Consumes (javax.ws.rs.Consumes)
  • @Produces (javax.ws.rs.Produces)
  • @Service (org.springframework.stereotype.Service)
  • MediaType (javax.ws.rs.core.MediaType)

Technology Used

  • Java 1.7
  • Eclipse Luna IDE
  • Spring-4.0.0-RELEASE
  • Apache-CXF-3.0.0
  • Apache Maven 3.2.1
  • Apache Tomcat 7.0.54

Mavenize or download required jars

Add Apache-CXF-3.0.0 & Spring-4.0.0-RELEASE dependencies to pom.xml

			<!-- Apache CXF -->

			<!-- Apache HTTP components for writing test client -->

			<!-- Spring framework -->

Folks who aren’t familiar with Maven concepts or don’t require maven for their project, can download the below jars individually from the spring site or maven repository and include them in the classpath

Directory Structure

Before moving on, let us understand the directory/package structure once you create project in Eclipse IDE
Maven has to follow certain directory structure

  • src/test/java –> test related files, mostly JUnit test cases
  • src/main/java –> create java source files under this folder
  • src/main/resources –> all configuration files placed here
  • Maven Dependencies or Referenced Libraries –> includes jars in the classpath
  • WEB-INF under webapp –> stores web.xml & other configuration files related to web application

Project Structure (Package Explorer view in Eclipse)


Jars Libraries Used in the Project (Maven Dependencies)


Web application

For any web application, entry point is web.xml which describes how the incoming http requests are served / processed. Further, it describes about the global-context and local-context param (i.e.; <context-param> & <init-param>) for loading files particular to project requirements & contains respective listener

With this introduction, we will understand how we configured web.xml for Apache CXF JAX-RS Restful web service for uploading/downloading files

web.xml (the entry point –> under WEB-INF)

This web.xml file describes,

  • Like any JEE web framework register org.apache.cxf.transport.servlet.CXFServlet with servlet container
  • All http requests with URL pattern “/services/*” will be sent to the registered servlet called “CXFServlet” (org.apache.cxf.transport.servlet.CXFServlet)
  • <context-param> with its attributes describes the location of the “apache-cxf-service.xml” file from where it has to be loaded. We will discuss briefly about these files
  • <welcome-file-list> files under this tag is the start-up page


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">


	<!-- Apache CXF -->

	<!-- web context param -->

	<!-- listener -->

	<!-- welcome file list -->

Apache CXF services

Apache CXF comes with spring based configuration, so it is easy to register beans in the spring container much like we do any bean in spring application. CXFServlet receives the incoming http requests and invokes corresponding registered beans in according to http url path

NOTE: For this Restful JAX-RS application, we are using Spring annotations to define/register beans in the spring container thereby avoiding lot of boilerplate code to write

This apache-cxf-services.xml describes,

  • <jaxrs:server /> defines which service bean to be invoked for the incoming http requests. In this case, any wild card pattern “/” will invoke “fileService” which is registered as service bean using @Service(“fileService”) annotation (on top of the FileServiceImpl java class)
  • <context:annotation-config /> to activate annotation on the registered beans with application context
  • <context:component-scan base-package=”” /> tag scans all classes & sub-classes under the value of base-package attribute and register them with the Spring container
  • NOTE: For two different beans we can have two different url-pattern(address) like
		<jaxrs:server id="restContainer" address="/">
				<ref bean="fileService" />
		<jaxrs:server id="twotest" address="/two">
				<ref bean="testService" />


<?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"
	xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">

	<!-- to turn on annotation wiring == turns on only the registered beans
		through ApplicationContext -->
	<context:annotation-config />

	<!-- scans and register beans using annotation-config (metadata) -->
	<context:component-scan base-package="com.apache.cxf.upload.download.service" />

	<!-- CXFServlet configured in web.xml sends requests here -->
	<jaxrs:server id="restContainer" address="/">
			<ref bean="fileService" />

Let’s see coding in action


URL Pattern

Http URL for any common web application is http://<server>:<port>/<context-root>/<from_here_application_specific_path>

In our example, we are going to deploy war into Tomcat 7.0 server so our server & port are localhost and 8080 respectively. Context root is the project name i.e.; ApacheCXF-UP-DOWN-Image-File. Initial path for this application is http://localhost:8080/ApacheCXF-UP-DOWN-Image-File

We have configured “/services/*” as url-pattern for the CXFServlet in web.xml and at interface-level (or say class-level) path configured is “/fileservice” using @Path annotation. Next, respective path for each method annotated with @Path (method-level)

File Service interface

File service exposes two public methods one for downloading image(.png) file and another for uploading file

Download image file method annotated with @Produces(“image/png”) and upload file method annotated with @Consumes(“multipart/form-data”)

NOTE: It’s always a good programming practice to do code-to-interface and have its implementation separately


package com.apache.cxf.upload.download.service;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.cxf.jaxrs.ext.multipart.Attachment;

public interface IFileService {

	// http://localhost:8080/ApacheCXF-UP-DOWN-Image-File/services/fileservice/download/image
	public Response downloadImageFile();

	// http://localhost:8080/ApacheCXF-UP-DOWN-Image-File/services/fileservice/upload/images
	public Response uploadImageFile(List<Attachment> attachments, @Context HttpServletRequest request);

File Service implementation

Implements above interface


It’s quite straightforward, constructing file object supplying path location for the .png file to be downloaded and setting this file object in ResponseBuilder and returning Response object


Iterate through each attachments extracting headers & inputstreams and writing to the UPLOAD_FILE_SERVER using simple file handling operations


package com.apache.cxf.upload.download.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import javax.activation.DataHandler;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import org.springframework.stereotype.Service;

public class FileServiceImpl implements IFileService {

	public static final String UPLOAD_FILE_SERVER = "D:\\Demo\\upload\\";

	public Response downloadImageFile() {

		File file = new File("D:/Demo/download/SampleImage.png");

		ResponseBuilder responseBuilder = Response.ok((Object) file);
		responseBuilder.header("Content-Disposition", "attachment; filename=\"MyImageFile.png\"");
		return responseBuilder.build();

	public Response uploadImageFile(List<Attachment> attachments, HttpServletRequest request) {

		// local variables
		DataHandler dataHandler = null;
		MultivaluedMap<String, String> multivaluedMap = null;
		String fileName = null;
		InputStream inputStream = null;

		for (Attachment attachment : attachments) {
			dataHandler = attachment.getDataHandler();
				// get filename to be uploaded
				multivaluedMap = attachment.getHeaders();
				fileName = getFileName(multivaluedMap);

				if(null != fileName && !"".equalsIgnoreCase(fileName)){
					// write & upload file to server
					inputStream = dataHandler.getInputStream();
					writeToFileServer(inputStream, fileName);

					// close the stream
			catch(IOException ioex) {
			finally {
				// release resources, if any
		return Response.ok("upload success").build();

	 * @param inputStream
	 * @param fileName
	 * @throws IOException
	private void writeToFileServer(InputStream inputStream, String fileName) throws IOException {

		OutputStream outputStream = null;
		try {
			outputStream = new FileOutputStream(new File(UPLOAD_FILE_SERVER + fileName));
			int read = 0;
			byte[] bytes = new byte[1024];
			while ((read = inputStream.read(bytes)) != -1) {
				outputStream.write(bytes, 0, read);
		catch (IOException ioe) {
			//release resource, if any

	 * @param multivaluedMap
	 * @return
	private String getFileName(MultivaluedMap<String, String> multivaluedMap) {

		String[] contentDisposition = multivaluedMap.getFirst("Content-Disposition").split(";");
		for (String filename : contentDisposition) {

			if ((filename.trim().startsWith("filename"))) {
				String[] name = filename.split("=");
				String exactFileName = name[1].trim().replaceAll("\"", "");
				return exactFileName;
		return "UnknownFile";

View Technologies

<table> element within <form> tag, on click of “Upload File” button invokes upload file service method which is configured in the action attribute. Maximum of three image files can be uploaded and this is supported in the implementation


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Apache CXF : File Upload</title>
		<b>Apache CXF : JAX-RS Restful web service Learning</b>
		<h4>Uploading files using JAX-RS Restful web service</h4>
			style="width: 400px; border: 1px solid blue; padding: 20px; text-align: center;">

			<form method="post" action="services/fileservice/upload/images"
				<table align="center" border="1" bordercolor="black" cellpadding="0"
						<td>Select File 1 :</td>
						<td><input type="file" name="uploadedFile1" size="100" /></td>
						<td>Select File 2 :</td>
						<td><input type="file" name="uploadedFile2" size="100" /></td>
						<td>Select File 3 :</td>
						<td><input type="file" name="uploadedFile3" size="100" /></td>
						<td><input type="submit" value="Upload File" /></td>
						<td><input type="reset" value="Reset" /></td>



  • Run maven command to build the war : mvn clean install (use command prompt or integrated maven in eclipse IDE
  • Copy war file from target folder
  • Paste it into apache tomcat (webapps folder)
  • Start the tomcat server

Test the service !!



There are many ways to do testing

  • JSP client
  • Copy URL of GET service into web browser
  • Advanced REST client from Google Chrome
  • Rest client from Mozilla Firefox Add On
  • Write your own client for example, Java client using improved CloseableHttpClient from Apache
  • JDK’s in-built classes like HttpURLConnection


1. JSP client


1.1 upload file using JSP client

Enter URL: http://localhost:8080/ApacheCXF-UP-DOWN-Image-File/uploadImageFile.html
And select image(.png) file using file chooser
Click “Upload File”


Result in web browser: upload success


1.2 download text file

Enter URL: http://localhost:8080/ApacheCXF-UP-DOWN-Image-File/services/fileservice/download/image into web browser
Allows downloading users to open/save image(.png) file


2. Java Client


2.1 Upload image file

Uses Apache’s improved CloseableHttpClient & MultipartEntityBuilder for invoking Restful web service to upload image(.png) file


package test.apache.cxf.rest.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

public class TestUploadFileService {

	public static void main(String []args) {

		String httpURL = "http://localhost:8080/ApacheCXF-UP-DOWN-Image-File/services/fileservice/upload/images";
		File filePath = new File("D:/Demo/download/SampleImage.png");
		String responseString = testUploadService(httpURL, filePath);
		System.out.println("responseString : " + responseString);

	public static String testUploadService(String uri, File filePath) {

		// local variables
		HttpPost httpPost = null;
		CloseableHttpClient closeableHttpClient = null;
		HttpResponse httpResponse = null;
		MultipartEntityBuilder multipartEntityBuilder = null;
		HttpEntity httpEntity = null;
		FileBody fileBody = null;
		InputStream inputStream = null;
		BufferedReader bufferedReader = null;
		StringBuilder stringBuilder = null;

		try {
			// http post request header
			httpPost = new HttpPost(uri);

			// constructs file to be uploaded
			fileBody = new FileBody(filePath);
			multipartEntityBuilder = MultipartEntityBuilder.create();
			multipartEntityBuilder.addPart("uploadfile", fileBody);
			httpEntity = multipartEntityBuilder.build();

			// actual execution of http post request
			closeableHttpClient = HttpClients.createDefault();
			httpResponse = closeableHttpClient.execute(httpPost);

			System.out.println("Response code/message: " + httpResponse.getStatusLine());
			httpEntity = httpResponse.getEntity();

			// get the response content
			inputStream = httpEntity.getContent();
			bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
			stringBuilder = new StringBuilder();
			String strReadLine = bufferedReader.readLine();

			// iterate to get the data and append in StringBuilder
			while (strReadLine != null) {
				strReadLine = bufferedReader.readLine();
				if (strReadLine != null) {
		catch (UnsupportedEncodingException usee) {
		catch (Exception ex) {
		finally {
			// shuts down, when work done
		return stringBuilder.toString();

Output in Console (upload .png file)

Response code/message: HTTP/1.1 200 OK
responseString : upload success

2.2 Download image file

Uses JDK’s in-built classes like HttpURLConnection to invoke Restful web service to download image(.png) file


package test.apache.cxf.rest.service;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.ws.rs.HttpMethod;

public class TestDownloadFileService {

	public static final String DOWNLOAD_FILE_LOCATION = "D:\\Demo\\test\\";

	public static void main(String []args) {

		String httpURL = "http://localhost:8080/ApacheCXF-UP-DOWN-Image-File/services/fileservice/download/image";
		String responseString = testDownloadService(httpURL);
		System.out.println("responseString : " + responseString);

	 * This method uses HttpURLConnection to invoke exposed Restful web service and returns the response string to the calling client
	 * @param requestParams
	 * @return
	public static String testDownloadService(String httpUrl) {

		// local variables
		URL url = null;
		HttpURLConnection httpURLConnection = null;
		String responseMessageFromServer = null;
		String responseString = null;
		InputStream inputStream = null;
		OutputStream outputStream = null;

		try {   

			// httpURLConnection
			url = new URL(httpUrl);
			httpURLConnection = (HttpURLConnection) url.openConnection();
			httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			httpURLConnection.setRequestProperty("Accept", "image/png");

			System.out.println("Response code: " + httpURLConnection.getResponseCode());
			if (httpURLConnection.getResponseCode() == 200) {

				responseMessageFromServer = httpURLConnection.getResponseMessage();
				System.out.println("ResponseMessageFromServer: " + responseMessageFromServer);

				inputStream = httpURLConnection.getInputStream();
				outputStream = new FileOutputStream(DOWNLOAD_FILE_LOCATION + "MyImageFile.png");
				byte[] buffer = new byte[1024];
				int bytesRead;
				while ((bytesRead = inputStream.read(buffer)) != -1) {
					outputStream.write(buffer, 0, bytesRead);
				responseString =  outputStream.toString();

				responseString = "download success";
			else {
				// do some actions
		catch(Exception  ex){
		return responseString;

Output in Console (download .png file)

Response code: 200
ResponseMessageFromServer: OK
responseString : download success

Conclusion: It’s quite easy to implement download/upload files functionality in JAX-RS Restful web service using simple annotations like @Produces & @Consumes on top of the service class to be exposed

In the next article, very similarly we will implement an example for uploading/downloading PDF files

Download project

ApacheCXF-Uploading-Downloading-Image-File (6kB)

Happy Coding !!
Happy Learning !!

Apache CXF: JAX-RS Restful web service for uploading/downloading PDF file + Java client
Apache CXF: JAX-RS Restful web service for uploading/downloading Text file + Java client