incodehq / incode-platform

Combines incode.org modules and isisaddons.org into a single set of modules.
http://platform.incode.org
Apache License 2.0
8 stars 9 forks source link

Customized ContentMappingService does not take effect #99

Closed sschong closed 5 years ago

sschong commented 5 years ago

Hi all,

I'm newly using Apache Isis and Incode Platform. I faced a strange issue with project extended from Incode Platform where I need to implement a customized ContentMappingService to provide a customized Dto JSON response to the client request.

Below are my codes to implement the customized ContentMappingService, however, Incode Platform seems only having ContentMappingServiceForCommandDto being picked up while my customized QBankContentMappingService did not being picked up by injected service thus the response JSON cannot be mapped correctly. This only happened when I deployed the WAR file to proper App Server like Standalone Tomcat/Jetty Server. If I run the project from Eclipse internal embedded Jetty Server, then the customized ContentMappingService is rendered correctly on the JSON response

It seems that the issue only happened to project extended from Incode Platform. If I'm using Apapche Isis original Simple App Archetype the Customized ContentMappingService would be picked up and rendered correctly.

Customized ContentMappingService Codes:

@DomainService(
        nature = NatureOfService.DOMAIN
)
public class ContentMappingServiceForQBank implements ContentMappingService {

    @Programmatic
    @Override
    public Object map(
            final Object object,
            final List<MediaType> acceptableMediaTypes) {
        System.out.println("mapping object: "+object);
        if(object instanceof QBank) {
            for (MediaType acceptableMediaType : acceptableMediaTypes) {
                final Map<String, String> parameters = acceptableMediaType.getParameters();
                final String className = parameters.get("x-ro-domain-type");
                System.out.println("mapping content");
                if(matches(className, QBankV1_0.class)) {
                    return newQBankV1_0((QBank) object);
                }
            }
        }else {
            return new QBankV1_0();
        }

        return new QBankV1_0();
    }
    @Inject
    QBanks qBanks;

    private static boolean matches(final String className,
            final Class<?>... classes){
         ......
    }

     @Programmatic
    public QBankV1_0 newQBankV1_0(final QBank qBank) {
          .....
    }
}

Result: Standalone Jetty Server Debug Console image

Postman response (when running with Standalone Jetty Server) image

Eclipse embedded Jetty server Debug Console (no issue when running via Eclipse) representation service contentNegotiationService: domainapp.modules.custom.service.QBanksContentNegotiationService@a46227 negotation service contentMappingService: domainapp.modules.custom.service.ContentMappingServiceForQBank@9469c9 domainObject: QBank acceptableMediaTypes: [application/json;profile="urn:org.restfulobjects:repr-types/object";x-ro-domain-type=domainapp.modules.custom.viewmodel.QBankV1_0] mapping object: QBank mapping content

Eclipse embedded Jetty server Postman Response (no issue when running via Eclipse) image

sschong commented 5 years ago

The issue had been resolved after investigated into log and debugging.

It seems that the below line of code is causing problem to the customized ContentMappingService which then causing ServiceInstantiator did not pick up the customized ContentMappingService. However, yet known to me why the behavior as such as no error is throwing and the code was working perfectly when running via Eclipse embedded Jetty.

List<String> nameList = new ArrayList<Answer>(qBank.getAnswerList().getAnswers()).stream().map(Answer::getName).collect(Collectors.toList());

This is confirmed by below logging:

With the above line of codes used 2018-11-27 23:13:26,488 [ServiceInstantiator main DEBUG] loading class for service: org.apache.isis.objectstore.jdo.datanucleus.service.eventbus.EventBusServiceJdo 2018-11-27 23:13:26,489 [ServiceInstantiator main DEBUG] loading class for service: domainapp.modules.base.service.AppUserRegistrationService 2018-11-27 23:13:26,490 [ServiceInstantiator main DEBUG] loading class for service: org.apache.isis.applib.services.queryresultscache.QueryResultsCache$Control

With the above line of codes being replaced/removed: 2018-11-27 23:17:47,705 [ServiceInstantiator main DEBUG] loading class for service: org.apache.isis.objectstore.jdo.datanucleus.service.eventbus.EventBusServiceJdo 2018-11-27 23:17:47,706 [ServiceInstantiator main DEBUG] loading class for service: domainapp.modules.base.service.AppUserRegistrationService 2018-11-27 23:17:47,707 [ServiceInstantiator main DEBUG] loading class for service: domainapp.modules.custom.service.ContentMappingServiceForQBank 2018-11-27 23:17:47,707 [ServiceInstantiator main DEBUG] loading class for service: org.apache.isis.applib.services.queryresultscache.QueryResultsCache$Control

danhaywood commented 5 years ago

Thanks for the detailed ticket. You say it's resolved so I'm going to close this ticket.

With respect to the issue, you mentioned something about it working on Eclipse embedded Jetty, and presumably not working in some other environment. That suggests to me this is some sort of classpath issue. Perhaps the presence of the line you quoted (List nameList=...) had something to do with this?

If you can provide an example application which demonstrates the problem, then I'll happily reopen.

Thx