Use of generics in custom mapper

2,293 views
Skip to first unread message

Sjaak Derksen

unread,
Dec 12, 2013, 5:58:31 PM12/12/13
to mapstru...@googlegroups.com
Hi,

First of all: Thanks. This is really a good initiative. I like to have control and having the generated code available gives a lot more insight in what's happening than in competing (runtime frameworks).

One of the things I see a use case is the following: 

I'm trying to use Mapstruct to map JAXB generated java beans to DTO's. Because I need element properties on my JAXB mapping, I've included a global binding that generates wrappers (JAXBElement) around each generated JAXB class. So a source object would typically look like this:

public class JaxbSource 
{
private JAXBElement<String> test;

private JAXBElement<BigDecimal> test2;

And a target DTO like this:

public class TargetDto 
{
private String test;
private BigDecimal test2;

Now, ideally, I would like to have nested properties in my mapper (in the form of Mapping(source = "test.value" , target = "test")) as is addressed elsewhere already.

But instead, I chose to use a custom mapper.

@Mapper(uses =  JaxbMapper.class)
public interface Convertor {
TargetDto transform(JaxbSource survey);
}

Custom mapper:

public class JaxbMapper{

    public BigDecimal asBigDecimal(JAXBElement<BigDecimal> t)
{
return t.getValue();
}

    public String asString(JAXBElement<String> t)
{
return t.getValue();
}


}

The problem is that I keep on adding types (and I have a lot of them). I would rather make use of generics to solve this:

    public  <T> T getValue(JAXBElement<T> t)
{
return t.getValue();
}

Unfortunately, mapstruct does not support this. Instead, it fails:

diagnostic /Users/sjaak/Development/java/NetBeansProjects/ogc/MapStruct/src/main/java/com/mycompany/mapstruct/Convertor.java:8: error: Can't map property "javax.xml.bind.JAXBElement<java.lang.String> test" to "java.lang.String test".
TargetDto transform(JaxbSource survey);
         ^

Is it possible that mapstruct could support generics in this way in the future?

Best regards & many thanks,
Sjaak

Ps. I know that Dozer offers support for JAXB Ojbectfactories as well. That might be a good addition for the future as well.

Gunnar Morling

unread,
Dec 13, 2013, 5:08:55 AM12/13/13
to Sjaak Derksen, mapstru...@googlegroups.com
Hi Sjaak,


2013/12/12 Sjaak Derksen <jpam.d...@gmail.com>

Hi,

First of all: Thanks. This is really a good initiative. I like to have control and having the generated code available gives a lot more insight in what's happening than in competing (runtime frameworks).

Thanks, that's great to hear. If you like the project, please help and spread the word about MapStruct :)
 

One of the things I see a use case is the following: 

I'm trying to use Mapstruct to map JAXB generated java beans to DTO's. Because I need element properties on my JAXB mapping, I've included a global binding that generates wrappers (JAXBElement) around each generated JAXB class. So a source object would typically look like this:

public class JaxbSource 
{
private JAXBElement<String> test;

private JAXBElement<BigDecimal> test2;

And a target DTO like this:

public class TargetDto 
{
private String test;
private BigDecimal test2;

Now, ideally, I would like to have nested properties in my mapper (in the form of Mapping(source = "test.value" , target = "test")) as is addressed elsewhere already.

Yes, that's on our agenda for the near future (https://github.com/mapstruct/mapstruct/issues/65). 

But instead, I chose to use a custom mapper.

@Mapper(uses =  JaxbMapper.class)
public interface Convertor {
TargetDto transform(JaxbSource survey);
}

Custom mapper:

public class JaxbMapper{

    public BigDecimal asBigDecimal(JAXBElement<BigDecimal> t)
{
return t.getValue();
}

    public String asString(JAXBElement<String> t)
{
return t.getValue();
}


}

The problem is that I keep on adding types (and I have a lot of them). I would rather make use of generics to solve this:

