Design RESTful Services for Oracle JET: Part 2

by Kenneth Lange  

In the first post in this mini-series on RESTful services, we looked at the RESTful architecture from a very high-level. In this second post, we will dive in and design a simple RESTful service, which can be called almost effortlessly from Oracle JET!

The Demo RESTful Service

Let’s take the employees table from Oracle’s HR schema and use it as the foundation for a CRUD RESTful service:

SQL> DESC EMPLOYEES; 
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------
 EMPLOYEE_ID                               NOT NULL NUMBER(6)    
 FIRST_NAME                                         VARCHAR2(20)
 LAST_NAME                                 NOT NULL VARCHAR2(25)  
 EMAIL                                     NOT NULL VARCHAR2(25)  
 PHONE_NUMBER                                       VARCHAR2(20)
 HIRE_DATE                                 NOT NULL DATE         
 JOB_ID                                    NOT NULL VARCHAR2(10) 
 SALARY                                             NUMBER(8,2)
 COMMISSION_PCT                                     NUMBER(2,2)
 MANAGER_ID                                         NUMBER(6)
 DEPARTMENT_ID                                      NUMBER(4)

I’ve implemented the demo service used in this post with Java API for RESTful Web Services (JAX-RS), so if you want to play around with it, feel free to download my NetBeans project. If you plan to use Oracle ADF to develop your services then check out Andrejus Baranovskis’ post about building RESTful services with ADF 12c.

Anyways, it isn’t the implementation that’s the focus of this post, but some basic design principles that will make sure your RESTful services are easy to use in Oracle JET.

Identify the Resource

Unlike SOAP and similar RPC technologies, you should not think in verbs (i.e. hire employee), but in nouns (i.e. employee).

Use the noun as the basic for the URI to your resource. The noun should always be in plural even when it’s bad grammar (i.e. informations). When designing RESTful services, consistency beats grammar!

So the path to our Employee RESTful service would be /employees

Use HTTP Methods

We will use standard HTTP methods to interact with the resource:

Task Method Path
Create a new employeePOST/employees
Delete an existing employeeDELETE/employees/{id}
Get a specific employeeGET/employees/{id}
Get a collection of employeesGET/employees
Update an existing employeePUT/employees/{id}

All interactions with the resource are handled via HTTP methods. So if we want to hire an employee, we create a new employee via the POST method. If we want to give an employee a salary increase, we will use the PUT method to update an existing employee with a new salary.

You should also note how the bad grammar continues. Even when we deal with a single employee, we still use plural in the path name to keep the naming consistent.

In the POST method, we must make sure that the client doesn’t need to supply the primary key (i.e. employeeId) as input. The RESTful service should automatically take that from a sequence. The reason is that it will be impossible for the client to guess an unused primary key. On top of that, the POST method should return the newly created employee, so the client can get access to the primary key, and continue to manipulate the record if necessary.

You should be careful about using other HTTP methods than the Big Four (GET, POST, PUT, DELETE), because they might be rejected by proxy servers, load balancers, or other opinionated middlemen that stands between the client and the server.

It’s true that the client might be able to use HTTP tunneling to get the traffic through anyway, but it doesn’t exactly make it easy to call your web service…

The only other HTTP method you should seriously consider is PATCH. PATCH is similar to PUT but where PUT makes a complete update of all fields (including those that hasn’t been changed) then PATCH is a partial update that only overwrites fields that have actually been changed.

If the client deals with simple data in a form-oriented way (load all data into a form, manipulate them, and write them all back) then consider PUT, but if the client uses data-grids where individual cells are updated in isolation, or your service uses seriously big and complex data structures then consider PATCH.

Use JSON Only

For HTTP request and response bodies, we should only use JSON (and not XML).

Yes, it’s trivial to add XML support in JAX-RS by changing an annotation, but XML is simply not used by Oracle JET (or similar frameworks) and the agile principle of maximizing the amount of work not done (to keep things simple) should be followed.

Why? Because code that hasn’t been written doesn’t contain defects or security holes, and it doesn’t need to be tested and maintained. This is probably also why some highly popular RESTful APIs, like Twitter’s, dropped XML support several years ago…

Don’t Leak the Implementation!

Finally, it’s important not to leak the server’s implementation of the resource, as that’s one of the bedrock principles of the RESTful architecture. That is, the client shouldn’t notice that we use Java and an Oracle Database for the implementation.

The most obvious leak in this example would be to leak the names of the database columns to the client. The standard in JavaScript is to use camel case (i.e. phoneNumber) and not snake case (i.e. phone_number) like in an Oracle Database.

If we leak this then either the client code will look dodgy (by mixing two naming standards) or the client will waste valuable time on implementing the parse and parseSave functions in oj.Model.extend to do the conversion…


But if we stick to the design principles outlined in this post then Oracle JET’s Model and Collection APIs will take care of almost everything for us, which will make our Oracle JET code look really neat!

For example, if we want to get a specific employee, we only need this code:

var Employee = oj.Model.extend({urlRoot:     "http://localhost:17286/EmployeeREST/webresources/employees",
                                idAttribute: "employeeId"});

var employee = new Employee();
employee.id = 198;

employee.fetch({
  success: function() {
    console.log("Employee: ", employee.attributes);
  }
});

Or if we need all employees, we can do it like this:

var Employee  = oj.Model.extend({idAttribute: "employeeId"});
var Employees = oj.Collection.extend({url:   "http://localhost:17286/EmployeeREST/webresources/employees",
                                      model: new Employee()});
      
var employees = new Employees();
employees.fetch({
  success: function() {
    console.log("Employees.models: ", employees.models);
  }
});

Or if we need to create a new employee, we just use this code:

var Employee = oj.Model.extend({urlRoot:     "http://localhost:17286/EmployeeREST/webresources/employees",
                                idAttribute: "employeeId"});

var employee = new Employee();
employee.attributes.firstName = "Han";
employee.attributes.lastName  = "Solo";
employee.attributes.email     = "hansolo";
employee.attributes.hireDate  = "1977-05-27T00:00:00+02:00";
employee.attributes.jobId     = "SH_CLERK";

employee.save().then(function() {
  console.log("Saved with employeeId: " + employee.id);
});

The code examples above show that if we design our RESTful services carefully then it’ll be super easy to call them from Oracle JET!

That’s it for now! Thank you for reading.

PS. I have written a small eBook about REST Services. You can download it here: The Little Book on REST Services. It’s free!


Share this post:


Subscribe to this blog:

Just enter your email below and press the button:


Related Posts: