Conversion between types

1,207 views
Skip to first unread message

Filipe Sousa

unread,
Jul 2, 2015, 5:05:38 PM7/2/15
to mapstru...@googlegroups.com
I have this class

public class User {
private Integer key1;
private Integer key2;
private Integer num1;
private Integer num2;
private String name
;

and this DTO

public class UserDto {
private String key1;
private String key2;
private String num1;
private String num2;
private String name;

and my mapper

@Mapper(uses = KeyMapper.class)
public interface UserMapper {
@Mappings({
@Mapping(target = "key1", qualifiedBy = Key.class),
@Mapping(target = "key2", qualifiedBy = Key.class)
})
UserDto toUserDto(User disciplina);

@Mappings({
@Mapping(target = "key1", qualifiedBy = Key.class),
@Mapping(target = "key2", qualifiedBy = Key.class)
})
User toUser(UserDto dto);
}

the key mapper

public class KeyMapper {
@Key
public String asString(Integer value) {
return "[" + value + "]";
}

@Key
public Integer asInteger(String value) {
return 0;
}
}


What I'm looking is to convert between an Integer and a String using KeyMapper as a provider.

The problem is that sometimes the compiler generates this

@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2015-07-02T22:00:58+0100",
comments = "version: 1.0.0.CR1, compiler: javac, environment: Java 1.8.0_45 (Oracle Corporation)"
)
public class UserMapperImpl implements UserMapper {

private final KeyMapper keyMapper = new KeyMapper();

@Override
public UserDto toUserDto(User user) {
if ( user == null ) {
return null;
}

UserDto userDto = new UserDto();

userDto.setKey1( keyMapper.asString( user.getKey1() ) );
userDto.setKey2( keyMapper.asString( user.getKey2() ) );
userDto.setName( user.getName() );
userDto.setNum1( keyMapper.asString( user.getNum1() ) );
userDto.setNum2( keyMapper.asString( user.getNum2() ) );

return userDto;
}

instead of

@Override
public UserDto toUserDto(User user) {
if ( user == null ) {
return null;
}

UserDto userDto = new UserDto();

userDto.setKey1( keyMapper.asString( user.getKey1() ) );
userDto.setKey2( keyMapper.asString( user.getKey2() ) );
userDto.setName( user.getName() );
if ( user.getNum1() != null ) {
userDto.setNum1( String.valueOf( user.getNum1() ) );
}
if ( user.getNum2() != null ) {
userDto.setNum2( String.valueOf( user.getNum2() ) );
}

return userDto;
}

That depends if tell the IDE (intellij) to compile UserMapper.java or UserMapperImpl.java

Is this the right way to do a custom conversion between types?

Thanks.

Gunnar Morling

unread,
Jul 3, 2015, 12:40:14 PM7/3/15
to mapstru...@googlegroups.com, nat...@gmail.com
Hi Filipe,

So is this to say that the generated output differs, without any changes to the mapped object types and the mapper definition? That would not be good indeed.

> That depends if tell the IDE (intellij) to compile UserMapper.java or UserMapperImpl.java

Are you compiling specific classes individually? So the problem does not occur when you do a full build (either in the IDE or on the command line)?

The expected output is the second one you posted, i.e. apply the @Key-qualified method only for key1 and key2, as only they are annotated with qualifiedBy=Key.class, unlike the num1/num2 properties. So your usage looks right, if that's what you wish to achieve. I am unsure what may cause the other version to be generated. It may be related to compiling only parts of the project in IntelliJ, I'd assume that it is not advisable to do so.

Btw. you can use @InheritInverseConfiguration on one of the methods to avoid the duplicated configuration.

--Gunnar

Andreas Gudian

unread,
Jul 3, 2015, 1:09:30 PM7/3/15
to Gunnar Morling, mapstru...@googlegroups.com, nat...@gmail.com
Gunnar, I think we talked about this a while ago: the qualifer-based selection currently allows all methods (qualified and unqualified) if the no qualifier is given (e.g. for a property).

We also discussed changing that in the way you described it above - but I didn't find an issue for it. It either slipped us by or the discussion came to a different conclusion- I don't really remember ;-).
--
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.

Gunnar Morling

unread,
Jul 3, 2015, 1:53:05 PM7/3/15
to Andreas Gudian, nat...@gmail.com, mapstru...@googlegroups.com

I just tried in Eclipse and it created the code I described. I am wondering though why it should change intermittendly which is what Filipe seems to report IIUC?

Andreas Gudian

unread,
Jul 3, 2015, 2:00:16 PM7/3/15
to Gunnar Morling, nat...@gmail.com, mapstru...@googlegroups.com
Just checked the code, apparently we did decide on something and changed qualifier-selector accordingly :-). 

@Filipe: does your qualifier have retention of at least "class"? Perhaps the annotation is missing in the class file? 


Am Freitag, 3. Juli 2015 schrieb Gunnar Morling :

Filipe Sousa

unread,
Jul 3, 2015, 3:45:42 PM7/3/15
to mapstru...@googlegroups.com, nat...@gmail.com, gunnar....@googlemail.com
I thinks that's the problem. Here is my annotation:

@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Key {
}


It's based on the example from documentation
  1. @Qualifier
  2. @Target(ElementType.TYPE)
  3. @Retention(RetentionPolicy.SOURCE)
  4. public @interface TitleTranslator {
  5. }

Changing retention to CLASS solves the problem.  Do I need both SOURCE and CLASS or just CLASS?

When I tell the IDE to make the project (I know eclipse does this automatically, but intellij uses javac) after making changes the User or the UserDto class, the UserMapperImpl does not update. In this case I'm telling the IDE to compile only the UserMapper or UserMapperImpl. I have no problem with maven

<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.0.0.CR1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.0.0.CR1</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<target>1.7</target>
<source>1.7</source>
<annotationProcessors>
<annotationProcessor>org.mapstruct.ap.MappingProcessor</annotationProcessor>
</annotationProcessors>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
</plugins>
</build>

On the other hand, the maven plugin used in the documentation some times causes me problems with the IDE.
Reply all
Reply to author
Forward
0 new messages