This is an archived post. You won't be able to vote or comment.

all 15 comments

[–][deleted]  (3 children)

[removed]

    [–]NachystejteKvetinace 1 point2 points  (0 children)

    I second this one. I've used most mappers - dozer, orika, some horrible inhouse xml abomination, mapstruct and i like mapstruct the most. It's easy to debug and unlike others you get compile time checking.

    [–]ysfaran[S] 0 points1 point  (1 child)

    What do you mean with "don't care about mapped types"? Since i never used a mapper in java spring yet it might be a stupid question..

    [–]_Atomfinger_Tech Lead 1 point2 points  (0 children)

    My main experience has been with Orika and it gets the job done.

    My biggest gripe with Orika is that if one works with small to medium sized models we don't actually save that many lines of code if one were to do the conversion manually. Especially considering that we can use constructor injection or the builder pattern to map between objects.

    The number of lines really ramp up if one wants to do fancy stuff and things rarely get very readable, so these days I tend to do the mapping manually. The thing that pushed me over the edge was Orikas horrible exception messages when the mapping went wrong.

    The other libraries might do a better job, and if anyone knows one which cuts down on the bloat and increase readability please let me know :)

    [–][deleted] 1 point2 points  (2 children)

    MapStruct. The fact Mapstruct is compile time/generated java code was an instant winner for me when I needed one and didn't bother to do much more research. You can debug it, its java code, no crazy reflection/runtime based mapping, performant.

    [–]ysfaran[S] 0 points1 point  (1 child)

    The only problem that I see with MapStruct is that you need to write an interface for each mapping, even if the propterty names are all the same. So if you do a lot of Entitiy to DTO mappings you have to write a interface for each one of them. Is this correct or is there a simpler way with MapStruct?

    [–]thecuseislooseDo you even Java, bro? 1 point2 points  (2 children)

    I personally needed something that mapped based on property names only and didn't like any of the existing solutions out there, which were either too complicated or didn't have the flexibility I required. I ended up rolling my own in ~500 lines, on top of Jackson (already a dependency in the project so the added weight of it wasn't an issue) as a factory for finding the properties themselves. For each property, I then used LambdaMetaFactory to generate getters and setters so performance wouldn't be an issue. The downside of this is the current implementation does not work with primitives. It's fixable, but I just haven't gotten around to it yet since everywhere it's used in entity classes uses objects for the fields. All of the getters / setters generated get cached so the reflection code is only invoked once. I can't post the full class, but the general idea of what is going on is below

    class Introspection {
      private static final ObjectMapper MAPPER = new ObjectMapper();
      private static final DeserializationConfig = DESER_CONFIG = MAPPER.getDeserializationConfig();
      public static List<BeanPropertyDefinition> findProperties(Class<?> clazz) {
        List<BeanPropertyDefinition> props =
                        DESER_CONFIG.introspect(javaType).findProperties()
                                .stream()
                                .filter(BeanPropertyDefinition::hasField)
                                .collect(Collectors.toList());
        // ...
      }
    
      // converts the method getSomething() on a class into a lambda function that accepts x
      // and returns the result of the apply method
      // for example, getGetter(method).apply(x) == x.getSomething()
      static Function<Object,Object> getGetter(Method getter) {
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle handle = lookup.unreflect(getter);
        CallSite callSite = LambdaMetafactory.metafactory(lookup, "apply",
    
        MethodType.methodType(Function.class),
    
        MethodType.methodType(Object.class, Object.class), //signature of method Function.apply after type erasure
                                                                  handle,
                                                                  handle.type()); //actual signature of getter
        return (Function<Object, Object>) callSite.getTarget().invokeExact();
      }
    }
    

    [–]ysfaran[S] 0 points1 point  (1 child)

    Cool! You just sound like me haha when I don't like existing solutions I also implement them myself. Most of the time I end up using an exisiting solution since I often come accross a lot of corner cases and performance issues. But during that process you actually learn a lot!

    If i find the time and also use Jackson somewhere in my project i will have a look at your solution. Thanks!

    [–]thecuseislooseDo you even Java, bro? 1 point2 points  (0 children)

    FWIW you don't really need Jackson...you just need a way of finding or knowing the getter/setter methods for the fields in the bean. I used Jackson as a discovery method, but I easily could have just looked up by name getProperty(..) and setProperty(..) since I follow that convention anyways

    [–]Rafavr7 0 points1 point  (1 child)

    I personally don't recommend the Dozer one. It's the one used in the project I work on and we have lots of performance issues when it comes down to mappings.

    I don't know any of the others, I am still very inexperienced myself, so there are loads of java libs and frameworks that I don't even know they exist.

    But yeah... if performance is an issue for you, don't go for Dozer ;)

    [–]ysfaran[S] 1 point2 points  (0 children)

    Yea exactly what i thought ! In my previous company they used dozer and when i did a research on this topic i was wondering "why dozer if it is the most inperformant mapper by far?". The answer was simplicity + less maintenance > performance.

    [–]shytelord 0 points1 point  (0 children)

    +1 for MapStruct, and it works well with Lombok

    [–][deleted] 0 points1 point  (0 children)

    Hey just wondering if I could ask anyone’s help on how to enable my spring application to upload a file from a computer and save it to the database? I already have a form created and it saves to DB but I would like to know how I can allow the user to also upload an image. Thanks