A REST web service, file uploads & Spring Boot

8ca7b37f78-arklein
In this article I will introduce a document archive application with a REST interface created with Spring Boot. You will find out how to handle file uploads by a REST web service. The web front end is created with AngularJS. The application is on GitHub. The impatient of you can follow this link to the repository: rest-document-archive to see the source code.

Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications. All configuration is done by annotations. You don’t need a single XML configuration file.


Build and run

To build an run the application open a terminal and type:

~$ git clone https://github.com/murygin/rest-document-archive.git
~$ cd rest-document-archive
~$ mvn package
~$ java -jar target/rest-document-archive-0.1.0.jar

You can now point a browser to http://localhost:8080/ to open the web front end.


REST API

  • Add a document/archive/upload?file={file}&person={person}&date={date} POST
    • file: A file posted in a multipart request
    • person: The name of the uploading person
    • date: The date of the document
  • Find documents/archive/documents?person={person}&date={date} GET
    • person: The name of the uploading person
    • date: The date of the document
  • Get a document/archive/document/{id} GET
    • id: The UUID of a document

Main classes

The document archive consists of a REST service controller, a service and a data access object. In addition there is Java client for the REST service and a web front end.

REST Service Controller

Executes incoming request and defines URL to service method mappings. All remote call are delegated to the archive service.

Service

A service to save, find and get documents from an archive.

Data access object

Data access object to insert, find and load documents. FileSystemDocumentDao saves documents in the file system. No database in involved. For each document a folder is created. The folder contains the document and a properties files with the meta data of the document. Each document in the archive has a Universally Unique Identifier (UUID). The name of the documents folder is the UUID of the document.

Client

A client for the document archive which is using the REST service.

Web client

A web client made with AngularJS.


Implementation details

Here are some implementation details:

Application class

Starting point to run and configure a Spring Boot application is an Application class in the root package of your application.

org.murygin.archive.Application:

@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Automatic Spring configuration is done by annotations @Configuration, @ComponentScan and @EnableAutoConfiguration. All classes in the same package or in any sub-packages are configured and added to Springs application context. The main() method uses Spring Boot’s SpringApplication.run() method to launch the application. No external application server is needed to run the web service. Spring boot starts an embedded servlet container.

REST Service Controller

The REST Service Controller ArchiveController.java handles incoming HTTP request and delegates execution to the Java service. The most interesting method is handleFileUpload because it receives the uploaded file. You don’t have to worry about how to convert a multipart file request param to a Java object. Spring does this job for you. All you have to do is defining a parameter of type org.springframework.web.multipart.MultipartFile and mapping it to the request by annotation org.springframework.web.bind.annotation.RequestParam (Line 3).

org.murygin.archive.rest.ArchiveController:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
  public @ResponseBody DocumentMetadata handleFileUpload(
         @RequestParam(value="file", required=true) MultipartFile file ,
         @RequestParam(value="person", required=true) String person,
         @RequestParam(value="date", required=true) @DateTimeFormat(pattern="yyyy-MM-dd") Date date) {
    try {
      Document document = new Document(file.getBytes(), file.getOriginalFilename(), date, person );
      getArchiveService().save(document);
      return document.getMetadata();
    } catch (Exception e) {
      // .. exception handling
    }
  }

In Line 5 you can see how to convert a String parameter to a Java date by defining a pattern with annotation org.springframework.format.annotation.DateTimeFormat.

File upload AngularJS

I will not describe how to handle a multipart/form-data file upload with AngularJS in this article. I recommend to read this article to learn more about it. You will find my implementation in the files: src/main/resources/static/app.js and index.html

Maven

The Spring Boot Maven plugin simplifies the Maven configuration by a built-in dependency resolver that sets the version number to match Spring Boot dependencies. That’s why Maven configuration is relatively simple in this project

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.murygin</groupId>
  <artifactId>rest-document-archive</artifactId>
  <version>0.1.0</version>

  <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>1.1.6.RELEASE</version>
  </parent>

  <properties>
      <start-class>org.murygin.archive.Application</start-class>
  </properties>

  <build>
      <plugins>
          <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>2.3.2</version>
          </plugin>
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
      </plugins>
  </build>

  <dependencies>
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
      </dependency>
      <dependency>
	  <groupId>org.springframework.boot</groupId>
	  <artifactId>spring-boot-starter-test</artifactId>
	  <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
  </dependencies>

  <repositories>
      <repository>
          <id>spring-releases</id>
          <name>Spring Releases</name>
          <url>http://repo.spring.io/libs-release</url>
      </repository>
  </repositories>
  <pluginRepositories>
      <pluginRepository>
          <id>spring-releases</id>
          <name>Spring Releases</name>
          <url>http://repo.spring.io/libs-release</url>
      </pluginRepository>
  </pluginRepositories>
</project>
    • hajar
    • 26. Mai 2015

    I wanted to try this code but when i type localhost:8080/index.html , i have the view and when i try to upload the file ,it’snot uploaded, i try to see what the problem using developpement tools of chrome it gives me this error :POST http://localhost:8080/archive/upload 400 (Bad Request). Can you help me please

  1. Do you see a stacktrace in your terminal?

    • hajar
    • 26. Mai 2015

    do you mean in the console noo there’s no error , just when i click on upload it gives me the error that i mentioned

    • hajar
    • 26. Mai 2015

    hajar :
    do you mean in the console ,yes there’s an error wich is request get not supported, and when i click on upload it gives me the error that i mentioned

    • pojg
    • 2. Juni 2016

    Very Helpful. Any steps to import the project into Eclipse and run the application on tomcat ?

  2. took me a while, but the 400 error is because the date format is required as YYYY-MM-DD

  1. No trackbacks yet.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: