Design Pattern to model Request and Response Objects for Webservices

The big problem I see in all the answers so far including the question is that they all violate the principal of separation of concerns, information hiding and encapsulation. In all answers request (and response) classes are tightly coupled to model classes. That is a more serious issue and raises a question more important than the relationship between the requests and responses…

What should be the relationship between the request/response classes and the model classes?

Since the request class (e.g. CreateBookRequest) and the model class Book have mostly the same data properties, you could do any of the following:

A. Put all your data/getters/setters into the Book class and have the CreateBookRequest extend from the class

B. Have your CreateBookRequest contain a Book as a member (as in the question and answers given by ekostadinov, Juan Henao, . The generic usage given by dasm80x86 is also a special case of this)

C. Put data/getters/setters in BookBase and have both Book and CreateBookRequest extend from BookBase

D. Put all/some data/getters/setters in BookStuff and have both Book and CreateBookRequest contain a BookStuff

E. Put all the data/getters/setters in both Book and CreateBookRequest. (you can copy-paste).

The correct answer is E. We are all so trained and eager to “re-use” that this is the least intuitive answer.

The request class CreateBookRequest (as well as the response class CreateBookResponse) and the model class Book, should NOT be be in same class hierarchy (other than both having Object as a top most parent) (A,C). Also the CreateBookRequest should not refer/contain to the model Book or to any of the composite classes that are members in the Book class (B,D)

The reasons for this are as follows:

  1. You want to modify the model object or the request object independent of each other. If your request refers to your model (as in A-D) any change in the model will be reflected in the interface, and therefore break your API. Your customers are going to write clients according to the API dictated by your request/response classes and they don’t want to change those clients whenever you make a change to your model classes. you want the request/response and the model to vary independently.

  2. Separation of concerns. Your request class CreateBookRequest may contain all kinds of interface/protocol related annotations and members (e.g. validation annotations that the JAX-RS implementation knows how to enforce). These interface-related annotations should not be in the model object. (as in A)

  3. from an OO perspective CreateBookRequest is not a Book (not IS_A) nor does it contain a book.

The flow of control should be as follows:

  1. The interface/control layer (the one that receives the Rest-API calls) should use as its methods parameters Request/Response classes defined specifically for that layer (e.g. CreateBookRequest). Let the container/infrastructure create those from the REST/HTTP/whatever request.

  2. The methods in the interface/control layer should create in some way an instance of a model class object, and copy values from the request classes
    into the model class object,

  3. The methods in the interface/control layer should call a BO/Manager/Whatever (in the model layer… which is responsible for business logic) passing to it the model class object and not the interface class/method parameter class object (in other words, NOT as Luiggi Mendoza has shown in his answer)

  4. The model/BO method would return some model class object or some “primitive”.

  5. Now the interface method (the caller) should create an interface class response object, and copy values into it from the model class object returned by the model/BO. (Just like Luiggi Mendoza as shown in his answer)

  6. The container/infrastructure would then create the JSON/XML/whatever response from the response class object.

Now to the question asked… What should be the relationship between the requests and response classes?

Request classes should extend from request classes and not extend nor contain response classes, and vice versa. (as was also suggested by question asker).
Usually you have a very basic BaseRequest class, extended by something like CreateRequest, UpdateRequest, etc… where properties common to all create requests are in CreateRequest which is then extended by more specific request classes such as CreateBookRequest…
Similarly, but parallel to it, the is the Response class hierarchy.

The question asker also asked whether it’s ok for both CreateBookRequest and CreateBookResponse to contain the same member such as (Never a model class though!) BookStuffInRequestAndResponse which properties common to both the request and response?

This is not as severe an issue as having the request or response refer to a class that is also referred to by the model. The problem with this is that if you need to make a change to your API request and make it in BookStuffInRequestAndResponse, it immediately affects your response (and vice versa).

It’s not so bad because 1) if your customer needs to fix their client code because you change the request parameters, they may as well fix handle/fix the changed response and 2) most likely changes in the request would require change to the response any way (for example adding a new attribute), however, that may not always be the case.

Leave a Comment