经典服务器中的进度 REST PUT returns 错误
Progress REST PUT in classic server returns error
我有一个名为 Cities
的测试 table。创建脚本如下:
ADD TABLE "Cities"
AREA "Schema Area"
LABEL "Cities"
DUMP-NAME "Cities"
ADD FIELD "ID" OF "Cities" AS integer
DESCRIPTION "ID"
INITIAL 0
LABEL "ID"
COLUMN-LABEL "ID"
ORDER 10
ADD FIELD "City" OF "Cities" AS character
DESCRIPTION "City name"
FORMAT "x(30)"
INITIAL ""
LABEL "Cities"
MAX-WIDTH 30
COLUMN-LABEL "Cities"
ORDER 20
ADD INDEX "IxID" ON "Cities"
AREA "Schema Area"
UNIQUE
PRIMARY
INDEX-FIELD "ID" ASCENDING
.
PSC
cpstream=1250
.
0002253205
我已经添加了一条记录到这个table:
create Cities.
assign
Cities.ID = 1
Cities.City = "Boston".
FOR EACH
例程显示一条记录的正确结果。
我已经创建了一些具有经典服务器设置的 REST 项目,用于学习和测试目的。所有服务器和配置都是标准的,因为安装者配置了它们。
我已将一些程序添加到 AppServer 文件夹(文件:test.p)并在其中创建了 temp-table。完整程序代码:
BLOCK-LEVEL ON ERROR UNDO, THROW.
DEFINE TEMP-TABLE ttCities LIKE Cities.
@openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false").
PROCEDURE readCities:
DEFINE OUTPUT PARAMETER TABLE FOR ttCities.
FOR EACH Cities NO-LOCK:
CREATE ttCities.
BUFFER-COPY Cities TO ttCities.
END.
END PROCEDURE.
@openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false").
PROCEDURE putCities:
DEFINE INPUT-OUTPUT PARAMETER TABLE FOR ttCities.
END PROCEDURE.
程序编译良好,注释由 OpenEdge 中的 Define Service Interface
功能添加。
在 Defined Services
节点中,我为 putCities
和 PUT verb:
创建了参数映射(我将省略 readCities
因为它工作得很好)
- 资源:
/PutCities
- 动词关联:
Verb='PUT'
-> test..putCities
- 输入的映射定义:参数 ttCities 直接连接到请求
HTTP Message -> Body
部分(而不是主体参数)
- 输出的映射定义:响应 ttCities 连接到
Interface Parameters -> ttCities
我的客户端代码非常基础 - 取自一些 Progress KB 文章和项目有 OpenEdge.Net.pl
个包含在 PROPATH 中的库:
BLOCK-LEVEL ON ERROR UNDO, THROW.
USING Progress.Json.ObjectModel.JsonObject.
USING Progress.Json.ObjectModel.*.
USING Progress.Json.ObjectModel.ObjectModelParser.
USING Progress.Lang.Object.
USING OpenEdge.Core.WidgetHandle.
USING OpenEdge.Core.String.
USING OpenEdge.Net.HTTP.IHttpRequest.
USING OpenEdge.Net.HTTP.IHttpResponse.
USING OpenEdge.Net.HTTP.ClientBuilder.
USING OpenEdge.Net.HTTP.RequestBuilder.
DEFINE VARIABLE oRequest AS IHttpRequest NO-UNDO.
DEFINE VARIABLE oResponse AS IHttpResponse NO-UNDO.
DEFINE VARIABLE oEntity AS Object NO-UNDO.
DEFINE VARIABLE lcHTML AS LONGCHAR NO-UNDO.
DEFINE VARIABLE hXmlDoc AS HANDLE NO-UNDO.
DEFINE VARIABLE hCities AS HANDLE NO-UNDO.
DEFINE VARIABLE oJson AS JsonObject NO-UNDO.
DEFINE VARIABLE lReturnValue AS LOGICAL NO-UNDO.
DEFINE TEMP-TABLE ttCities LIKE Cities.
hCities = TEMP-TABLE ttCities:HANDLE.
create ttCities.
assign
ttCities.ID = 1
ttCities.City = "Boston".
oJson = NEW JsonObject().
lReturnValue = oJson:Read(hCities).
oRequest = RequestBuilder:Put('http://127.0.0.1:8980/REST6/rest/REST6/PutCities', oJson):Request.
oResponse = ClientBuilder:Build():Client:Execute(oRequest).
MESSAGE oResponse:StatusCode oResponse:StatusReason VIEW-AS ALERT-BOX.
/* some other code to parse response */
此代码编译良好,但调用它时出现以下错误:
Cities already exists with ID 1.
我想在服务器上调用了该过程,但由于此错误而无法更新数据库记录。据我所知,调用 PUT 方法应该对记录执行更新——而不是创建新的。此外,将 ttCities.ID
更改为值 2 会创建新记录。
所以我的问题很简单:如何处理这个?我应该在 putCities
过程中编写自己的自定义逻辑吗?
任何帮助将不胜感激。
我认为问题如下:
您创建了您的临时数据库 table "like" 您的数据库 table 因此它继承了唯一索引以及 table "Cities" 的友好名称.
您的 ReadCities 为每个数据库记录创建了一个临时 table 记录,因此我们有一个 ID 为 1 的记录。
虽然您的客户端代码创建了 ID 为 1 的临时 table 记录,但随后转到 ReadCities 代码并获取所有数据库记录,此时您会收到错误消息那里已经有 ID 为 1 的临时 table 记录。
您可能可以通过在代码中放置消息来确定收到错误的时间点来证明这一点。我想如果你在 "lReturnValue = oJson:Read(hCities)." 之前放一条消息,在它之后放一条消息,那么你会在错误之前收到第一条消息。
我有一个名为 Cities
的测试 table。创建脚本如下:
ADD TABLE "Cities"
AREA "Schema Area"
LABEL "Cities"
DUMP-NAME "Cities"
ADD FIELD "ID" OF "Cities" AS integer
DESCRIPTION "ID"
INITIAL 0
LABEL "ID"
COLUMN-LABEL "ID"
ORDER 10
ADD FIELD "City" OF "Cities" AS character
DESCRIPTION "City name"
FORMAT "x(30)"
INITIAL ""
LABEL "Cities"
MAX-WIDTH 30
COLUMN-LABEL "Cities"
ORDER 20
ADD INDEX "IxID" ON "Cities"
AREA "Schema Area"
UNIQUE
PRIMARY
INDEX-FIELD "ID" ASCENDING
.
PSC
cpstream=1250
.
0002253205
我已经添加了一条记录到这个table:
create Cities.
assign
Cities.ID = 1
Cities.City = "Boston".
FOR EACH
例程显示一条记录的正确结果。
我已经创建了一些具有经典服务器设置的 REST 项目,用于学习和测试目的。所有服务器和配置都是标准的,因为安装者配置了它们。 我已将一些程序添加到 AppServer 文件夹(文件:test.p)并在其中创建了 temp-table。完整程序代码:
BLOCK-LEVEL ON ERROR UNDO, THROW.
DEFINE TEMP-TABLE ttCities LIKE Cities.
@openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false").
PROCEDURE readCities:
DEFINE OUTPUT PARAMETER TABLE FOR ttCities.
FOR EACH Cities NO-LOCK:
CREATE ttCities.
BUFFER-COPY Cities TO ttCities.
END.
END PROCEDURE.
@openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false").
PROCEDURE putCities:
DEFINE INPUT-OUTPUT PARAMETER TABLE FOR ttCities.
END PROCEDURE.
程序编译良好,注释由 OpenEdge 中的 Define Service Interface
功能添加。
在 Defined Services
节点中,我为 putCities
和 PUT verb:
readCities
因为它工作得很好)
- 资源:
/PutCities
- 动词关联:
Verb='PUT'
-> test..putCities - 输入的映射定义:参数 ttCities 直接连接到请求
HTTP Message -> Body
部分(而不是主体参数) - 输出的映射定义:响应 ttCities 连接到
Interface Parameters -> ttCities
我的客户端代码非常基础 - 取自一些 Progress KB 文章和项目有 OpenEdge.Net.pl
个包含在 PROPATH 中的库:
BLOCK-LEVEL ON ERROR UNDO, THROW.
USING Progress.Json.ObjectModel.JsonObject.
USING Progress.Json.ObjectModel.*.
USING Progress.Json.ObjectModel.ObjectModelParser.
USING Progress.Lang.Object.
USING OpenEdge.Core.WidgetHandle.
USING OpenEdge.Core.String.
USING OpenEdge.Net.HTTP.IHttpRequest.
USING OpenEdge.Net.HTTP.IHttpResponse.
USING OpenEdge.Net.HTTP.ClientBuilder.
USING OpenEdge.Net.HTTP.RequestBuilder.
DEFINE VARIABLE oRequest AS IHttpRequest NO-UNDO.
DEFINE VARIABLE oResponse AS IHttpResponse NO-UNDO.
DEFINE VARIABLE oEntity AS Object NO-UNDO.
DEFINE VARIABLE lcHTML AS LONGCHAR NO-UNDO.
DEFINE VARIABLE hXmlDoc AS HANDLE NO-UNDO.
DEFINE VARIABLE hCities AS HANDLE NO-UNDO.
DEFINE VARIABLE oJson AS JsonObject NO-UNDO.
DEFINE VARIABLE lReturnValue AS LOGICAL NO-UNDO.
DEFINE TEMP-TABLE ttCities LIKE Cities.
hCities = TEMP-TABLE ttCities:HANDLE.
create ttCities.
assign
ttCities.ID = 1
ttCities.City = "Boston".
oJson = NEW JsonObject().
lReturnValue = oJson:Read(hCities).
oRequest = RequestBuilder:Put('http://127.0.0.1:8980/REST6/rest/REST6/PutCities', oJson):Request.
oResponse = ClientBuilder:Build():Client:Execute(oRequest).
MESSAGE oResponse:StatusCode oResponse:StatusReason VIEW-AS ALERT-BOX.
/* some other code to parse response */
此代码编译良好,但调用它时出现以下错误:
Cities already exists with ID 1.
我想在服务器上调用了该过程,但由于此错误而无法更新数据库记录。据我所知,调用 PUT 方法应该对记录执行更新——而不是创建新的。此外,将 ttCities.ID
更改为值 2 会创建新记录。
所以我的问题很简单:如何处理这个?我应该在 putCities
过程中编写自己的自定义逻辑吗?
任何帮助将不胜感激。
我认为问题如下:
您创建了您的临时数据库 table "like" 您的数据库 table 因此它继承了唯一索引以及 table "Cities" 的友好名称. 您的 ReadCities 为每个数据库记录创建了一个临时 table 记录,因此我们有一个 ID 为 1 的记录。
虽然您的客户端代码创建了 ID 为 1 的临时 table 记录,但随后转到 ReadCities 代码并获取所有数据库记录,此时您会收到错误消息那里已经有 ID 为 1 的临时 table 记录。
您可能可以通过在代码中放置消息来确定收到错误的时间点来证明这一点。我想如果你在 "lReturnValue = oJson:Read(hCities)." 之前放一条消息,在它之后放一条消息,那么你会在错误之前收到第一条消息。