    public  <T> T getValue(JAXBElement<T> t)
{
return t.getValue();
}

Unfortunately, mapstruct does not support this. Instead, it fails:

diagnostic /Users/sjaak/Development/java/NetBeansProjects/ogc/MapStruct/src/main/java/com/mycompany/mapstruct/Convertor.java:8: error: Can't map property "javax.xml.bind.JAXBElement<java.lang.String> test" to "java.lang.String test".
TargetDto transform(JaxbSource survey);
         ^

Is it possible that mapstruct could support generics in this way in the future?

Yes, absolutely. That should definitely work, could you please open an issue at https://github.com/mapstruct/mapstruct/issues/? Would you possibly be interested in providing a fix for this?
 

Best regards & many thanks,
Sjaak

Ps. I know that Dozer offers support for JAXB Ojbectfactories as well. That might be a good addition for the future as well.

Support for custom instantiation strategies has been a rather vague idea only so far, but JAXB seems a very reasonable use case for this. Could you open an issue for this as well? Wondering how this could be configured in a nice way.

Thanks for the nice feedback, Sjaak. If you have further ideas please make sure to let us know :)

--Gunnar


--
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/groups/opt_out.

Gunnar Morling

unread,
Dec 13, 2013, 5:11:44 AM12/13/13
to mapstru...@googlegroups.com
Hi Sjaak,


On Thursday, December 12, 2013 11:58:31 PM UTC+1, Sjaak Derksen wrote:
Hi,

First of all: Thanks. This is really a good initiative. I like to have control and having the generated code available gives a lot more insight in what's happening than in competing (runtime frameworks).

Thanks, that's great to hear. If you like the project, please help and spread the word about MapStruct :)
 
One of the things I see a use case is the following: 

I'm trying to use Mapstruct to map JAXB generated java beans to DTO's. Because I need element properties on my JAXB mapping, I've included a global binding that generates wrappers (JAXBElement) around each generated JAXB class. So a source object would typically look like this:

public class JaxbSource 
{
private JAXBElement<String> test;

private JAXBElement<BigDecimal> test2;

And a target DTO like this:

public class TargetDto 
{
private String test;
private BigDecimal test2;

Now, ideally, I would like to have nested properties in my mapper (in the form of Mapping(source = "test.value" , target = "test")) as is addressed elsewhere already.
Yes, that's on our agenda for the near future (https://github.com/mapstruct/mapstruct/issues/65). 
 
But instead, I chose to use a custom mapper.

@Mapper(uses =  JaxbMapper.class)
public interface Convertor {
TargetDto transform(JaxbSource survey);
}

Custom mapper:

public class JaxbMapper{

    public BigDecimal asBigDecimal(JAXBElement<BigDecimal> t)
{
return t.getValue();
}

    public String asString(JAXBElement<String> t)
{
return t.getValue();
}


}

The problem is that I keep on adding types (and I have a lot of them). I would rather make use of generics to solve this:

    public  <T> T getValue(JAXBElement<T> t)
{
return t.getValue();
}

Unfortunately, mapstruct does not support this. Instead, it fails:

diagnostic /Users/sjaak/Development/java/NetBeansProjects/ogc/MapStruct/src/main/java/com/mycompany/mapstruct/Convertor.java:8: error: Can't map property "javax.xml.bind.JAXBElement<java.lang.String> test" to "java.lang.String test".
TargetDto transform(JaxbSource survey);
         ^

Is it possible that mapstruct could support generics in this way in the future?
Yes, absolutely. That should definitely work, could you please open an issue at https://github.com/mapstruct/mapstruct/issues/? Would you possibly be interested in providing a fix for this?
 
Best regards & many thanks,
Sjaak

Ps. I know that Dozer offers support for JAXB Ojbectfactories as well. That might be a good addition for the future as well.

Sjaak Derksen

unread,
Dec 14, 2013, 3:55:50 AM12/14/13
to mapstru...@googlegroups.com
Hi Gunnar,

Thanks for your quick reaction. 

I'll open an issue as you suggested. Its some time ago that I wrote annotation processor  code, so I need to find my way around again :-). But, I'll have look and come back on this and see if I can help out and provide a usable fix. It will take some time though (some weeks).

Best regards,
Sjaak


Op donderdag 12 december 2013 23:58:31 UTC+1 schreef Sjaak Derksen:

Sjaak Derksen

unread,
Dec 28, 2013, 3:12:11 AM12/28/13
to mapstru...@googlegroups.com
Hi Gunnar,

I've spent some time on the issue and just checked in some code. Took me some time to get my Netbeans configured though (with Eclipse code formatter and check-style plugin). The solution makes the check in the MapCreationProcessor, method getMappingMethodReference a bit more accurate by introducing a MethodMatcher, which is in essence a visitor that check if the provided arguments and return type match the candidate methods. It takes the TypeParameters in the candidate method into consideration.

I've added unit test as well. It would be good to do a good check on my solution for the wild-cards. I'm always a bit struggling with the super / extends criteria.

Have a nice sylvester & good 2014,
Best regards,
Sjaak

Gunnar Morling

unread,
Dec 28, 2013, 5:09:48 PM12/28/13
to mapstru...@googlegroups.com
Hi Sjaak,

On Saturday, December 28, 2013 9:12:11 AM UTC+1, Sjaak Derksen wrote:
Hi Gunnar,

I've spent some time on the issue and just checked in some code. Took me some time to get my Netbeans configured though (with Eclipse code formatter and check-style plugin). The solution makes the check in the MapCreationProcessor, method getMappingMethodReference a bit more accurate by introducing a MethodMatcher, which is in essence a visitor that check if the provided arguments and return type match the candidate methods. It takes the TypeParameters in the candidate method into consideration.

That sounds great.

I've added unit test as well. It would be good to do a good check on my solution for the wild-cards. I'm always a bit struggling with the super / extends criteria.

Many thanks for taking a shot at this! I'd love to take a look at your change, where can I find it? Could you send a pull request for it via GitHub?
 
Have a nice sylvester & good 2014,

Thanks, you too. All the best for you for 2014!
 
Best regards,
Sjaak

--Gunnar
Reply all
Reply to author
Forward
0 new messages