CXF REST File Upload

CXF REST File Upload explains step by step details of Implementing a REST service for uploading attachment using Apache CXF, Spring and Eclipse
JAX-RS is Java API for RESTful Webservices which is very rely upon Representational State Transfer model, you can view JAX-RS specification
JAX-RS uses annotations for simplifying the development efforts.
Below you can see an example of How to upload an attachment using CXF JAX-RS(REST based) file upload
Required Libraries
You need to download
Following jar must be in classpath
- commons-logging-1.1.1.jar
- cxf-2.7.3.jar
- httpasyncclient-4.0-beta3.jar
- httpclient-4.2.1.jar
- httpcore-4.2.2.jar
- httpcore-nio-4.2.2.jar
- neethi-3.0.2.jar
- spring-aop-3.0.7.RELEASE.jar
- spring-asm-3.0.7.RELEASE.jar
- spring-beans-3.0.7.RELEASE.jar
- spring-context-3.0.7.RELEASE.jar
- spring-core-3.0.7.RELEASE.jar
- spring-expression-3.0.7.RELEASE.jar
- spring-web-3.0.7.RELEASE.jar
- wsdl4j-1.6.2.jar
- jaxb-api-2.2.6.jar
- jaxb-impl-2.2.6.jar
- javax.ws.rs-api-2.0-m10.jar
- xmlschema-core-2.0.3.jar
- jettison-1.3.3.jar (JSON library)
CXF REST File Upload
I am creating a simple restful service project that used to upload Multipart (MediaType.MULTIPART_FORM_DATA) attachment
Firstly create a Dynamic Web Project (File->New->Dynamic Web Project) named "CXFRestUpload" according to following screenshot
Create a Service Interface
Here we are implement the logic, this will defines which methods of restful service, to be invoked by the client
We are using annotations @Consumes(MediaType.MULTIPART_FORM_DATA) in order to upload the CXF Multipart file attachments
import java.io.File;
import java.io.FileOutputStream;
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.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 org.apache.cxf.jaxrs.ext.multipart.Attachment;
public class UploadServiceImpl {
@POST
@Path("/uploadFile")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(List<Attachment> attachments, @Context HttpServletRequest request) {
for (Attachment attachment : attachments) {
DataHandler handler = attachment.getDataHandler();
try {
InputStream stream = handler.getInputStream();
MultivaluedMap<String, String> map = attachment.getHeaders();
System.out.println("fileName Here" + getFileName(map));
OutputStream out = new FileOutputStream(new File("C:/uploads/" + 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 exactFileName = name[1].trim().replaceAll("\"", "");
return exactFileName;
}
}
return "unknown";
}
}
Here we are using one example showing with POST method
GET---> Calling this method will not result any changes to the server
POST---> Calling this method will result changes to the server, This have more secure than GET method
@Consumes annotation specifies, the request is coming from the client
you can specify the Mime type as @Consumes("application/xml"), if the request is in xml format
@Produces annotation specifies, the response is going to the client
you can specify the Mime type as @Produces ("application/xml"), if the response need to be in xml format
Create a cxf.xml
CXF is using Spring internally, Finding classes by spring we need to add service implementation beans are added on "jaxrs:serviceBeans".
<?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:jaxrs="http://cxf.apache.org/jaxrs" 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"> <import resource="classpath:META-INF/cxf/cxf.xml" /> <jaxrs:server id="base" address="/rest"> <jaxrs:serviceBeans> <ref bean="UploadService" /> </jaxrs:serviceBeans> </jaxrs:server> <bean id="UploadService" class="com.student.UploadServiceImpl" /> </beans>
Change web.xml
Change the web.xml file to find CXF servlet and cxf.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/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> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app>
Publishing CXF Restful Service
Deployed REST Web Service Using CXF