2

I simply want to change the date format in my DTO returned by @ResponseBody

My question is not this question as my output is a JSON List and I am printing it on Postman instead of using a view with JS and other UI features.

It's not this one as well because I am returning a JSON List, not just the Date object.

It is an extension of this one, but I don't think Orika mapper is the culprit.

I am getting the timestamp value of date on returning the List using @ResponseBody.

My custom code-

@RequestMapping(value = "/my/report", method = RequestMethod.POST)
@ResponseBody
public List<OrderWsDTO> createReport() {
    //stuff
    return Optional.ofNullable(orderDataList)
            .orElse(Collections.emptyList())
            .stream()
            .map(orderData -> getDataMapper().map(orderData, OrderWsDTO.class, fields))
            .collect(Collectors.toList());
}

The mapper is: map:162, ConfigurableMapper (ma.glasnost.orika.impl)

Same issue with getDataMapper().mapAsList(orderDataList, OrderWsDTO.class, fields):

@RequestMapping(value = "/my/report", method = RequestMethod.POST)
@ResponseBody
public List<OrderWsDTO> createReport() {
    //stuff
    return getDataMapper().mapAsList(orderDataList, OrderWsDTO.class, fields);
}

OrderWsDTO is a DTO with getters and setters and a date field that is java.util.Date.

In postman I can see the date format as :
"date": "1552476861991"

The same exact call which returns OrderWsDTO instead of List<OrderWsDTO> changes the date format. It is printing the date as 2019-03-13T12:10:05+0000 which is format : yyy-MM-dd'T'HH:mm:ss.SSXXX

@RequestMapping(value = "/my/report", method = RequestMethod.POST)
@ResponseBody
public OrderWsDTO createReport() {
    //stuff
    return getDataMapper().map(orderData, OrderWsDTO.class, fields);
}


Why is the date showing two different formats when printed in List<DTO> and DTO?

Also, where is it getting the format : yyy-MM-dd'T'HH:mm:ss.SSXXX?


Edit 1:

The date is getting formatted here: de.hybris.platform.webservicescommons.jaxb.adapters.DateAdapter#marshal()
Format : yyyy-MM-dd'T'HH:mm:ssZ

Now, how to override this class?


Edit 2:

I am not able to override the jaxbContextFactory which has the list of adapters to modify the date. The jaxbContextFactory looks like-

<alias name="defaultJaxbContextFactory" alias="jaxbContextFactory"/>
<bean id="defaultJaxbContextFactory" class="de.hybris.platform.webservicescommons.jaxb.MoxyJaxbContextFactoryImpl">
    <property name="wrapCollections" value="${webservicescommons.messageconverters.context.wrapCollections}" />
    <property name="analysisDepth" value="${webservicescommons.messageconverters.context.analysisDepth}" />
    <property name="typeAdapters" ref="jaxbTypeAdaptersList" />
    <property name="subclassRegistry" ref="subclassRegistry" />
    <property name="otherClasses" ref="jaxbContextClasses" />
    <property name="metadataSourceFactory" ref="metadataSourceFactory" />
    <property name="excludeClasses"  ref ="jaxbContextFactoryExcludeClasses"/>
</bean>

On overriding this bean in my custom code it is still picking the old values for typeAdapters. Interestingly, it is replacing other properties with my custom properties.

My custom overridden bean-

<alias name="defaultJaxbContextFactory" alias="jaxbContextFactory"/>
<bean id="defaultJaxbContextFactory" class="de.hybris.platform.webservicescommons.jaxb.MoxyJaxbContextFactoryImpl">
    <property name="wrapCollections" value="false" />
    <property name="analysisDepth" value="30" />
    <property name="typeAdapters" ref="mylist" />
    <property name="subclassRegistry" ref="subclassRegistry" />
    <property name="otherClasses" ref="jaxbContextClasses" />
    <property name="metadataSourceFactory" ref="metadataSourceFactory" />
    <property name="excludeClasses"  ref ="jaxbContextFactoryExcludeClasses"/>
</bean>

<util:list id="mylist">
    <value>com.myproject.mymodule.myadapter</value>
    <value>de.hybris.platform.webservicescommons.jaxb.adapters.VariableMapAdapter</value>
    <value>de.hybris.platform.webservicescommons.jaxb.adapters.XSSStringAdapter</value>
