问题: 我无法通过composer-rest-server生成的RESTful API发布事务。我收到statusCode 422;事务实例无效。但是,相同的示例适用于Playground。
情境: 我在我的.cto文件中设置了一个名为Offer的交易,该交易发布了买房的提议:
// Offer - Specifies an offer that a bidder places on a house listing with an associated price
transaction Offer {
o Double bidPrice
--> HouseListing listing
--> Person bidder
}
composer-rest-server生成了一个带有以下JSON字符串的API,用于发布Offer类型的事务:
{
"$class": "org.acme.purchasing.Offer",
"bidPrice": 0,
"listing": "string",
"bidder": "string",
"transactionId": "string",
"timestamp": "2017-07-21T13:37:09.460Z"
}
我已经使用以上示例派生的以下JSON代码将其替换为示例事务:
{
"$class": "org.acme.purchasing.Offer",
"bidPrice": 1000,
"listing": "001",
"bidder": "RJOHNSON",
"transactionId": "1b9aa63c-dfad-4aad-a610-dfc80f2796b2",
"timestamp": "2017-07-21T13:37:09.460Z"
}
返回的响应是错误代码422:
{
"error": {
"statusCode": 422,
"name": "ValidationError",
"message": "The `Offer` instance is not valid. Details: `transactionId` can't be set (value: \"1b9aa63c-dfad-4aad-a610-d...6b2\").",
"details": {
"context": "Offer",
"codes": {
"transactionId": [
"absence"
]
},
"messages": {
"transactionId": [
"can't be set"
]
}
},
"stack": "ValidationError: The `Offer` instance is not valid. Details: `transactionId` can't be set (value: \"1b9aa63c-dfad-4aad-a610-d...6b2\").\n at /usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:355:12\n at ModelConstructor.<anonymous> (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:566:11)\n at ModelConstructor.next (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/hooks.js:93:12)\n at ModelConstructor.<anonymous> (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:563:23)\n at ModelConstructor.trigger (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/hooks.js:83:12)\n at ModelConstructor.Validatable.isValid (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:529:8)\n at /usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:351:9\n at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:178:5)\n at Function.ObserverMixin.notifyObserversOf (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:153:8)\n at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:176:15)\n at Function.ObserverMixin.notifyObserversOf (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:153:8)\n at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:176:15)"
}
}
现在奇怪的是,我已经将相同的BNA部署到Hyperledger Composer Playground上,并且能够成功执行Offer类型的交易。
请注意,在Playground中,&#34; transactionId&#34;和&#34;时间戳&#34;未指定,因为Playground似乎处理这些值。例如,这就是Playground最初向我提出的建议:
{
"$class": "org.acme.purchasing.Offer",
"bidPrice": 0,
"listing": "resource:org.acme.purchasing.HouseListing#id:7965",
"bidder": "resource:org.acme.purchasing.Person#id:4441"
}
有人可以建议为什么它说Offer实例无效?我的第一个想法是,它不喜欢我放置在&#34; transactionId&#34;但是另一个Stack Overflow帖子指出transactionId只是我已经生成的任意UUIDv4字符串。
更新#1:默认演示失败
为了确保BNA没有错误,我已将默认的carauction-demo(与我的示例紧密相似)部署到我的本地Hyperledger Fabric实例上并部署了composer-rest-server。我还将相同的BNA部署到了游乐场。所有资产和参与者在Explorer(本地实例)和Playground中都创建了相同的内容。在提交要约交易时:
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 800,
"listing": "resource:org.acme.vehicle.auction.VehicleListing#L001",
"member": "resource:org.acme.vehicle.auction.Member#member3@acme.org"
}
这个JSON由Playground生成并在那里成功。复制/粘贴/执行到资源管理器会产生状态500错误。
{
"error": {
"statusCode": 500,
"name": "Error",
"message": "error trying invoke chaincode. Error: chaincode error (status: 500, message: Error: Object with ID 'string' in collection with ID 'Asset:org.acme.vehicle.auction.VehicleListing' does not exist)",
"stack": "Error: error trying invoke chaincode. Error: chaincode error (status: 500, message: Error: Object with ID 'string' in collection with ID 'Asset:org.acme.vehicle.auction.VehicleListing' does not exist)\n at _initializeChannel.then.then.then.then.catch (/usr/lib/node_modules/composer-rest-server/node_modules/composer-connector-hlfv1/lib/hlfconnection.js:806:34)"
}
}
我仍然迷失在这里的错误。
答案 0 :(得分:1)
经过多次实验和一些搜索,我得出结论,问题是NPM是使用sudo(作为root)安装的。我将安装重新编译为非root用户,问题现在已经解决了。一切都按预期工作。
答案 1 :(得分:0)
Composer将transactionId本身更新为生成的,您不能在JSON中执行此操作,因此会出现错误原因。这是一个Loopback - &gt; Swagger转换问题,因为它不应出现在/ POST REST操作中 - 在此处捕获https://github.com/hyperledger/composer/issues/663
答案 2 :(得分:0)
所以我已经成功执行了Offer事务(/ POST)。我认为&#39; 500&#39;错误是因为通过REST在您的商品交易中存在缺少字段(&#39;字符串&#39;类型)或关系。
的示例使用/ POST的这些商品交易中的任何一个在资源管理器中都是成功的:
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 20,
"listing": "org.acme.vehicle.auction.VehicleListing#100",
"member": "org.acme.vehicle.auction.Member#a@b.com"
}
OR
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 20,
"listing": "org.acme.vehicle.auction.VehicleListing#100",
"member": "org.acme.vehicle.auction.Member#a@b.com",
"timestamp": "2017-07-28T14:07:02.558Z"
}
在资源管理器中以200(SUCCESS)和transactionId响应:
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 20,
"listing": "org.acme.vehicle.auction.VehicleListing#100",
"member": "org.acme.vehicle.auction.Member#a@b.com",
"transactionId": "e75b9934-1f08-4daf-90db-702bbe4b8fa1"
}
这是上面#100的我的VehicleListing资产JSON
{
"$class": "org.acme.vehicle.auction.VehicleListing",
"listingId": "100",
"reservePrice": 50,
"description": "string",
"state": "FOR_SALE",
"offers": [
{
"$class": "org.acme.vehicle.auction.Offer",
"bidPrice": 50,
"listing": "100",
"member": "resource:org.acme.vehicle.auction.Member#a@b.com",
"transactionId": "string123",
"timestamp": "2017-07-28T14:07:02.825Z"
}
],
"vehicle": "resource:org.acme.vehicle.auction.Vehicle#123"
}
我为Vehicle 123以及会员a@b.com创建了资产