-
Notifications
You must be signed in to change notification settings - Fork 351
Description
At the moment, there is only one way to ignore a field in ModelMapper
and that's to reference the field's setter in a skip()
call when configuring the TypeMap
for a given mapping. This means that you need a setter for a field, even if the only purpose of that setter is to be passed to the skip()
call. Normally, that would work fine even though it's a little annoying, but it means additional boilerplate for every mapping that requires a skip, unless you want to throw away the very useful validate()
function.
At my job, we have a custom reflection-based mapper from our database objects to POJOs. That mapper handles things similarly to ModelMapper
. I would like to deprecate that code and use ModelMapper
instead since it does basically what we want it to do. The difficulty comes with a security layer that we also have. We take the POJOs and run them through a security service that can decide to redact individual fields of a POJO. It accomplishes this by expecting POJOs which it touches to have a no-args constructor and reflects over fields, creating a new POJO and then copying over all fields that aren't redacted. Additionally, it sets another field (identified by a security annotation) which is an enum implementation of an interface that lets downstream clients know what rule was applied to redact the POJO.
This field is where we run into trouble. I've got the rest of the system integrated with ModelMapper
just fine, including finding these POJOs based on annotation, creating TypeMap
structures for each so they automatically get validate()
support and an optional configure(TypeMap typeMap)
function on the POJO for any mappings that need custom rules. However, with the current skip support, every one of our POJOs needs to define that custom configure()
and a setter for the security field just to ask ModelMapper
to ignore the field. The best alternative I've come up with so far is to create an interface that contains a dummy setter which matches the field name and has a default implementation that does nothing. Then, I can add a skip to the TypeMap
for that POJO based on seeing if the POJO implements that interface. That's messy, is easy for a developer to forget, and also ends up adding boilerplate to POJOs that otherwise are zero-config. Our existing reflection-based custom mapper knows how to ignore this field.
I'd like to teach the annotation-scanning code which creates the initial TypeMap
for each POJO to auto-skip this field based on the security annotation that's present on the field, but if the only way I can skip is to provide a concrete setter, I can't. Using a lambda doesn't work because ModelMapper
uses the name of the setter function in the skip()
call to determine the field being skipped, so I can't create a setter with reflection. Asking each engineer to remember to add configuration that includes just the mapper->skip()
call is unnecessary boilerplate that somewhat negates the point of a configuration-light service like ModelMapper
, especially when many POJOs would otherwise require zero configuration. I also don't want to stop calling the validate()
function because it's quite useful and is in my opinion one of the selling features of ModelMapper
.
What do you think about a skip()
variant that takes a string which it can match against an attribute? I know this bumps up against the "refactoring safe" goals of the library, but I don't see any other way short of introducing an annotation to the ModelMapper
library for skipping fields. Either way, I'd like there to be a way for infrastructure code that sets up ModelMapper
TypeMap
configurations to be able to ignore fields in a general manner. I'm willing to take a stab at a solution and put up a PR, but if that's not the direction this library wants to go, I might as well look elsewhere. What are your thoughts in this area?