Mapping of XMLGregorianCalendar to java.util.Date

1,736 views
Skip to first unread message

jms

unread,
Oct 31, 2012, 5:19:40 AM10/31/12
to model...@googlegroups.com
Hi,

First of all, I am just starting to use modelmapper. 

1) MemberDetails.java ( This class was generated from WSDL via wsimport ). This is the source. It has a few properties but the one I am having problems with is the property of type XMLGregorianCalendar, as below:

public class MemberDetails {

    @XmlSchemaType(name = "date")
    protected XMLGregorianCalendar birthDate;

    public XMLGregorianCalendar getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(XMLGregorianCalendar value) {
        this.birthDate = value;
    }

}

2) MemberDTO.java. This is the destination:

@ManagedBean
@ViewScoped
public class MemberDTO {

public Date birthDate;

public Date getBirthDate() {
return birthDate;
}

public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}

}



A) If I do the following:

ModelMapper mapper = new ModelMapper();
member = mapper.map(memberDetails, MemberDTO.class);

I get:

1) Converter org.modelmapper.internal.converter.NumberConverter@1892c59 failed to convert javax.xml.datatype.XMLGregorianCalendar to int.

1 error
at org.modelmapper.internal.Errors.throwMappingExceptionIfErrorsExist(Errors.java:338)
at org.modelmapper.internal.MappingEngineImpl.map(MappingEngineImpl.java:77)
at org.modelmapper.ModelMapper.map(ModelMapper.java:185)
at au.aas.com.bpm.insurance.InsuranceCase.retrieveMemberDetails(InsuranceCase.java:157)
at au.aas.com.bpm.insurance.InsuranceCase.main(InsuranceCase.java:164)
Caused by: org.modelmapper.MappingException: ModelMapper mapping errors:

1) Error mapping 1970-05-31+10:00 to java.lang.Integer


It seems to be mapping the source property MemberDetails.birthDate to the destination property MemberDTO.birthDate.date, which is not what I was expecting ( notice the extra .date ). I was expecting it to map the source property MemberDetails.birthDate to the destination property MemberDTO.birthDate.


B) So I created a new Map:

public class MemberMap extends PropertyMap<MemberDetails, MemberDTO> {
@Override
protected void configure() {
map().setBirthDate(source.getBirthDate().toGregorianCalendar().getTime());
}
}


.. and now the following code:

ModelMapper mapper = new ModelMapper();
mapper.addMappings(new MemberMap());
member = mapper.map(memberDetails, MemberDTO.class);

.. results in:

Exception in thread "main" org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) Invalid source method java.util.Calendar.setTimeInMillis(). Ensure that method has zero parameters and does not return void.

1 error
at org.modelmapper.internal.Errors.throwConfigurationExceptionIfErrorsExist(Errors.java:224)
at org.modelmapper.internal.MappingBuilderImpl.build(MappingBuilderImpl.java:138)
at org.modelmapper.internal.TypeMapImpl.addMappings(TypeMapImpl.java:66)
at org.modelmapper.internal.TypeMapStore.getOrCreate(TypeMapStore.java:93)
at org.modelmapper.ModelMapper.addMappings(ModelMapper.java:90)


C) I can use the STRICT matching strategy, but then I loose the matching for the other properties which was working with the STANDARD matching strategy.

D) I have also tried adding a converter to the mapper:

ModelMapper mapper = new ModelMapper();
mapper.addConverter(new XMLGregorianCalendarToDateConverter());

.. but that did not work as well as it thinks that the source MemberDetails.birthDate matches to the destination MemberDTO.birthDate.date, as per [A].


Any ideas ?

Thanks.

Michał Sładek

unread,
Nov 1, 2012, 5:12:22 PM11/1/12
to model...@googlegroups.com
Hi,

I'm telling WSIMPORT to convert the XMLGregorianCalendar to joda.DateTime objects when generating the java classes (you can do this over the bindings.xml). Or if you wish you can convert directly to Date, but in my opinion joda.DateTime is more comfortable to use and is very well mapped with modelmapper.
Good luck with your mappings. Hope this will help you a bit.

Best regards,
Michal

Jonathan Halterman

unread,
Nov 2, 2012, 6:30:47 PM11/2/12
to model...@googlegroups.com
The reason that ModelMapper doesn't simply match getBirthDate to setBirthDate is that the types don't match, which as you saw is why source.birthDate is being matched to destination.birthDate.date. In that case the conversion that is attempted is String (toString) to int.

I'm mobile so I don't have a chance to try this at the moment, but you should be able to do something like what you were doing with option B and D combined, with a small change:

  map(source.getBirthDate()).setBirthDate(null);

...

  mapper.addConverter(new XMLGregorianCalendarToDateConverter());

Here we're forcing destination.birthDate to be mapped from source.birthDate. The type conversion should then be handled by the converter. As an alternative we can specify that the converter be used just for this one property:

  using(XMLGregorianCalendarToDateConverter()).map(source.getBirthDate()).setBirthDate(null);

Something like that should probably work. 

Cheers,
Jonathan

JW

unread,
Nov 19, 2012, 6:07:56 PM11/19/12
to model...@googlegroups.com
Hi,

I'm in similar situation as the original poster.  I have a ThingDTO with 20 java.util.Date fields and a InternalThing with 20 XMLGregorianCalendar fields. 

How can I convert ThingDTO to InternalThing without having to write:

public class ThingMap extends PropertyMap<ThingDTO, Thing> {
@Override
protected void configure() {
map(source.getDateOne()).setDateOne(null);
map(source.getDateTwo()).setDateTwo(null);
....
                map(source.getDateTwenty()).setDateTwenty(null);
}
}

In other words, I'd like to convert all java.util.Date fields to their corresponding XMLGregorianCalendar fields using the same converter -- without having to list every field explicitly.

Thanks!

Jonathan Halterman

unread,
Nov 19, 2012, 6:59:31 PM11/19/12
to model...@googlegroups.com
I'd actually like to add proper support for mapping to and from Dates and GregorianCalendars so that no custom conversion is required. I'll get that in within the next day or two:

https://github.com/jhalterman/modelmapper/issues/21

Aside from that there is an issue right now that prevents a custom converter (such as Date->XmlGregorianCalendar) from always being applied to properties within a different TypeMap. I intend to have this fixed shortly (hopefully today).

Cheers,
Jonathan

Jonathan Halterman

unread,
Nov 20, 2012, 4:41:36 PM11/20/12
to model...@googlegroups.com
FYI - I just pushed built-in support for XMLGregorianCalendar. If, as you were wondering, you wanted a particular type conversion to apply for several properties without having to creating mappings for each one, you would just specify a custom converter:

mapper.addConverter(new SomeCalendarToDateConverter());

...and properties will be mapped between other types using that Converter as needed.

Cheers,
Jonathan

On Monday, November 19, 2012 3:07:56 PM UTC-8, JW wrote:
Reply all
Reply to author
Forward
0 new messages