Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible for MapStruct to automatically detect mappings for Collections containing generic types as both source and target?

I recently picked up MapStruct, and I really like the way it works. Since I'm new to MapStruct, I apologize in advance if this question is silly or makes little sense.

Due to server version, I'm bound to Java 6.

I have 3 types of entities, A, B, and C, as well as their DTO counterparts.

public class A{
    //...
}
public class B extends A{
    //...
}
public class C extends A{
    //...
}

public class ADto{
    //...
}
public class BDto extends ADto{
    //...
}
public class CDto extends ADto{
    //...
}

My mapper defines:

public abstract ADto mapAToADto(A source);

public abstract A mapADtoToA(ADto source);

public abstract BDto mapBToBDto(B source);

public abstract B mapBDtoToB(BDto source);

public abstract CDto mapCToCDto(C source);

public abstract C mapCDtoToC(CDto source);

Which works fine for now.

In my application, I work with List<A> and List<ADto> that contains both subtypes.

My current implementation was to implement my own mapping method that iterates over source list and checks types with instanceof , then calls matching mapping method listed above.

Current implementation:

public <T extends ADto, S extends A> List<T> toList(List<S> source) {
if (source == null) {
    return null;
}

List<T> list = new ArrayList<T>();
for (S entity : source) {
    if (entity instanceof B) {
        list.add((T) mapBToBDto((B) entity));
    } else if (entity instanceof C) {
        list.add((T) mapCToCDto((C) entity));
    } else {
        list.add((T) mapADtoToA((A) entity));
    }
}

return list;
};

I was wondering if there is a way to direct MapStruct to figure it out automatically. Am I missing something?

Edit: My optimistic approach was with:

@IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL)
public abstract <T extends ADto, S extends A> List<T> listAToADto(List<S> source);

Which results in:

Can't generate mapping method for a generic type variable target

Thank you

like image 738
Željko Tomić Avatar asked Sep 05 '17 12:09

Željko Tomić


People also ask

What is MapStruct used for?

MapStruct is a code generator tool that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach. The generated mapping code uses plain method invocations and thus is fast, type-safe, and easy to understand.

How do I map a MapStruct collection?

In general, mapping collections with MapStruct works in the same way as for simple types. Basically, we have to create a simple interface or abstract class and declare the mapping methods. Based on our declarations, MapStruct will generate the mapping code automatically.

How do you map a list of objects using MapStruct?

Using Mapstruct we can map list in similar fashion as we map primitives. To get a list of objects, we should provide a mapper method which can map an object.

Does MapStruct use reflection?

During compilation, MapStruct will generate an implementation of this interface. This implementation uses plain Java method invocations for mapping between source and target objects, i.e. no reflection or similar.


1 Answers

Your implementation is correct. MapStruct is an Annotation Processor that generates code during compilation. We don't generate any reflection checks (All the types that implement and interface or extend a class are not known during compilation). Therefore your approach to the problem is correct.

like image 91
Filip Avatar answered Sep 28 '22 08:09

Filip