problem invoking external mappers

939 views
Skip to first unread message

b lee

unread,
Mar 8, 2015, 9:14:24 AM3/8/15
to mapstru...@googlegroups.com
I  am exploring use of mapstruct using the examples Car, CarDto examples given. So far so good for the basic mapping (omitting the CarType which gives an error). However I am trying to extend the demo to convert Fahrenheit to Celsius using the instructions in 5.3. I think I am following the instructions correctly but i can not get the conversion to work. The code and error result is given below. Appreciate any help to resolve this 

defaults  are used for all configurations options - i.e. no component model is specified

============================================
Buildfile: /home/brian/workspace/TestMapper/build.xml
compile:
     [echo] Compiling ...
    [javac] Compiling 6 source files to /home/brian/workspace/TestMapper/bin/cla
sses
    [javac] /home/brian/workspace/TestMapper/src/org/TestMap/CarMapper.java:15: 
error: No property named "fahr" exists in source parameter(s).
    [javac]        @Mapping(source= "fahr", target ="celsius")
    [javac]        ^
    [javac] warning: No processor claimed any of these annotations: org.mapstruc
t.Mappings,org.mapstruct.Mapper
    [javac] 2 errors
    [javac] 1 warning

BUILD FAILED
/home/brian/workspace/TestMapper/build.xml:39: Compile failed; see the compiler 
error output for details.

Total time: 2 seconds

=================================


public class TempMapper {
public TempMapper(){
}
public long toFahr(long temp){
return ((temp*9)/5)+32;
}
public long toCelsius(long temp){
return (temp*5/9)-32;
}

}


@Mapper(uses=TempMapper.class) 
public interface CarMapper {
 
   CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); 
 
   
   @Mappings({
       @Mapping(source = "numberOfSeats", target = "seatCount"),
       @Mapping(source= "fahr", target ="celsius")
   })
   
   
   CarDto carToCarDto(Car car); 
}


public class Car {
   private String make;
   private int numberOfSeats;
  // private CarType type;
   private int type;
   
   private long fahr;
 
   public Car(String makee, int numSeats, int ctype) {
   
   make=makee;
   numberOfSeats=numSeats;
   type=ctype;
   }
   //constructor, getters, setters etc.

public String getMake() {
return make;
}

public void setMake(String make) {
this.make = make;
}

public int getNumberOfSeats() {
return numberOfSeats;
}

public void setNumberOfSeats(int numberOfSeats) {
this.numberOfSeats = numberOfSeats;
}

public int getType() {
return type;
}

public void setType(int type) {
this.type = type;
}

}

public class CarDto {
 
   private String make;
   private int seatCount;
   private String type;
   
   private long celsius;
   
   public CarDto() {
   
   }

public String getMake() {
return make;
}

public void setMake(String make) {
this.make = make;
}

public int getSeatCount() {
return seatCount;
}

public void setSeatCount(int seatCount) {
this.seatCount = seatCount;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}
 
 
   //constructor, getters, setters etc.
}

Andreas Gudian

unread,
Mar 8, 2015, 9:52:51 AM3/8/15
to b lee, mapstru...@googlegroups.com
Hi Brian,

Did you specify getters and setters for your new attributes?

Andreas
--
You received this message because you are subscribed to the Google Groups "mapstruct-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mapstruct-use...@googlegroups.com.
To post to this group, send email to mapstru...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

b lee

unread,
Mar 8, 2015, 12:00:30 PM3/8/15
to mapstru...@googlegroups.com, leeb...@gmail.com
Andreas,
Thanks for the quick response. No I did not as I expected that the methods in the external mapper class would be substituted fr regular get/set methods.  This is implied in 5.3 of the User manual and the example class there - see text below  from  5.3. If I create get/set methods then the external mapper will not be invoked I guess ?

regards
Brian 

"

In addition to methods defined on the same mapper type MapStruct can also invoke mapping methods defined in other classes, be it mappers generated by MapStruct or hand-written mapping methods. This can be useful to structure your mapping code in several classes (e.g. with on mapper type per application module) or you want to provide custom mapping logic which can’t be generated by MapStruct.

For instance the Car class might contain an attribute manufacturingDate while the corresponding DTO attribute is of type String. In order to map this attribute, you could implement a mapper class like this:

  1. public class DateMapper {
  2.  
  3. public String asString(Date date) {
  4. return date != null ? new SimpleDateFormat( "yyyy-MM-dd" )
  5. .format( date ) : null;
  6. }
  7.  
  8. public Date asDate(String date) {
  9. try {
  10. return date != null ? new SimpleDateFormat( "yyyy-MM-dd" )
  11. .parse( date ) : null;
  12. }
  13. catch ( ParseException e ) {
  14. throw new RuntimeException( e );
  15. }

In the @Mapper annotation at the CarMapper interface reference the DateMapper class like this:

  1. @Mapper(uses=DateMapper.class)
  2. public class CarMapper {
  3.  
  4. CarDto carToCarDto(Car car);
  5. }

When generating code for the implementation of the carToCarDto() method, MapStruct will look for a method which maps a Date object into a String, find it on the DateMapper class and generate an invocation ofasString() for mapping the manufacturingDate attribute.

To unsubscribe from this group and stop receiving emails from it, send an email to mapstruct-users+unsubscribe@googlegroups.com.
To post to this group, send email to mapstruct-users@googlegroups.com.

Andreas Gudian

unread,
Mar 8, 2015, 3:08:07 PM3/8/15
to b lee, mapstru...@googlegroups.com
Hi Brian,

the generated code would kind of look like this:

carDto.setCelsius( tempMapper.toCelsius( car.getFahr() ) );

So you will need at least a getter for "fahr" in class Car and a setter for "celsius" in CarDto.

The error message given in your compile output means that there is no method "getFahr()" in the source type (Car) - that would correspond to a readable bean property with name "fahr".

Andreas


To unsubscribe from this group and stop receiving emails from it, send an email to mapstruct-use...@googlegroups.com.
To post to this group, send email to mapstru...@googlegroups.com.

b lee

unread,
Mar 8, 2015, 6:40:30 PM3/8/15
to mapstru...@googlegroups.com, leeb...@gmail.com
Hi Andreas,
I added the getter/setter for the two attributes and got the  error below which I'm not sure what it means ?

[javac] /home/brian/workspace/TestMapper/src/org/TestMap/CarMapper.java:19: 
error: Ambiguous mapping methods found for mapping property "long fahr" to long:
 long org.TestMap.TempMapper.toFahr(long temp), long org.TestMap.TempMapper.toCe
lsius(long temp).
    [javac]    CarDto carToCarDto(Car car); 


Brian 

Andreas Gudian

unread,
Mar 9, 2015, 3:56:47 AM3/9/15
to b lee, mapstru...@googlegroups.com
That means that there are two methods available that map from long to long and MapStruct can't decide which one to use, because they both fit equally well.

You would have to use Qualifier annotations to clear this up - see the docs for an example.
Reply all
Reply to author
Forward
0 new messages