Tutorial

Spring Restful Web Services Example with JSON, Jackson and Client Program

Published on August 3, 2022
author

Pankaj

Spring Restful Web Services Example with JSON, Jackson and Client Program

Spring is one of the most widely used Java EE frameworks. We have earlier seen how to use Spring MVC to create Java-based web applications. Today we will learn to create Spring Restful Web Services using Spring MVC and then test it out with the Rest client. In the end, we will also look into how to invoke Spring Restful web service using Spring RestTemplate API. spring rest, spring restful web services

Spring REST

We will use Spring latest version 4.0.0.RELEASE and utilize Spring Jackson JSON integration to send JSON response in the rest call response. The tutorial is developed in Spring STS IDE for creating Spring MVC skeleton code easily and then extended to implement Restful architecture. Create a new Spring MVC Project in the STS, our final project will look like the below image. We will look into each of the components one by one. Spring-Rest-Example-Project

Spring REST Configuration XML Files

Our pom.xml file looks like below.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>SpringRestExample</artifactId>
	<name>SpringRestExample</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>4.0.0.RELEASE</org.springframework-version>
		<org.aspectj-version>1.7.4</org.aspectj-version>
		<org.slf4j-version>1.7.5</org.slf4j-version>
		<jackson.databind-version>2.2.3</jackson.databind-version>
	</properties>
	<dependencies>
		<!-- Jackson -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${jackson.databind-version}</version>
		</dependency>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>

		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>

		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-eclipse-plugin</artifactId>
				<version>2.9</version>
				<configuration>
					<additionalProjectnatures>
						<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
					</additionalProjectnatures>
					<additionalBuildcommands>
						<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
					</additionalBuildcommands>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
					<compilerArgument>-Xlint:all</compilerArgument>
					<showWarnings>true</showWarnings>
					<showDeprecation>true</showDeprecation>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.2.1</version>
				<configuration>
					<mainClass>org.test.int1.Main</mainClass>
				</configuration>
			</plugin>
		</plugins>
		
	</build>
</project>

STS tool generates the pom.xml file for us. However, I have updated the Spring Framework, AspectJ, SLF4J and Jackson version to the latest one as of today. Most of the part is common and generated automatically, the important point to note is that I have added Jackson JSON libraries in the dependency because we will use that to convert Objects to JSON and vice versa.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="https://java.sun.com/xml/ns/javaee"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

This file is generated automatically and I haven’t changed anything in that. However, if you want to change context configuration files and their location, you can do it in the web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
		
</beans>

This file contains the shared resources that will be visible to all the web components, we will be developing a simple rest service and that’s why I haven’t changed anything here.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
	xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="https://www.springframework.org/schema/beans"
	xmlns:context="https://www.springframework.org/schema/context"
	xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<!-- Configure to plugin JSON as request and response in method handler -->
	<beans:bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<beans:property name="messageConverters">
			<beans:list>
				<beans:ref bean="jsonMessageConverter"/>
			</beans:list>
		</beans:property>
	</beans:bean>
	
	<!-- Configure bean to convert JSON to POJO and vice versa -->
	<beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
	</beans:bean>	
	
	<context:component-scan base-package="com.journaldev.spring.controller" />
	
</beans:beans>

Most of the part is auto generated and contains boiler-plate configurations. However important points to note are annotation-driven element to support annotations based configuration and plugging in MappingJackson2HttpMessageConverter to the RequestMappingHandlerAdapter messageConverters so that Jackson API kicks in and converts JSON to Java Beans and vice versa. By having this configuration, we will be using JSON in request body and we will receive JSON data in the response.

Spring REST Model Classes

Let’s write a simple POJO class that will serve as input and output to our Restful web service methods.

package com.journaldev.spring.model;

import java.io.Serializable;
import java.util.Date;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;

public class Employee implements Serializable{

	private static final long serialVersionUID = -7788619177798333712L;
	
