Search code examples
javajersey

Designing API to start and stop a process with Jersey


I am developing a REST web server with Java and Jersey. This is my first web application and I want to be sure that I am structuring the application well. I created my first function which is working well:

@Path("/startAuto") 
public class Rest {

    @GET
    public String startAuto() {
        try {
            ProcessBuilder pb = new ProcessBuilder("/startAuto.sh");
            Process p = pb.start();     
            p.waitFor();                
            return ("Auto Started");
        } catch (Exception e) {
            e.printStackTrace();
            return ("error");
        }
    }
}

I want to add a new function like stopAuto.

Which is cleaner: adding the function in this class or create a new class?


Solution

  • Approach 1

    The GET method should be used for retrieving information. Don't use GET to change a state of a resource. Prefer POST instead.

    So, you'll have something as following:

    • Start the process:
    POST /auto/start HTTP/1.1
    Host: example.org
    
    • Stop the process:
    POST /auto/stop HTTP/1.1
    Host: example.org
    

    With this approach, you will have the following in your resource class:

    @Path("/auto")
    public class Rest {
    
        @POST
        @Path("/start")
        public String start() {
            ...
        }
    
        @POST
        @Path("/stop")
        public String stop() {
            ...
        }
    }
    

    Approach 2

    REST is protocol independent and is a resource-oriented architecture. When implementing REST applications over the HTTP protocol, for example, the resource is identified by the URI and the operation over the resource is expressed by the HTTP method.

    With this approach, the new state of the resource will be expressed in the request payload using JSON, for example. To obtain the state of a resource, use GET and to replace the state of a resource, use PUT.

    You could have the following:

    • Start the process:
    PUT /auto/status HTTP/1.1
    Host: example.org
    Content-Type: application/json
    
    {
       "value" : "started"
    }
    
    • Stop the process:
    PUT /auto/status HTTP/1.1
    Host: example.org
    Content-Type: application/json
    
    {
       "value" : "stopped"
    }
    
    • Get the status of the process:
    GET /auto/status HTTP/1.1
    Host: example.org
    

    Your resource class will be like:

    @Path("/auto/status")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public class Rest {
    
        @PUT
        public String changeStatus(Status status) {
            ...
        }
        
        @GET
        public Status getStatus() {
            ...
        }
    }
    

    And that's what the Status class will look like:

    public class Status {
    
        private String value;
        
        // Default constructor, getters and setters omitted
    }
    

    Response status codes

    You certainly will need to inform your client about the result of the operation. To do it, use the HTTP response status codes.

    A few status that might be useful:

    • 200: Use this status to indicate that the request has succeeded.
    • 202: Use this status code to indicate the request has been accepted for processing, but the processing has not been completed.
    • 204: Use this status code to indicate the server has successfully fulfilled the request and that there is no additional content to send in the response payload body.
    • 409: Use this indicates that the request could not be completed due to a conflict with the current state of the target resource.