Map Rest Connector Object Response into a Process Variable (complex Business Object with MULTIPLE Business OBject, including LISTs)

I am calling this service I've found in other examples https://www.metaweather.com/api/location/44418/, from a REST Connector out and it returns a complex structure.

All the examples I've found extract a single STRING from the complex structure (from bodyAsObject) without issues. I could do so also without any problem. 

But, when I try to map the full object to a process variable, I keep getting parsing or type error messages. Even if I only try to extract a List. In this example, let's say I need to extract bodyAsObject.sources.

In the BDM, I created a New Business Object called: 'TestService' that contains a variable called 'sources' that is Multiple of type source, where source is another Business Object that has 4 elements:

- title (STRING),

- slug (STRING),

- url (STRING)

- crawl_rate (STRING).

Then I created a process variable called testService of type com.company.model.TestService

Then in the REST Connector / Output operations, I configure:

testService - Use a Java method -  setSources(List<source>)

With the following script:

return bodyAsObject.sources

When I test it it returns an ArrayList. I tried many things to parse it and no one worked. When I run the process it fails on this Service Task.

Is there anything I am missing?

Thanks

Hi, You can write a script in the connector output that look like this:

//Returns a list of com.company.model.Source 
bodyAsObject.sources.collect{ 
    def source = new com.company.model.Source() 
    source.title = it.title 
    source.slug = it.slug 
    source.url = it.url 
    source.crawl_rate = it.crawl_rate 
    source
}

Be aware that Business Object should be used in Business variables and not in Process variables.

HTH
Romain

Edit: fix typo in script

Thanks for your answer. I tried this and, even though it is not erroring out, it is not returning the four attributes. It only returns the last one. In this case 'crawl_rate'. And it just returns a list of integers.

>(c) ArrayList<E> : [360,480,360,180,360,720,360]

If I change the order, say I leave title for the last one, it returns a list of strings, containing all the titles from the list.

I tried with all variables and all work the same way.It also works mapping the return to a business variable through the java method 'setSources()'.

I tried adding a line 'source' to return the full object. Having the following script:

bodyAsObject.sources.collect{
    def source = new com.company.model.Source()
    source.url = it.url
    source.slug = it.slug
    source.title = it.title
    source.crawl_rate = it.crawl_rate
    source
}

But then I'm back to my original issue returning complex objects:

java.lang.reflect.InvocationTargetException
org.bonitasoft.engine.exception.BonitaRuntimeException: Unable to deserialize object <object-stream>
  <map>
    <entry>
      <string>output0</string>
      <list>
        <com.company.model.Source>
          <title>BBC</title>
          <slug>bbc</slug>
          <url>http://www.bbc.co.uk/weather/</url>
          <crawl__rate>360</crawl__rate>
        </com.company.model.Source>
        <com.company.model.Source>
          <title>Forecast.io</title>
          <slug>forecast-io</slug>
          <url>http://forecast.io/</url>
          <crawl__rate>480</crawl__rate>
        </com.company.model.Source>
        <com.company.model.Source>
          <title>HAMweather</title>
          <slug>hamweather</slug>
          <url>http://www.hamweather.com/</url>
          <crawl__rate>360</crawl__rate>
        </com.company.model.Source>
        <com.company.model.Source>
          <title>Met Office</title>
          <slug>met-office</slug>
          <url>http://www.metoffice.gov.uk/</url>
          <crawl__rate>180</crawl__rate>
        </com.company.model.Source>
        <com.company.model.Source>
          <title>OpenWeatherMap</title>
          <slug>openweathermap</slug>
          <url>http://openweathermap.org/</url>
          <crawl__rate>360</crawl__rate>
        </com.company.model.Source>
        <com.company.model.Source>
          <title>Weather Underground</title>
          <slug>wunderground</slug>
          <url>https://www.wunderground.com/?apiref=fc30dc3cd224e19b</url>
          <crawl__rate>720</crawl__rate>
        </com.company.model.Source>
        <com.company.model.Source>
          <title>World Weather Online</title>
          <slug>world-weather-online</slug>
          <url>http://www.worldweatheronline.com/</url>
          <crawl__rate>360</crawl__rate>
        </com.company.model.Source>
      </list>
    </entry>
  </map>