	private int id;
	private String name;
	private Date createdDate;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	@JsonSerialize(using=DateSerializer.class)
	public Date getCreatedDate() {
		return createdDate;
	}
	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}
	
	
}

The only important point to note is the use of @JsonSerialize annotation to use DateSerializer class for Date conversion from Java type to JSON format and vice versa.

Spring Restful web service End Points

We will have the following rest web services endpoints.

Sl. No URI HTTP Method Details
1 /rest/emp/dummy GET Health Check service, to insert a dummy data in the Employees data storage
2 /rest/emp/{id} GET To get the Employee object based on the id
3 /rest/emps GET To get the list of all the Employees in the data store
4 /rest/emp/create POST To create the Employee object and store it
5 /rest/emp/delete/{id} PUT To delete the Employee object from the data storage based on the id

We have a class defining all these URI as String constants.

package com.journaldev.spring.controller;

public class EmpRestURIConstants {

	public static final String DUMMY_EMP = "/rest/emp/dummy";
	public static final String GET_EMP = "/rest/emp/{id}";
	public static final String GET_ALL_EMP = "/rest/emps";
	public static final String CREATE_EMP = "/rest/emp/create";
	public static final String DELETE_EMP = "/rest/emp/delete/{id}";
}

Spring Restful web service Controller class

Our EmployeeController class will publish all the web service endpoints mentioned above. Let’s look at the code of the class and then we will learn about each of the methods in detail.

package com.journaldev.spring.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.journaldev.spring.model.Employee;

/**
 * Handles requests for the Employee service.
 */
@Controller
public class EmployeeController {
	
	private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class);
	
	//Map to store employees, ideally we should use database
	Map<Integer, Employee> empData = new HashMap<Integer, Employee>();
	
	@RequestMapping(value = EmpRestURIConstants.DUMMY_EMP, method = RequestMethod.GET)
	public @ResponseBody Employee getDummyEmployee() {
		logger.info("Start getDummyEmployee");
		Employee emp = new Employee();
		emp.setId(9999);
		emp.setName("Dummy");
		emp.setCreatedDate(new Date());
		empData.put(9999, emp);
		return emp;
	}
	
	@RequestMapping(value = EmpRestURIConstants.GET_EMP, method = RequestMethod.GET)
	public @ResponseBody Employee getEmployee(@PathVariable("id") int empId) {
		logger.info("Start getEmployee. ID="+empId);
		
		return empData.get(empId);
	}
	
	@RequestMapping(value = EmpRestURIConstants.GET_ALL_EMP, method = RequestMethod.GET)
	public @ResponseBody List<Employee> getAllEmployees() {
		logger.info("Start getAllEmployees.");
		List<Employee> emps = new ArrayList<Employee>();
		Set<Integer> empIdKeys = empData.keySet();
		for(Integer i : empIdKeys){
			emps.add(empData.get(i));
		}
		return emps;
	}
	
	@RequestMapping(value = EmpRestURIConstants.CREATE_EMP, method = RequestMethod.POST)
	public @ResponseBody Employee createEmployee(@RequestBody Employee emp) {
		logger.info("Start createEmployee.");
		emp.setCreatedDate(new Date());
		empData.put(emp.getId(), emp);
		return emp;
	}
	
	@RequestMapping(value = EmpRestURIConstants.DELETE_EMP, method = RequestMethod.PUT)
	public @ResponseBody Employee deleteEmployee(@PathVariable("id") int empId) {
		logger.info("Start deleteEmployee.");
		Employee emp = empData.get(empId);
		empData.remove(empId);
		return emp;
	}
	
}

