REST based File upload using Apache CXF and Spring

You can find the introductions about RESTFUL services here

Apache CXF is an open source implementation of JAX-WS and JAX-RS.

It originated as the combination of two open-source projects: Celtix developed by IONA Technologies (acquired by Progress Software in 2008) and XFire developed by a team hosted at Codehaus. These two projects were combined by people working together at the Apache Software Foundation. The name CXF derives from combining the “Celtix” and “XFire” project names.

Step 1:
Maven dependency for Apache CXF

          <properties>
          <cxf.version>2.5.0</cxf.version>
          </properties>
           <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxf.version}</version>
        </dependency>

        <dependency>
          <groupId>org.apache.cxf</groupId>
          <artifactId>cxf-rt-frontend-jaxrs</artifactId>
          <version>${cxf.version}</version>
       </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>

Step 2:
Add spring dependency

         <spring.version>3.0.5.RELEASE</spring.version>
         <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

Step 3:
web.xml configuration of both spring and Apache CXF

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/beans.xml</param-value>
    </context-param>
    <listener>
	<listener-class>
                        org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>
    <servlet>
		<servlet-name>CXFServlet</servlet-name>
		<display-name>CXF Servlet</display-name>
		<servlet-class>
			org.apache.cxf.transport.servlet.CXFServlet
		</servlet-class>
		<load-on-startup>2</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/rest/*</url-pattern>
	</servlet-mapping>

Note:
With this configuration Apache CXF will take over all the URL which starts like //rest

Step 4:
create the REST service to handle upload

import org.apache.cxf.jaxrs.ext.multipart.Attachment;
import javax.activation.DataHandler;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.io.*;
import java.util.List;


/**
 *  File upload service to upload files using RESTFUL services. 
 *  Author: Ananth Durai
 */

public class FileUploadService {

    @POST
    @Path("/file")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFile(List<Attachment> attachments,@Context HttpServletRequest request) {
        for(Attachment attr : attachments) {
            DataHandler handler = attr.getDataHandler();
            try {
                InputStream stream = handler.getInputStream();
                MultivaluedMap map = attr.getHeaders();
                OutputStream out = new FileOutputStream(new File(getFileName(map)));

                int read = 0;
                byte[] bytes = new byte[1024];
                while ((read = stream.read(bytes)) != -1) {
                    out.write(bytes, 0, read);
                }
                stream.close();
                out.flush();
                out.close();
            } catch(Exception e) {
              e.printStackTrace();
            }
        }

        return Response.ok("file uploaded").build();
    }

    private String getFileName(MultivaluedMap<String, String> header) {

        String[] contentDisposition = header.getFirst("Content-Disposition").split(";");

        for (String filename : contentDisposition) {
            if ((filename.trim().startsWith("filename"))) {

                String[] name = filename.split("=");

                String finalFileName = name[1].trim().replaceAll("\"", "");
                return finalFileName;
            }
        }
        return "unknown";
    }

}

Step 5:
Registering services as spring bean on beans.xml

 <bean id="uploadserviceclass" class="FileUploadService" />
 <jaxrs:server id="uploadservice" address="/upload">
        <jaxrs:serviceBeans>
            <ref bean="uploadserviceclass" />
        </jaxrs:serviceBeans>
  </jaxrs:server> 

Step 6:
Test jsp client to test the application

<html>
<body>
	<h1>JAX-RS Upload Form</h1>

	<form action="http://<server>/<contextpath>/rest/upload/file" method="post" enctype="multipart/form-data">

	   <p>
		Select a file : <input type="file" name="uploadedFile" size="50" />
	   </p>
	   <p>
	   The Next file : <input type="file" name="uploadedFile2" size="50" />
	   </p>

	   <input type="submit" value="Upload It" />
	</form>

</body>
</html>