Search code examples
jsonxpagesibm-sbt

Xpages SBT <xe:restJsonData> & java.util.ArrayList incompatible with com.ibm.commons.util.io.json.JsonJavaObject


I'm trying to use the Endpoint functionality in SBT within XPages with a different rest service (to those in the examples). The authentication is working after a few tweaks (thanks Serdar!) but I wanted to mimic the StackOverflow example and use the response via a <xe:restJsonData> and repeat control.

Using the SO example as I starting point if I change the params to match my service I get this error...

Error while reading the JSON stream java.util.ArrayList incompatible with com.ibm.commons.util.io.json.JsonJavaObject

I'm guessing it's something to do with the splitpath as the resulting json doesn't have a common parent as such. Looks a bit like this (edited)...

[ { "user_id": 1688810, "space_id": null, "type": "user", "title": [ "Workflow Architect" ], "external_id": null, "last_seen_on": "2014-07-21 06:42:03", "name": "XXX XXX" }, { "user_id": 1998697, "name": "YYY YYY", "rights": [ "view" ], "external_id": null, "space_id": null, "title": [ "Owner" ], "org_id": null, "country": "United States", "type": "user", "last_seen_on": "2014-07-20 16:52:03", "location": [ "Amarillo" ] } ] I've tried a split path of blank or "/" but get the same error. I know the data is coming back as putting in a computed value of @Endpoint("podio").xhrGet("/contact/").getData(); shows it ok (raw)

Any ideas how I can split this result to work or is it fundamentally not possible with that object as the json is complex? Thanks!

Full stack trace...

com.ibm.xsp.FacesExceptionEx: Error while reading the JSON stream
at com.ibm.xsp.extlib.sbt.generic.GenericRestJsonDataSource$JsonAccessor.loadBlock(GenericRestJsonDataSource.java:137)
at com.ibm.xsp.extlib.model.DataBlockAccessor.findBlockByIndex(DataBlockAccessor.java:344)
at com.ibm.xsp.extlib.model.DataBlockAccessor.prefetchData(DataBlockAccessor.java:292)
at com.ibm.xsp.extlib.model.DataAccessorModel.getRowCount(DataAccessorModel.java:93)
at com.ibm.xsp.model.TabularDataModel.isRowAvailable(TabularDataModel.java:96)
at com.ibm.xsp.extlib.model.DataAccessorModel.isRowAvailable(DataAccessorModel.java:69)
at com.ibm.xsp.component.UIDataIterator.isRowAvailable(UIDataIterator.java:523)
at com.ibm.xsp.component.UIDataIterator.pushVars(UIDataIterator.java:504)
at com.ibm.xsp.component.UIDataIterator.setRowIndex(UIDataIterator.java:469)
at com.ibm.xsp.renderkit.html_extended.IteratorRenderer.encodeRows(IteratorRenderer.java:62)
at com.ibm.xsp.renderkit.html_extended.IteratorRenderer.encodeChildren(IteratorRenderer.java:55)
at com.ibm.xsp.renderkit.ReadOnlyAdapterRenderer.encodeChildren(ReadOnlyAdapterRenderer.java:162)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:979)
at com.ibm.xsp.component.UIDataIterator.encodeChildren(UIDataIterator.java:725)
at com.ibm.xsp.util.FacesUtil.renderComponent(FacesUtil.java:844)
at com.ibm.xsp.util.FacesUtil.renderComponent(FacesUtil.java:853)
at com.ibm.xsp.util.FacesUtil.renderComponent(FacesUtil.java:853)
at com.ibm.xsp.util.FacesUtil.renderComponent(FacesUtil.java:853)
at com.ibm.xsp.util.FacesUtil.renderComponent(FacesUtil.java:853)
at com.ibm.xsp.component.UIViewRootEx._renderView(UIViewRootEx.java:1317)
at com.ibm.xsp.component.UIViewRootEx.renderView(UIViewRootEx.java:1255)
at com.ibm.xsp.application.ViewHandlerExImpl.doRender(ViewHandlerExImpl.java:651)
at com.ibm.xsp.application.ViewHandlerExImpl._renderView(ViewHandlerExImpl.java:321)
at com.ibm.xsp.application.ViewHandlerExImpl.renderView(ViewHandlerExImpl.java:336)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:103)
at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:210)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:120)
at com.ibm.xsp.controller.FacesControllerImpl.render(FacesControllerImpl.java:270)
at com.ibm.xsp.webapp.FacesServlet.serviceView(FacesServlet.java:261)
at com.ibm.xsp.webapp.FacesServletEx.serviceView(FacesServletEx.java:157)
at com.ibm.xsp.webapp.FacesServlet.service(FacesServlet.java:160)
at com.ibm.xsp.webapp.FacesServletEx.service(FacesServletEx.java:138)
at com.ibm.xsp.webapp.DesignerFacesServlet.service(DesignerFacesServlet.java:103)
at com.ibm.designer.runtime.domino.adapter.ComponentModule.invokeServlet(ComponentModule.java:576)
at com.ibm.domino.xsp.module.nsf.NSFComponentModule.invokeServlet(NSFComponentModule.java:1315)
at com.ibm.designer.runtime.domino.adapter.ComponentModule$AdapterInvoker.invokeServlet(ComponentModule.java:853)
at com.ibm.designer.runtime.domino.adapter.ComponentModule$ServletInvoker.doService(ComponentModule.java:796)
at com.ibm.designer.runtime.domino.adapter.ComponentModule.doService(ComponentModule.java:565)
at com.ibm.domino.xsp.module.nsf.NSFComponentModule.doService(NSFComponentModule.java:1299)
at com.ibm.domino.xsp.module.nsf.NSFService.doServiceInternal(NSFService.java:662)
at com.ibm.domino.xsp.module.nsf.NSFService.doService(NSFService.java:482)
at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.doService(LCDEnvironment.java:350)
at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.service(LCDEnvironment.java:306)
at com.ibm.domino.xsp.bridge.http.engine.XspCmdManager.service(XspCmdManager.java:272)
Caused by: java.lang.ClassCastException: java.util.ArrayList incompatible with com.ibm.commons.util.io.json.JsonJavaObject
at com.ibm.xsp.extlib.sbt.generic.GenericRestJsonDataSource$JsonAccessor.loadBlock(GenericRestJsonDataSource.java:121)
... 43 more'

Solution

  • I have bumped the same problem before. That's an incapability of GenericRestJsonDataSource. If the remote service provides an array, instead of an object, the data from the client service returns an ArrayList of JsonJavaObject's.

    However it expects an JsonJavaObject that contains an ArrayList of JsonJavaObject's.

    That's why in the previous example of BaseCamp (at the linked question) I have designed an additional Java bean that pulls the data and maintains its own List structures. That also helped me a lot on caching.

    Your data should be in a format like:

    {
      items: [
         {
           prop: value, ....
         },
         {
           prop: value, ....
         }
      ]
    }
    

    Just like in the SO example. In this case splitPath should be items.

    That's an easy fix within the class in fact. The accessor class in the GenericRestJsonDataSource should be modified to check if the returning item is an ArrayList. However at the time, it seemed like a more convenient method to design my own Service bean.