For simplicity, I am storing all the employee’s data in the HashMap empData. @RequestMapping annotation is used to map the request URI to the handler method. We can also specify the HTTP method that should be used by client application to invoke the rest method. @ResponseBody annotation is used to map the response object in the response body. Once the response object is returned by the handler method, MappingJackson2HttpMessageConverter kicks in and convert it to JSON response. @PathVariable annotation is the easy way to extract the data from the rest URI and map it to the method argument. @RequestBody annotation is used to map the request body JSON data into the Employee object, again this is done by the MappingJackson2HttpMessageConverter mapping. Rest of the code is simple and self-understood, our application is ready for deployment and testing. Just export as WAR file and copy it in the servlet container web app directory. If you have the server configured in the STS, you can simply run it on the server to get it deployed. I am using WizTools RestClient to invoke the rest calls but you can also use Chrome extension Postman. Below screenshots shows the different invocations of the rest APIs exposed by our application and it’s output. Health Check - Get Dummy Employee Rest Call Spring-Rest-Example-1 Create Employee POST Rest Call: Make sure request Content-Type is set to “application/json” otherwise you will get HTTP Error Code 415. Sping-Rest-Example-POST Get Employee Rest Call Spring-Rest-Example-GET-1 Delete Employee Rest Call Spring-Rest-Example-PUT Get All Employees Rest Call Spring-Rest-Example-GET

Spring Rest Client Program

Rest Clients are good to test our rest web service but most of the times, we need to invoke rest services through our program. We can use Spring RestTemplate to invoke these methods easily. Below is a simple program invoking our application rest methods using RestTemplate API.

package com.journaldev.spring;

import java.util.LinkedHashMap;
import java.util.List;

import org.springframework.web.client.RestTemplate;

import com.journaldev.spring.controller.EmpRestURIConstants;
import com.journaldev.spring.model.Employee;

public class TestSpringRestExample {

	public static final String SERVER_URI = "https://localhost:9090/SpringRestExample";
	
	public static void main(String args[]){
		
		testGetDummyEmployee();
		System.out.println("*****");
		testCreateEmployee();
		System.out.println("*****");
		testGetEmployee();
		System.out.println("*****");
		testGetAllEmployee();
	}

	private static void testGetAllEmployee() {
		RestTemplate restTemplate = new RestTemplate();
		//we can't get List<Employee> because JSON convertor doesn't know the type of
		//object in the list and hence convert it to default JSON object type LinkedHashMap
		List<LinkedHashMap> emps = restTemplate.getForObject(SERVER_URI+EmpRestURIConstants.GET_ALL_EMP, List.class);
		System.out.println(emps.size());
		for(LinkedHashMap map : emps){
			System.out.println("ID="+map.get("id")+",Name="+map.get("name")+",CreatedDate="+map.get("createdDate"));;
		}
	}

	private static void testCreateEmployee() {
		RestTemplate restTemplate = new RestTemplate();
		Employee emp = new Employee();
		emp.setId(1);emp.setName("Pankaj Kumar");
		Employee response = restTemplate.postForObject(SERVER_URI+EmpRestURIConstants.CREATE_EMP, emp, Employee.class);
		printEmpData(response);
	}

	private static void testGetEmployee() {
		RestTemplate restTemplate = new RestTemplate();
		Employee emp = restTemplate.getForObject(SERVER_URI+"/rest/emp/1", Employee.class);
		printEmpData(emp);
	}

	private static void testGetDummyEmployee() {
		RestTemplate restTemplate = new RestTemplate();
		Employee emp = restTemplate.getForObject(SERVER_URI+EmpRestURIConstants.DUMMY_EMP, Employee.class);
		printEmpData(emp);
	}
	
	public static void printEmpData(Employee emp){
		System.out.println("ID="+emp.getId()+",Name="+emp.getName()+",CreatedDate="+emp.getCreatedDate());
	}
}

Most of the program is simple to understand, however when invoking rest method returning a Collection, we need to use LinkedHashMap because JSON to object conversion doesn’t know about the Employee object and converts it to the collection of LinkedHashMap. We can write a utility method to convert from LinkedHashMap to our Java Bean object. When we run the above program, we get the following output in the console.

ID=9999,Name=Dummy,CreatedDate=Tue Mar 04 21:02:41 PST 2014
*****
ID=1,Name=Pankaj Kumar,CreatedDate=Tue Mar 04 21:02:41 PST 2014
*****
ID=1,Name=Pankaj Kumar,CreatedDate=Tue Mar 04 21:02:41 PST 2014
*****
2
ID=1,Name=Pankaj Kumar,CreatedDate=1393995761654
ID=9999,Name=Dummy,CreatedDate=1393995761381

