I developed a Business Network Definition with Hyperledger Composer, deployed it on a Hyperledger Fabric example-chain (running locally on a VirtualBox-installation of Ubuntu with Docker-containers) and started Composer's REST-server with composer-rest-server (and options -c [cardname] -n always -w true). Then I played a bit in the browser and all is working fine.
Now comes the problematic bit: I want to write a Java-program interacting with this REST API and somehow the API seems unable to parse my Java-sent requests. I copied the JSON-string that Java produces to the browser, ran it there and it worked fine. But if I send it programmatically I get the error (see at the end).
This is what I send through the browser
{"cId":"C_ID7","cDomain":"example.com"}
The browser tells me with CURL it should look like this
curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{"cId":"C_ID7","cDomain":"example.com"}' 'http://localhost:3000/api/com.example.Company'
Now I want to send the same message through Java+JSOUP with the following code:
Response resp = Jsoup.connect(baseURL + namespace + "Company").ignoreContentType(true).method(Method.POST)
.ignoreHttpErrors(true)
.requestBody("{\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}").execute();
The same (without the requestBody and Method.GET) works for GET-requests. ignoreContentType(true) is necessary, because JSOUP will not handle 'application/json', see here. ignoreHttpErrors(true) is necessary, to get through the Http 500 error, which conceals the true error, which I need for trouble-shooting.
So then finally what I see, when I execute the above code, is the following error:
{"error":{"statusCode":500,"name":"Error","message":"Property names containing dot(s) are not supported. Model: com_example_Company, dynamic property: {\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}","stack":"Error: Property names containing dot(s) are not supported. Model: com_example_Company, dynamic property: {\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"}\n at com_example_Company.ModelBaseClass._initProperties
(/home/[user]
]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model.js:249:17)\n
at com_example_Company.ModelBaseClass (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model.js:60:8)\n
at com_example_Company.Model (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at com_example_Company.PersistedModel (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at new com_example_Company (eval at createModelClassCtor
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/model-builder.js:671:21), <anonymous>:12:24)\n
at Function.DataAccessObject.create (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:359:13)\n
at SharedMethod.invoke
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/shared-method.js:270:25)\n
at HttpContext.invoke (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/http-context.js:297:12)\n
at phaseInvoke (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/lib/remote-objects.js:676:9)\n at runHandler
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/lib/phase.js:135:5)\n
at iterate (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:146:13)\n
at Object.async.eachSeries
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:162:9)\n
at runHandlers (/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/lib/phase.js:144:13)\n
at iterate
(/home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:146:13)\n
at /home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:157:25\n
at /home/[user]/.nvm/versions/node/v8.9.4/lib/node_modules/composer-rest-server/node_modules/strong-remoting/node_modules/loopback-phase/node_modules/async/lib/async.js:154:25"}}
where obviously [user] is my username. So I had a look at the loopback-datasource-juggler sources and found that in model-builder.js (source on Github) instead of parsing the different properties of the string, it is given the complete string ("{\"cId\":\"C_ID7\",\"cDomain\":\"example.com\"). In line 269 the builder checks whether there are dot-characters in the property-name. Since in our case the property name is the complete JSON-string, there are dots and the program fails.
Unfortunately XML does not seem to be supported at this point.
Now: How can this happen? My only guess is an encoding thing done by Java, because the same JSON works in the browser. Any ideas what could have caused this?
And one smaller issue: The error message in the code is ''Property names containing dot(s) are not supported. ' + 'Model: %s, property: %s'', but in the error I receive it says something about "dynamic property". Am I at the wrong point for searching what causes the error?
com_example_Companyinstance is not valid. Details:cIdcan't be blank (value: undefined);cDomaincan't be blank (value: undefined).","details":{"context":"com_example_Company","codes":{"cId":["presence"],"cDomain":["presence"]}, ...." - Bat