</object-stream>
com.thoughtworks.xstream.converters.ConversionException:
---- Debugging information ----
cause-exception     : com.thoughtworks.xstream.mapper.CannotResolveClassException
cause-message       : com.company.model.Source
class               : java.util.ArrayList
required-type       : java.util.ArrayList
converter-type      : com.thoughtworks.xstream.converters.collections.CollectionConverter
path                : /map/entry/list/com.company.model.Source
line number         : 6
class[1]            : java.util.HashMap
converter-type[1]   : com.thoughtworks.xstream.converters.collections.MapConverter
version             : 1.4.10
-------------------------------
com.thoughtworks.xstream.mapper.CannotResolveClassException: com.company.model.Source

Full error here:https://www.heypasteit.com/clip/0IUTUS

I am testing it from the test button in the connector wizard.

For any List of Objects in the BDM, I try to return a List of the same objects in the Script of the connector and I keep getting this message.

I need to return these lists of objects to map them in the UI for both tables and select widgets. Is this the correct way to do so? Using a complex multiple variable in the BDM and trying to map it in the connector output wizard?

Is it possible to do what I am trying? Because it looks to me it should be done this way but Bonita is doing something extra in the engine.

Thanks for the help!

 

Even when I don't work with lists. Using the java method 'addToSources(Source)' and being the script:

def source = new com.company.model.Source()
source.url = "it.url"
source.slug = "it.slug"
source.title = "it.title"
source.crawl_rate = 1

return source

I am getting the "Unable to deserialize object" error

This is an issue only occurring using Test connector as the BDM jar is NOT in the classpath.
It will work properly in the process.

Generated bdm-pojo.jar should be suggested in classpath jar list when testing a connector.

It worked thanks!

Now I have:

- Source: {title, slug, url, crawl_rate}

- Sources: Source Multiple

- InfoTables: {Sources,...} // it contains many lists to be displayed in UI tables

I am mapping infoTables in a task contract but when I try to map it into a table in the UI using, as I do with JSON variables in the UI:

InfoTables.Sources

Is there an specific way to do it that I am missing?

I do not understand what you are trying to achieve. Can you be more specific ? If it is a question unrelated with REST connector output mapping, please open a new question.

I have 10 different lists of constant values to load in Select and table Widgets. I'd like to have just one variable in the contract for this purpose. I grouped all the lists in a single parent object. My BDM for an example looks like this

BDM Model Name Attrubute Name Type Multiple
InformationCombos

sources

		<p>List2</p>

		<p>...</p>

		<p>List10</p>
		</td>
		<td>
		<p>Sources</p>

		<p>Type2</p>

		<p>...</p>

		<p>Type10</p>
		</td>
		<td>No</td>
	</tr>
	<tr>
		<td>Sources</td>
		<td>source</td>
		<td>Source</td>
		<td>Yes</td>
	</tr>
	<tr>
		<td>Source</td>
		<td>
		<p>Key</p>

		<p>Value</p>
		</td>
		<td>
		<p>String</p>

		<p>String</p>
		</td>
		<td>No</td>
	</tr>
</tbody>

Then in the UI I try to reference this in the Available Values section of a Select Widget but I can't make it show. I tried many things but looks like I'm doing something wrong.

  • InformationCombos.Sources
  • InformationCombos.Sources.value
  • Used generated variable: InformationCombos_sources_source
  • ...

Nothing works.

My variable is an external API type:

informationCombos  ../{{context.informationCombos_ref.link}}

If the relation on your BusinessObject are lazy there are not loaded with the parent and an additional request must be performed.

Check the how to use the `lazyRef` filter in the doc.

Or you can use an eager (always load children values) relation if it suits your use case.

HTH

Romain