6

I have a DXA 2.0 webapp with Web 8.5 working without issues. I am trying to build a REST API in DXA to spit out JSON content of a DCP. I'm able to use the Broker API (ComponentPresentationFactory) to get the content without issues. I'm having issues when I use DXA API to get the DCPs. So in the AdminController, I have two GET requests created. One returns the index page model without any errors.

@GetMapping(value = "/getpagemodel")
public @ResponseBody PageModel getPageModel() throws Exception {    
    PageModel pageModel = contentProvider.getPageModel("index", webRequestContext.getLocalization());
    return pageModel;
}

It's when I try and get an entity model, I'm seeing errors. It's able make a GET request to "http://localhost:8998/EntityModel/tcm/19/999-815", but fails when the mvc data is created. I don't see MvcData object in the JSON of the GET request. There is a NullPointerException in createMvcData.

@GetMapping(value = "/getentitymodel")
public @ResponseBody EntityModel getEntityModel() throws Exception { 
    // 999 is component item id and 815 is the component template item id   
    EntityModel entityModel = contentProvider.getEntityModel("999-815", webRequestContext.getLocalization());
    return entityModel;
}  

Logs when I try and get the entity model:

3:12:33.637 [http-nio-8080-exec-7] DEBUG o.s.web.client.RestTemplate - Created GET request for "http://localhost:8998/EntityModel/tcm/19/999-815" 23:12:33.637 [http-nio-8080-exec-7] DEBUG o.s.web.client.RestTemplate - Setting request Accept header to [application/json, application/*+json] 23:12:33.812 [http-nio-8080-exec-7] DEBUG o.s.web.client.RestTemplate - GET request for "http://localhost:8998/EntityModel/tcm/19/999-815" resulted in 200 (null) 23:12:33.827 [http-nio-8080-exec-7] DEBUG o.s.web.client.RestTemplate - Reading [class com.sdl.dxa.api.datamodel.model.EntityModelData] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@116eb89] 23:12:33.827 [http-nio-8080-exec-7] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [public java.lang.String com.sdl.dxa.controller.AdminController.getEntityModel() throws java.lang.Exception]: java.lang.NullPointerException 23:12:33.827 [http-nio-8080-exec-7] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [public java.lang.String com.sdl.dxa.controller.AdminController.getEntityModel() throws java.lang.Exception]: java.lang.NullPointerException 23:12:33.843 [http-nio-8080-exec-7] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [public java.lang.String com.sdl.dxa.controller.AdminController.getEntityModel() throws java.lang.Exception]: java.lang.NullPointerException 23:12:33.859 [http-nio-8080-exec-7] DEBUG o.s.web.servlet.DispatcherServlet - Could not complete request java.lang.NullPointerException: null at com.sdl.dxa.tridion.mapping.impl.DefaultModelBuilder.createMvcData(DefaultModelBuilder.java:141) at com.sdl.dxa.tridion.mapping.impl.DefaultModelBuilder.buildEntityModel(DefaultModelBuilder.java:109) at com.sdl.dxa.tridion.mapping.impl.ModelBuilderPipelineImpl.createEntityModel(ModelBuilderPipelineImpl.java:86) at

The output of the entity model request is below. The MvcData object isn't present so I guess when DXA tries to create the mvc data, a null pointer exception is thrown.

enter image description here

The output of the page model request is below.

enter image description here

So my question is:

  • How can I use ContentProvider to get the content of a DCP without registering a view model?

3 Answers 3

5

ContentProvider getEntityModel developed to work with MVC data. So it require registering view model. You can use dummy view to register your model.

In case you need full data which is returned by model service, you can write your custom provider by extending contentprovider. For reference you can check DefaultContentProvide code at https://github.com/sdl/dxa-web-application-java/blob/f341566cf51e1d3519f3c01b7d6e98dc21d076f6/dxa-framework/dxa-tridion-provider/src/main/java/com/sdl/dxa/tridion/mapping/impl/DefaultContentProvider.java.

3

I got this to work following Mukesh's suggestion. I updated the Component Template with a dummy Entity View Name 'Promo' as shown below.

enter image description here

In the SpringInitializer in the custom DXA module having the custom models, I registered the custom model of which I was trying to get the JSON content to the dummy view 'Promo' like this:

@RegisteredViewModels({
    @RegisteredViewModel(viewName = "Promo", modelClass = Promo.class),
}) 

I was then able to get the JSON content of the Component published as a DCP by casting the EntityModel to the custom model 'Promo' like this:

@GetMapping(value = "/getentitymodel")
public @ResponseBody Promo getEntityModel() throws Exception{    
    EntityModel entityModel = contentProvider.getEntityModel("2044-2045", webRequestContext.getLocalization());
    Promo promo = (Promo)entityModel;       
    return promo;
} 

The /getentity GET request was able to return the Component's content as a JSON shown below.

enter image description here

1
  • 1
    Thanks for the feedback. Please accept Mukesh’s Answer. Jan 8, 2019 at 18:37
1

I had a similar issue in DXA 2.2.9 .NET and followed the @Mukesh answer and did update the Component Template (DCP) with a dummy Entity View Name and registered in the web app module. Even after this change still no luck.

Further investigation and found that GetEntity GraphQL data response missing the MvcData in the DXA R2 JSON. Further DXA TBB Framework investigation found that It only expands if we enable IncludeComponentTemplateData property to true in the TBB. So make sure this property parameter should be enabled in the DCP template.

 <includeComponentTemplateData>true</includeComponentTemplateData>

.NET Example API Controller to get the DCP Entity Models

namespace Sdl.Web.Modules.Core.Controllers
{
    public class APIController : BaseController
    {
    
        public ActionResult GetDCPContent(string componentItemId, string templateItemId)
        {
            // The pageUrl parameter provided by ASP.NET MVC is relative to the Web App, but we need a server-relative (i.e. absolute) URL path.
            string absoluteUrlPath = Request.Url.AbsolutePath;

            using (new Tracer(componentItemId, absoluteUrlPath))
            {
                try
                {

                    EntityModel entityModel = ContentProvider.GetEntityModel($"{componentItemId}-{templateItemId}", WebRequestContext.Localization);

                    SetupViewData(entityModel);
                    EntityModel model = (EnrichModel(entityModel) as EntityModel) ?? entityModel;

                    MvcData mvcData = model.MvcData;

                    if (mvcData == null)
                    {
                        throw new DxaException($"Page Model [{model}] has no MVC data.");
                    }

                    Log.Debug("Api Request for URL path '{0}' maps to Model [{1}] with View '{2}'", absoluteUrlPath, model, model.MvcData.ViewName);

                    return View($"../{model.MvcData.ControllerName}/{model.MvcData.ViewName}", model);
                }
                catch (Exception ex)
                {
                    Log.Error(ex);
                    return ServerError();
                }

            }
        }

        public ActionResult ServerError()
        {
            using (new Tracer())
            {
                //For a server error, it may be that there is an issue with connectivity,
                //so we show a very plain page with no dependency on the Content Provider
                Response.StatusCode = 500;
                return View("ServerError");
            }
        }
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.