</util:list>

For typeAdapters it is always picking the values-

<property name="typeAdapters">
        <list>
            <value>de.hybris.platform.webservicescommons.jaxb.adapters.DateAdapter</value>
            <value>de.hybris.platform.webservicescommons.jaxb.adapters.StringMapAdapter</value>
            <value>de.hybris.platform.webservicescommons.jaxb.adapters.XSSStringAdapter</value>
        </list>
    </property>

Edit 3:

I tried overriding the bean in mycustomaddon-web-spring.xml as -

<bean id="customJaxbContextFactory" parent="jaxbContextFactory">
    <property name="metadataSourceFactory" ref="customMetadataSourceFactory" />
    <property name="typeAdapters">
        <list>
            <value>myproject.adapters.DateAdapter</value>
            <value>de.hybris.platform.webservicescommons.jaxb.adapters.StringMapAdapter</value>
            <value>de.hybris.platform.webservicescommons.jaxb.adapters.XSSStringAdapter</value>
        </list>
    </property>
</bean>

I have added the custom adapter class i.e. myproject.adapters.DateAdapter in acceleratoraddon/web. Did not work out though.

Farrukh Chishti
  • 7,652
  • 10
  • 36
  • 60
  • 1
    The format you get is [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601). I don’t know how it came about, but it’s recommended to use it if you can. When you are on Java 8 or later, why are you using the long outdated and poorly designed `Date` class? You probably want `Instant` from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Mar 13 '19 at 12:55
  • 1
    @OleV.V. : Not an option. Both `OrderData` and `OrderWsDTO` are already defined in OTB code. – Farrukh Chishti Mar 13 '19 at 13:10
  • 1
    Orika is doing it's job successfully, I'd suggest you take a look at your JSON marshaller. Since you're using Spring, I'm going to take a guess that you're using Jackson. You will need to configure the format that you want. This link might help to get you started https://stackoverflow.com/q/4823358/1018903 && https://www.baeldung.com/jackson-serialize-dates – André Mar 14 '19 at 02:09

1 Answers1

1

The 'jaxbContextFactory' bean is first defined in the 'webservicescommons-spring.xml' which creates the bean in the application context. So when you override the bean in your custom extension using (customExtension)-spring.xml, it is just overriding the bean in the application context. More information about context loading in Hybris can be found here.

The typeAdapters property mentioned in your comments is defined in another bean which is defined in the 'jaxb-converters-spring.xml'

<bean id="customJaxbContextFactory" parent="jaxbContextFactory">
        <property name="metadataSourceFactory" ref="customMetadataSourceFactory" />
        <property name="typeAdapters">
            <list>
                <value>de.hybris.platform.webservicescommons.jaxb.adapters.DateAdapter</value>
                <value>de.hybris.platform.webservicescommons.jaxb.adapters.StringMapAdapter</value>
                <value>de.hybris.platform.webservicescommons.jaxb.adapters.XSSStringAdapter</value>
            </list>
        </property>
    </bean>

Since the beans defined in the jaxb-converters-spring-xml are loaded in the WebApplicationContext, you will need to override this bean using the (customExtension)-web-spring.xml where you can define the bean and corresponding class in the websrc of your custom extension.

Navish Sharma
  • 233
  • 2
  • 11
  • Did not work out. I copied the entire bean definition in my custom-web-spring.xml while replacing only the date adapter with my custom date adapter. My custom module is an addon so I have made the date adapter entry inside the : `myaddon/acceleratoraddon/web/src/com/myproject/myaddon/adapters/IndDateAdapter.java` – Farrukh Chishti Mar 16 '19 at 16:15
  • 1
    Is your add-on loaded correctly? Also can you check which date adapter is the groovy returning : spring.getBean("jaxbContextFactory").getTypeAdapters(); – Navish Sharma Mar 16 '19 at 17:22
  • Yes. I can hit the controllers declared in the addon. Also, I can see the custom date adapter getting copied in my original `webservicescomons`. Running the groovy and checking the bean value on debugging is giving the same value for OTB adapters not my custom one. If its not asking too much can you please try it in your codebase. You can check using any OTB, call that prints date, like: https://localhost:9002/customcommercewebservices/v2/basesite/orders/123?fields=FULL – Farrukh Chishti Mar 16 '19 at 18:29