Another point is that RestTemplate put methods doesn’t have option to set response object because PUT method should be used to store something on the server and a simple HTTP 200 status code should be sufficient.

Download Spring Restful Webservice Project

That’s all for the Spring Restful web application tutorial. Download the sample project from the above link and play around with it to learn more. UPDATE: Because of so many requests to provide similar example with XML as well as supporting both XML and JSON, I have extended this application in Spring REST XML JSON Example to support both XML and JSON requests and response. I strongly suggest you go through that to see the beauty of the spring framework and how easy it is to achieve this.

You can download complete project from our GitHub Repository.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Pankaj

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
March 7, 2014

Great work, very helpful.

- sreeni

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    March 23, 2014

    I cannot tell you how thankful I am for this. After banging my head against the wall for half the day you have given me the “magic” configuration that will correctly return json from my REST controllers. Thank you, thank you, thank you! Note to anyone using Spring 4 and getting a 406 HTTP response when trying to make a call to your controllers: just copy the spring-context.xml file on this page and be done with it.

    - Scott

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      April 1, 2014

      Thanks a lot boss, quick reference. Small doubt, in controller class, while creating employee you are purring created emp in to a map ( empData ) , but you are returning pojo class object ( emp ). Why so ? Any ways Thanks !

      - ashok

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        April 5, 2014

        I am trying to do an API that will receive a list of Customers for example an this list is processed by the service, but I have some questions: - If I receive the list of Customers inside the Body as @RequestBody then how should I process it. - My controller must process all in a once because we have to process all the customers or none. - I am trying to deserialize the Jason content to a lIst of customers, but after this I should process customer by customer invoking the service n times but my transactions are at service level not at controller level. . Could you please give me any idea about how to do it? I am doing my final degree work and I am really stuff by this. Many thanks, Ana

        - Ana

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          April 8, 2014

          Can we make this application to support any kind of format(json,xml, etc) to generate and also to receive …?

          - Narayana

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            May 6, 2014

            How did you come up with the name “spring Jackson” for your program?..spring Jackson, oregon

            - spring788@hotmail.com

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              May 7, 2014

              I want to expose rest service to receive byte array, so in my service i used @RequestBody final byte[] byteArray This is resulting me below exception org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of byte[] out of START_OBJECT token Could you please help me out in this.

              - Anil

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                May 13, 2014

                Sir at which you have used restful web services i mean how to know that this application using restful web service. ?? please make me clear… Thanks

                - Bhabadyuti

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  May 14, 2014

                  Perfect!, first example i see to extract the paths with enums, now take it to the next level and implement Hateoas? :)

                  - Mortier

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    May 16, 2014

                    You should really overthink your “RESTful” URL design in this example. RESTful URLs do not have any verbs in them, just nouns. So the right URLs for your example would be: GET /employees (get a list of all employees) POST /employees (create a new employee) GET /employees/id (get a specific employee from id) DELETE /employees/id (delete a specific employee from id) Although I appreciate your motiviation to provide examples for other people on the internet, you should ensure that you do not teach wrong things.

                    - Thomas

                      Try DigitalOcean for free

                      Click below to sign up and get $200 of credit to try our products over 60 days!

                      Sign up

                      Join the Tech Talk
                      Success! Thank you! Please check your email for further details.

                      Please complete your information!

                      Become a contributor for community

                      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                      DigitalOcean Documentation

                      Full documentation for every DigitalOcean product.

                      Resources for startups and SMBs

                      The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                      Get our newsletter

                      Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                      New accounts only. By submitting your email you agree to our Privacy Policy

                      The developer cloud

                      Scale up as you grow — whether you're running one virtual machine or ten thousand.

                      Get started for free

                      Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                      *This promotional offer applies to new accounts only.