Integration of Modelmapper with jOOQ

705 views
Skip to first unread message

Lukas Eder

unread,
Mar 7, 2013, 2:55:07 PM3/7/13
to model...@googlegroups.com
Hello,

I have recently been made aware of your library helping to automatically map between "similar" types in Java. I like where you're going, and I'm sure there is quite a bit of potential to add more sophistication to your mapping algorithms.

I'm the developer of jOOQ and more sophisticated mapping has been requested often on the jOOQ user group. I'm a bit reluctant to put more effort into that area myself, as mapping is not the core business in jOOQ. Instead, jOOQ knows a RecordMapper interface, which could be implemented by a jOOQ/ModelMapper integration. So, I have a couple of questions:

1. Can ModelMapper also map from arbitrary non-POJO types (e.g. jOOQ's Record, or java.util.Map) to object hierarchies? Do you have an example for that?
2. The ModelMapper examples contain *ToOne relations. Are *ToMany relations also supported? e.g. List<Order> Customer.orders;
3. Are you planning to implement some mapping strategies taking their information from JPA annotations (e.g. Table, Column, OneToMany, etc.)
4. Would you be interested in creating / maintaining a couple of shared examples that integrate our two tools?

Cheers
Lukas

Jonathan Halterman

unread,
Mar 8, 2013, 1:45:17 PM3/8/13
to model...@googlegroups.com
Hey Lukas - Responses inline below:


On Thursday, March 7, 2013 11:55:07 AM UTC-8, Lukas Eder wrote:
Hello,

I have recently been made aware of your library helping to automatically map between "similar" types in Java. I like where you're going, and I'm sure there is quite a bit of potential to add more sophistication to your mapping algorithms.

I hope so, and am always open to ideas.
 

I'm the developer of jOOQ and more sophisticated mapping has been requested often on the jOOQ user group. I'm a bit reluctant to put more effort into that area myself, as mapping is not the core business in jOOQ. Instead, jOOQ knows a RecordMapper interface, which could be implemented by a jOOQ/ModelMapper integration. So, I have a couple of questions:

1. Can ModelMapper also map from arbitrary non-POJO types (e.g. jOOQ's Record, or java.util.Map) to object hierarchies? Do you have an example for that?

I've had some requests around this in the past, but haven't spent much time thinking about it yet. I'm certainly open to this and potentially related issues such as how to map from any arbitrary model (Map of Maps, POJO graph, Record, Jackson JsonNode, etc.) to some other model. It's definitely a problem I'd be interested in tackling.
 
2. The ModelMapper examples contain *ToOne relations. Are *ToMany relations also supported? e.g. List<Order> Customer.orders;

If I understand your question I think you're referring to flattening and projection? ModelMapper certainly does both. It will happily map a property one level deep in a source object to some property 5 levels deep in a destination object, or visa versa, as long as it's considered a valid match. Let me know if this isn't what you meant.
 
3. Are you planning to implement some mapping strategies taking their information from JPA annotations (e.g. Table, Column, OneToMany, etc.)

No plans currently. If you have some thoughts on how this should look, feel free to post an issue on github.
 
4. Would you be interested in creating / maintaining a couple of shared examples that integrate our two tools?

Sure. I'm open to integration with any libraries where there's a good synergy. I maintain a few extensions that provide basic 3rd party integrations and am open to adding others.

Do you have an idea how you think this should work? It looks like jOOQ Records are flat (1 level deep) objects. So we could map them to POJOs that are also 1 level deep or we could project them to models that are a bit more complex. I think some work would need to be done in ModelMapper to support this, similar to what was mentioned for your question 1 above - we need to support mapping from arbitrary models. Any other thoughts?

Cheers,
Jonathan
 

Cheers
Lukas

Lukas Eder

unread,
Mar 16, 2013, 12:03:18 PM3/16/13
to model...@googlegroups.com
Hi Jonathan,

Sorry for my late reply. Somehow, Google Groups ate my subscription settings, so I didn't get any notification email. Responses inline:


Am Freitag, 8. März 2013 19:45:17 UTC+1 schrieb Jonathan Halterman:
Hey Lukas - Responses inline below:

On Thursday, March 7, 2013 11:55:07 AM UTC-8, Lukas Eder wrote:
Hello,

I have recently been made aware of your library helping to automatically map between "similar" types in Java. I like where you're going, and I'm sure there is quite a bit of potential to add more sophistication to your mapping algorithms.

I hope so, and am always open to ideas.
 

I'm the developer of jOOQ and more sophisticated mapping has been requested often on the jOOQ user group. I'm a bit reluctant to put more effort into that area myself, as mapping is not the core business in jOOQ. Instead, jOOQ knows a RecordMapper interface, which could be implemented by a jOOQ/ModelMapper integration. So, I have a couple of questions:

1. Can ModelMapper also map from arbitrary non-POJO types (e.g. jOOQ's Record, or java.util.Map) to object hierarchies? Do you have an example for that?

I've had some requests around this in the past, but haven't spent much time thinking about it yet. I'm certainly open to this and potentially related issues such as how to map from any arbitrary model (Map of Maps, POJO graph, Record, Jackson JsonNode, etc.) to some other model. It's definitely a problem I'd be interested in tackling.

Great! 

2. The ModelMapper examples contain *ToOne relations. Are *ToMany relations also supported? e.g. List<Order> Customer.orders;

If I understand your question I think you're referring to flattening and projection? ModelMapper certainly does both. It will happily map a property one level deep in a source object to some property 5 levels deep in a destination object, or visa versa, as long as it's considered a valid match. Let me know if this isn't what you meant.

This is precisely what I meant. It is the kind of mapping that I don't want to implement in jOOQ any time soon, so it would be nice to "delegate" the work to a mapping API such as yours.
  
3. Are you planning to implement some mapping strategies taking their information from JPA annotations (e.g. Table, Column, OneToMany, etc.)

No plans currently. If you have some thoughts on how this should look, feel free to post an issue on github.

OK, I will, some time in the next week. I'll describe how jOOQ currently uses JPA annotations. With ModelMapper being able to go several levels deep in a destination object, I'm sure that more powerful JPA annotation matching can be done in ModelMapper

4. Would you be interested in creating / maintaining a couple of shared examples that integrate our two tools?

Sure. I'm open to integration with any libraries where there's a good synergy. I maintain a few extensions that provide basic 3rd party integrations and am open to adding others.

Do you have an idea how you think this should work? It looks like jOOQ Records are flat (1 level deep) objects. So we could map them to POJOs that are also 1 level deep or we could project them to models that are a bit more complex. I think some work would need to be done in ModelMapper to support this, similar to what was mentioned for your question 1 above - we need to support mapping from arbitrary models. Any other thoughts?

That more or less describes it. jOOQ Records are like Maps (Map<Field<?>, ?>). They can be mapped onto "flat" (1 level deep) POJOs using jOOQ. The contract is described here:

So, any integration could either depart from that "flat" POJO, or directly from the map. I think that ModelMapper would generally profit if Map->POJO mappings were supported "out of the box". So, if Map->POJO mapping is implemented, an "official" integration would be very simple

Cheers
Lukas

Jonathan Halterman

unread,
Mar 16, 2013, 1:02:26 PM3/16/13
to model...@googlegroups.com
Excellent - I started work on mapping from non-bean sources the other day and will see where that takes me. 

One of ModelMapper's core abstractions is a TypeMap which describes how two types map to each other. Ex: TypeMap<Person, PersonDTO>. If we're mapping Record to PersonDTO then the TypeMap would be TypeMap<Record, PersonDTO>. This could be problematic though since different Records could contain different values that should map to PersonDTO in different ways. So having a single TypeMap describing how a Record type maps to a PersonDTO type could be inadequate. Do you think this would be a problem for your users?

In that case I could add support for named TypeMaps, where TypeMaps can be given an optional name which disambiguates them from each other. Ex:

modelMapper.createTypeMap(Record.class, PersonDTO.class, "personHistory");
modelMapper.createTypeMap(Record.class, PersonDTO.class, "personDetails");

or

PersonDTO dto = modelMapper.map(record, PersonDTO.class, "personHistory");

I'm interested in your thoughts.

Cheers,
Jonathan
 

Cheers
Lukas
 

Lukas Eder

unread,
Mar 22, 2013, 7:26:42 AM3/22/13
to model...@googlegroups.com
Great. Looking forward to see first results.
 
One of ModelMapper's core abstractions is a TypeMap which describes how two types map to each other. Ex: TypeMap<Person, PersonDTO>. If we're mapping Record to PersonDTO then the TypeMap would be TypeMap<Record, PersonDTO>. This could be problematic though since different Records could contain different values that should map to PersonDTO in different ways. So having a single TypeMap describing how a Record type maps to a PersonDTO type could be inadequate. Do you think this would be a problem for your users?

In that case I could add support for named TypeMaps, where TypeMaps can be given an optional name which disambiguates them from each other. Ex:

modelMapper.createTypeMap(Record.class, PersonDTO.class, "personHistory");
modelMapper.createTypeMap(Record.class, PersonDTO.class, "personDetails");

or

PersonDTO dto = modelMapper.map(record, PersonDTO.class, "personHistory");

I'm interested in your thoughts.

I'm not sure if a "static" type mapping from "generic" types (such as org.jooq.Record / java.util.Map) to "specific" types (such as PersonDTO) makes general sense. Of course, internally, you may wish to use such utilities, but I'm not sure if users should register such mappings. Specifically, in the case of a java.util.Map, due to the lack of reified generics in Java, you have no way of predicting what's in the Map. In other words, you will need to discover the "generic type" structure on-the-fly

As you've mentioned yourself, you have also no way of telling what kinds of table expressions (e.g. joins) were used to produce a jOOQ Record.

Supporting "generic" Map types is a challenging task :-)

Jonathan Halterman

unread,
Mar 27, 2013, 8:25:56 PM3/27/13
to model...@googlegroups.com
Thanks for the feedback. You're right on about that. It looks like I'll definitely need named TypeMaps then so different Map -> Record mappings can be differentiated. Hopefully I get some time to work on this soon. Will keep you posted.

- Jonathan

Jonathan Halterman

unread,
Jul 16, 2013, 1:20:27 PM7/16/13
to model...@googlegroups.com
@Lukas:

I just pushed a branch I'm working on that provides an SPI for integrating ModelMapper with 3rd part data sources such as jOOQ. Have a look at the test. You can see that we can use the RecordValueReader to project flat record values into a deep model.

I've also introduced named TypeMaps, which allow for mapping information between two types such as Record and Order to be disambiguated if you have different records that you want to map into an order. Since Record is a "generic type", the TypeMap name provides for disambiguation.

What do you think of how this looks?

- Jonathan

Lukas Eder

unread,
Jul 16, 2013, 2:42:45 PM7/16/13
to model...@googlegroups.com
Hi Jonathan,

Thanks for getting back in touch regarding this integration. I'm currently on vacation, but I'll happily take a look next week

Cheers
Lukas


2013/7/16 Jonathan Halterman <jhalt...@gmail.com>
--
You received this message because you are subscribed to a topic in the Google Groups "modelmapper" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/modelmapper/TYpnSzS-0EY/unsubscribe.

To unsubscribe from this group and all its topics, send an email to modelmapper...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Jonathan Halterman

unread,
Jul 24, 2013, 1:58:32 PM7/24/13
to model...@googlegroups.com
Sounds good. I'm close to cutting a release to include these integrations, but I'd like to get your input to see if things make sense to you.

Jonathan

Lukas Eder

unread,
Jul 26, 2013, 3:50:39 AM7/26/13
to model...@googlegroups.com
Hi Jonathan,

2013/7/16 Jonathan Halterman <jhalt...@gmail.com>
@Lukas:

I just pushed a branch I'm working on that provides an SPI for integrating ModelMapper with 3rd part data sources such as jOOQ. Have a look at the test. You can see that we can use the RecordValueReader to project flat record values into a deep model.

That integration makes sense in my opinion. At first, I was thinking that maybe you could want to allow for RecordValueReader<R extends Record>, in order to be able to define more fine-grained record types. This might be useful if someone wants to override the get() method in the RecordValueReader. On the other hand, they can implement their own RecordValueReader, if they would find this additional typesafety useful...

So I think the current example is fine.

I've also introduced named TypeMaps, which allow for mapping information between two types such as Record and Order to be disambiguated if you have different records that you want to map into an order. Since Record is a "generic type", the TypeMap name provides for disambiguation.

That's great! I think that such an extension point will make the difference for more sophisticated use cases.

What do you think of how this looks?

Great! I think it's time for some community feedback! :-)
If you publish this with a couple of examples and if that's OK with you, I'll feature that publication and the examples on my blog (http://blog.jooq.org) which is syndicated on DZone. That might generate some traffic for ModelMapper in general.

Cheers
Lukas

Jonathan Halterman

unread,
Aug 3, 2013, 7:00:11 PM8/3/13
to model...@googlegroups.com
Hey Lukas,
I just pushed the ModelMapper 0.6.0 release which includes the new jOOQ integration. There's some basic documentation and examples on the website, though I'd be happy to add anything else that you might think might be useful

That would be awesome if you'd blog about the new integration! Traffic for ModelMapper is always good since I haven't really advertised much. Let me know if the current examples look good or if you need anything else from me for the blog post. Feel free to e-mail me directly.

Cheers,
Jonathan
 

Cheers
Lukas

Lukas Eder

unread,
Aug 6, 2013, 4:23:44 AM8/6/13
to model...@googlegroups.com
Hi Jonathan,


2013/8/4 Jonathan Halterman <jhalt...@gmail.com>

Hey Lukas,


On Friday, July 26, 2013 12:50:39 AM UTC-7, Lukas Eder wrote:
Hi Jonathan,

2013/7/16 Jonathan Halterman <jhalt...@gmail.com>
@Lukas:

I just pushed a branch I'm working on that provides an SPI for integrating ModelMapper with 3rd part data sources such as jOOQ. Have a look at the test. You can see that we can use the RecordValueReader to project flat record values into a deep model.

That integration makes sense in my opinion. At first, I was thinking that maybe you could want to allow for RecordValueReader<R extends Record>, in order to be able to define more fine-grained record types. This might be useful if someone wants to override the get() method in the RecordValueReader. On the other hand, they can implement their own RecordValueReader, if they would find this additional typesafety useful...

So I think the current example is fine.

I've also introduced named TypeMaps, which allow for mapping information between two types such as Record and Order to be disambiguated if you have different records that you want to map into an order. Since Record is a "generic type", the TypeMap name provides for disambiguation.

That's great! I think that such an extension point will make the difference for more sophisticated use cases.

What do you think of how this looks?

Great! I think it's time for some community feedback! :-)
If you publish this with a couple of examples and if that's OK with you, I'll feature that publication and the examples on my blog (http://blog.jooq.org) which is syndicated on DZone. That might generate some traffic for ModelMapper in general.

I just pushed the ModelMapper 0.6.0 release which includes the new jOOQ integration. There's some basic documentation and examples on the website, though I'd be happy to add anything else that you might think might be useful

I'll have a look right away.
 
That would be awesome if you'd blog about the new integration! Traffic for ModelMapper is always good since I haven't really advertised much. Let me know if the current examples look good or if you need anything else from me for the blog post. Feel free to e-mail me directly.

Thanks for your work. I'll write up a quick blog post. I'm sure it'll be syndicated to DZone. If you get really rich with ModelMapper, remember to also add a backlink to jOOQ ;-)

Cheers
Lukas
Reply all
Reply to author
Forward
0 new messages