1

I'm working on a personal project, desktop app for client and REST API server that handles all of database inquiries.

Here's my scenario.

I have a hibernate entity in high level

@Entity
@Table(name="Customer")
public class Customer {
    private int id;
    private int age;
    // getters and setters
}

Client and server will use the same persistence class since even though it provides REST API, I'll be the only one working on the client.

The REST API v1 response for get Customer is

new ResponseEntity<Customer>(article, HttpStatus.OK);

Then the client will receive the Customer json and parse it back to Customer object.

Now my question is, if there's a change in Customer class, say age field got deleted and dob field is added, how do I manage this change on the server side?

I've read articles on creating versions but I cannot imagine how it can be done in a situation like this. v2 will use the most recent version of Customer class but then v1 will be unavailable (in other words it's response has changed) as v1's Customer class version does not exist anymore. Some were suggesting to use different packages for each versions and I don't think it's appropriate because that means all of the business logic that uses these persistence classes will also have to be put into different packages according to their versions.

I may be using the wrong structure so any advice is highly appreciated.

fwan
  • 183
  • 2
  • 3
  • 14

3 Answers3

0

If you want to share a subset of classes between two applications, you typically go and pack all those classes into a separate jar file and exchange it between the applications.

A possible Maven-based scenario would be creating a new project with the classes you want to share. Pull up the artifact's version everytime you make a change and mvn install it into an artifact repository, e.g. Nexus. Now you need to pull up the dependency in both your desktop app and server project.

Of course, there are other ways, but isolating shared code in a separate module/project is probably the recommended way to go.

Jan B.
  • 6,030
  • 5
  • 32
  • 53
0

Versioning can be tricky when you expose persistence models in the REST API. To deal with multiple versions, you should consider different DTOs for each version of your REST API, as suggested in this answer.

Dedicated REST API models will bring the benefit of exposing only the data that you need. Then your controllers or services can handle it accordingly.

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
0

One of the motivations of providing an API (web or otherwise) is to insulate the client from implementation changes. So if a change to your implementation must ripple out into the API, you've lost the plot somewhere.

Resources you should review

Here's a key takeaway from Webber

The web is not your domain, it's a document management system. All the HTTP verbs apply to the document management domain. URIs do NOT map onto domain objects - that violates encapsulation. Work (ex: issuing commands to the domain model) is a side effect of managing resources. In other words, the resources are part of the anti-corruption layer. You should expect to have many many more resources in your integration domain than you do business objects in your business domain.

OK, down into your issue

I've read articles on creating versions but I cannot imagine how it can be done in a situation like this. v2 will use the most recent version of Customer class but then v1 will be unavailable (in other words it's response has changed) as v1's Customer class version does not exist anymore. Some were suggesting to use different packages for each versions and I don't think it's appropriate because that means all of the business logic that uses these persistence classes will also have to be put into different packages according to their versions.

Here are the key ideas: the semantic meaning of "Customer" doesn't seem to be changing; your old clients have every right to expect the old representation will continue to work. So the first idea to integrate into your design is that the integration resource that provides a differently shaped representation of the Customer is a different resource in your API.

So there "should" be an old endpoint that returns the old representation, and a newer endpoint that retrieves the new one.

Second point is that you should be putting some design effort into your contracts up front (obviously, this isn't critical in an exercise where you control both the server and the only client; but if this intended to be a learning exercise, it is). That means, among other things, taking care to understand which elements in a representation are mandatory, and which are optional.

The client only has a right to expect that mandatory fields will be present. Optional fields may be present, but the client has to be written robustly enough to handle the case where they are not (a typical implementation will have a default value to stand in if the server doesn't provide one). Furthermore, the clients must expect that new fields may appear, and these must be ignored.

Sometimes known as weak schema, this approach should be familiar if you have looked into the details of avro, protocol buffers, and so on. It basically means building into your representation (message) design the ability to extend it in the future.

Community
  • 1
  • 1
VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91