Reputation: 1332
I’ve got a problem designing architecture for an application combining Domain Driven Desing principles with REST. The biggest problem for me here is that the Domain is just interfaces specification and response entities. Of course I can change this common layer as I please, but for now that’s the idea. I need this common layer because I want to be able to plug one of many implementations to the domain-based interface.
So here it comes:
Option 1: I could combine encapsulation with REST with classical objects (just have public methods exposing behaviours and private fields annotated by @JsonProperty), but I need interfaces (or I could use abstract classes), and you can’t have private inherited fields there...
Option 2: I could use public getters annotated by @JsonProperty, but that would break encapsulation
Option 3: So what I thought would be good here, at least from encapsulation point is creating immutable value objects that will be implemented (if you can say that set of public fields is an implementation) in the common layer, and will be use as input and output for specific methods called on domain objects. Is it a good option? I have no idea… It just seems to work well and don’t brake encapsulation principle
I think it basically explains my problem. What I think would be good for the REST API is using Restlet Objects, but it’s a problem for me to wrap my mind around Restlet Objects, that are in fact interfaces implemented by different implementation classes…
I’m attaching some basic architecture diagram, maybe It’ll help you understanding my problem:
Upvotes: 3
Views: 1336
Reputation: 1332
I've asked this question to a friend architect and this is what he wrote me:
Let’s think what is REST? REST is just a representation layer, which exposes a view on the system. It already draws a distinction (systems boundaries) between system and its representation, what we have here is classic problem of different responsibilities. I do strongly believe that “value is system boundary”. I wouldn’t expose domain objects, but rather create value objects, which are transformed from and to domain objects. It means creating whole bunch of value objects which represent individual resources at REST layer. Of course if your are in Java world it means creating classes, with getters and setters, but it is definitely worth it. I may sound like fascists but I would draw clear boundary between domain and its representation, you would just need nice mapping layer (there is plenty of these), but I wouldn’t like to see domain objects in JAXRS endpoints (resources). This way you create anticoruption layer between you and and other thirdparty frameworks you use for BPM, so in short it means upgrades and changes in these frameworks will be under YOUR control. So I think you are heading into right direction, but would not use domain classes in JAXRS, and create Value Objects.
I would need to build following layers. BPM engine -> common interface (which in my understanding look like Strategies from DDD) -> VO objects which are build by root aggregates (you need a way to factor these objects), VO should have JSON mapping annotations, not common interfaces -> JAXRS which access root aggregates, gets VO from them -> Jackson does the magic of mapping
So thanks to this you could have stable interface, you don’t want to rebuild your REST layer every time something changes inside of the system. So VO are here to hide how your internal interface (common interfaces) change. Correct me if I am wrong, but you want to create kind of common lowest denominator of BPM engines, to have same model, despite of differences of Activit and jBPM models.
I do think JAXRS should be really thin layer, in application I work on, in couple of places we started to add some logic, you know deadlines, at the end of the day everything exploded in our faces, when people didn’t know that there are some additional rules applied in JAXRS, refactoring was nightmare. Finally we moved to model where JAXRS just reaches for aggregate roots/entities asks for VO and returns it back.
Upvotes: 1
Reputation: 1894
I have essentially the same architecture on one of my more complex enterprise applications. I approached this by creating "JAXB value objects" that, using JAXB (+jackson, if you wish) annotations, defined the XML/JSON format I wished to see from the JAX-RS endpoints. I essentially used an adapter pattern so I could treat those value object as implementations as well, and added a factory method on those value objects so I could do the copying (sometimes deep) as necessary. One thing that deviated from your #3 is that I did not make my JAXB value objects immutable (although the interfaces appear immutable) because JAXB really don't like this. If I'm passing these JAXB value objects to another component (I don't) I would do a defensive copy first.
In addition to keeping my domain built around interfaces (something JAXB really doesn't like), which was important for different implementations like you mentioned, it also allowed me to define different JAXB value object when I did need to have different "views" defined.
Upvotes: 1