I'm working in Java Spring, and I have typical service and repository layers. The repository grabs a JSON; passes it along to the service; service maps the repository response to a DTO.

I also need to perform some event logging afterwards (send these events to an auditing REST service), which requires some properties that are not part of the DTO, but rather part of the repository response object. Note that these particular properties are actually used as part of the business logic to perform the mapping.

So, you may say that for obvious reasons, just go ahead and use the repository response object to perform these event loggings since some of properties are not present in the DTO object.

However, mapping of repository response to DTO requires quite a bit of calculations, business rules, etc. which now the event logging also needs if I only use the repository response. In other word, I have to again execute those same business rules which I performed during mapping, and use them for event logging process. All because the event logging needs a few properties that repository response object has but not the DTO object.

To make matters worse, the same DTO object is used by a few controllers to ultimately send results back as part of the JSON.

There are two solutions I pondered:

  1. Include those needed properties in the DTO object, so they can be used by the event logging process, but go ahead and mute them during marshalling/demarshalling with the JSON library. If additional event logging scenarios are introduced with more missing properties from the repository response, then I have to keep adding them here
  2. Do a portion of logging that requires those missing properties from DTO while performing the mapping in place. The issue is, now I'm heavily coupling the operation of mapping from one object to another with partial or complete event logging which will be terrible for unit testing and general laws of universe. Also, as additional event logging scenarios might come along, this coupling becomes even deeper and deeper

I wanted to know if there are other solutions/design patterns that can be more sensible, extensible, and maintainable that I can utilize?


Given that you want to keep doing your logging where you're doing it, rather then move it to where all this stuff is already known, I'd go with option 1.

What I'd do a little differently isn't to teach something to "mute" them before marshalling. That smacks of knowing more than I want to know. I'd spin up another DTO for logging and send both together in a collection. Then you can hand marshalling what it's always expected and logging can have whatever it's extra little bit of info is without anything but logging knowing whatever that is.

This is an old idea that has been used on errors when you don't want to handle them right away and don't want to branch your process with an exception but you still want the error to get expressed. You just pack up the error and stuff it in the typical dataflow. You can find a great lesson on that here.

Now if you don't like casting when you take things out of a collection I'm afraid you have a little bit of work ahead of you because Java still doesn't offer a heterogeneous collection in its standard library. Joshua Bloch (author of much of Java) has you covered. Either follow that link or pick up a copy of his book: Effective Java.

| improve this answer | |

The better is option I found was to create a new object that extends an aggreggate portion of my DTO object (ObjThatIsNeededForBothUIAndLogging ) and placed those extra properties there (ObjWithExtraProps), and use that for my logging purposes. I can then copy properties needed for UI from ObjWithExtraProps to its parent's (ObjThatIsNeededForBothUIAndLogging) minus those extra properties when needed, e.g.:

MainServiceObject (DTO) ---- Inherits ----> ObjectUsedForUI (JSON)
       |           \                                |
  Aggregate         \                            Aggregate
       |             \________ Old Aggregate _____<>|
       /\                                           /\
       \/                                           \/ 
   ObjWithExtraProps ------ Inherits -----> ObjThatIsNeededForBothUIAndLogging  
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.