Combining DDD, multiple implementations, and REST

I am having a problem designing an application architecture that combines Driven Desing principles with REST. The biggest problem for me here is that Domain is only interface specifications and response objects. Of course, I can change this general layer as I please, but for now this is the idea. I need this generic layer because I want to connect one of the many implementations to the domain interface.

So this is it:

  • There are different business process mechanisms.
  • To have a common API for everyone, I need to wrap them in my wrapper classes that will implement my interfaces.
  • I expect there will be good encapsulation from my wrappers (as DDD shows - do not expose their internals)
  • I also expect to be able to expose my domain objects via REST, and this is where the biggest problem comes in:

Option 1 . I could combine REST encapsulation with classic objects (there are just public methods that display behavior and private fields annotated with @JsonProperty), but I need interfaces (or I could use abstract classes) and you cannot have private inherited fields. ..

Option 2 : I could use public getters annotated with @JsonProperty, but that would break encapsulation

Option 3 . What I think would be good here, at least from the point of encapsulation, is to create immutable value objects that will be implemented (if you can say the set of public fields is an implementation) in a common layer and will be used as input and output for certain methods called domain objects. Is this a good option? I have no idea ... This seems to work well and does not hinder the encapsulation principle.

I think this mainly explains my problem. I think it would be nice for the REST API to use Restlet objects, but for me the problem is tricking the Restlet Objects which are actually interfaces implemented by different implementation classes ...

I'm attaching some basic architecture diagram, maybe Itll can help you understand my problem: Architecture outline

+3


source to share


2 answers


I asked this question to an architect friend and this is what he wrote to me:

Let's think about what is REST? REST is simply a presentation layer that provides a view of the system. He already draws a distinction (system boundaries) between the system and its representation, what we have here is the classic problem of different responsibilities. I firmly believe that "meaning is the boundary of the system." I would not expose domain objects, but create value objects that are converted from and to domain objects. This means creating a whole bunch of value objects that represent individual resources at the REST level. Of course, if you're in the Java world, that means creating classes with getters and setters, but it's definitely worth it. I may sound fascists, but I would draw a clear border between the domain and its representation, you just need a good mapping layer (there are many),but I would not like to see domain objects in JAXRS endpoints (resources). In this way, you create an anti-corruption layer between you and other third party structures that you use for BPM, so, in short, this means that updates and changes within this framework will be under your control. So I think you are heading in the right direction but are not using domain classes in JAXRS and are creating Value objects.but don't use domain classes in JAXRS and create Value objects.but don't use domain classes in JAXRS and create Value objects.

I will need to build the following layers. BPM engine -> general interface (which in my understanding looks like Strategies from DDD) -> VO objects that are built using root aggregates (you need a way to define these objects), VO should have JSON mapping annotations, not generic interfaces -> JAXRS. which access the root aggregates gets VO from them -> Jackson does display magic



So, thanks to this you can have a stable interface, you don't want to rebuild your REST layer every time something changes inside the system. Therefore the VO is here to hide how your internal interface (common interfaces) changes. Correct me if I'm wrong, but you want to create a kind of common least denominator of BPM engines to have the same model despite the differences in Activit and jBPM models.

I think JAXRS should be a really thin layer, in the application I'm working on, in a few places we started adding some logic, you know the timing, eventually it all exploded on our faces when people didn't know there were some additional rules, refactoring was a nightmare. Finally, we moved on to a model where JAXRS will just reach for the aggregate roots / entities, request a VO, and return it back.

+1


source


I have the same architecture in one of my more complex enterprise applications. I approached this by creating "JAXB Value Objects" which, using JAXB (+ jackson if you like) annotations, defined the XML / JSON format that I wanted to see from the JAX-RS endpoints. I essentially used an adapter pattern so that I can treat this value object as implementations, and also added a factory method on these value objects so that I can do (sometimes deep) copying as needed. One thing that deviated from your # 3 is that I didn't make JAXB value objects immutable (although the interfaces seem to be immutable) because JAXB really doesn't like it. If I pass these JAXB value objects to another component (I don't), I'll make a defensive copy first.



In addition to keeping my domain built around interfaces (something JAXB really doesn't like), which was important across different implementations, as you mentioned, it also allowed me to define a different JAXB value object when I needed to have different "views" ...

+1


source







All Articles