Upload file to REST (Data Object WebSpeed service)

Posted by jts-law on 25-Jan-2018 10:46

We are using OE 11.7.2 on Windows 7 and Server 2012R2 (both 64 bit) and have a REST API using a Data Object WS service for a Kendo UI Builder app.

Our app needs to be able to upload a file for processing and I'm struggling to figure out how to implement this on the backend.  Since I'm not sure what the signature of the POST method should be, I've been trying different things and nothing works.  The latest trial is the following:

   @openapi.openedge.export(type="REST", useReturnValue="false", writeDataSetBeforeImage="false").
   @progress.service.resourceMapping(type="REST", operation="create", URI="", alias="", mediaType="application/octet-stream").
   METHOD PUBLIC VOID UploadAcctCat(INPUT mpEntity AS OpenEdge.Net.MultipartEntity):
      
      MESSAGE "Received " mpEntity:Size " parts".

/* Save contents to a temp file for processing... */
END METHOD. /* UploadAcctCat */

When my KUIB app tries calling this URI, I get the following in the oepas1.agent.log:

[18/01/25@09:31:41.622-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr [OE.W.DO.DOH.UI ERROR] Exception raised for POST localhost:8810/.../UploadProfitAcctCat; Entity=UploadProfitAcctCat_4126; Operation=OpenEdge.Web.DataObject.MappedOperation_3508: POST svc:UI v1.0.0 uri:UploadProfitAcctCat: type:Class ; name:Progress.Lang.Object, type-of:Progress.Lang.Object, fn:, numargs:3, num-schemas:0, name:
[18/01/25@09:31:41.622-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr Error(s) raised:
[18/01/25@09:31:41.622-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr Unsupported object type: OpenEdge.Net.MultipartEntity (0)
[18/01/25@09:31:41.653-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr [OE.W.DO.DOH.UI ERROR] Error writing exception
[18/01/25@09:31:41.653-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr Error(s) raised:
[18/01/25@09:31:41.653-0600] P-014160 T-013292 1 AS-9 LogMgrWrtr Unsupported object type: Progress.Lang.AppError (0)

Any thoughts on how to implement a file upload backend REST service?

Louis Winter

Posted by Peter Judge on 05-Feb-2018 08:42

Louis,
 
From the docs you linked, it looks like the operations (error/success) expect the same JSON responses
Event Data
e.files Array
 
Lists the files that were uploaded or removed.
 
Each file has:
 
    name
    extension - The file extension including the leading dot. For example, .jpg, .png, an so on.
    size - The file size in bytes. If not available, the value is null.
    uid - The unique identifier of the file or batch of files.
 
e.operation String
 
The upload or remove operation.
e.XMLHttpRequest Object
 
Represents either the original XHR that is used for the operation or a stub that contains:
 
    responseText
    status
    statusText
 
Before you access any other fields, verify that this is an actual XHR.
 
The docs aren’t clear on how you signal an error vs success (I’d think a status code). You can do this with a custom map file too.
 
You can build the whole JSON yourself (easiest for now, I think) by tweaking your method’s signature to be
  METHOD PUBLIC INTEGER UploadFile(INPUT mpEntity AS OpenEdge.Net.MultipartEntity,
                                   OUTPUT pResponse AS JsonObject):
 
And the mapping entry to
{
  "services": {
    "UI": {
      "version": "1.0.0",
      "operations": {
        "/UploadFile": {
          "POST": {
            "contentType": "application/json",
            "entity": {
              "name": "UploadFileClass",
              "function": "UploadFile",
              "arg": [
                {
                  "ablName": "",
                  "ablType": "INTEGER",
                  "ioMode": "RETURN",
                  "msgElem": {"type": "StatusCode", "name": null}
                },
                {
                  "ablName": "mpEntity",
                  "ablType": "CLASS OpenEdge.Net.MultipartEntity",
                  "ioMode": "INPUT",
                  "msgElem": {"type": "BODY", "name": null}
                },
                {
                  "ablName": "pData",
                  "ablType": "CLASS Progress.Json.ObjectModel.JsonObject",
                  "ioMode": "OUTPUT",
                  "msgElem": {"type": "BODY", "name": null}
                }
              ]
            }
          }
        }
      },
      "schemas": null
    }
  }
}
 
 
 
 
 

All Replies

Posted by Peter Judge on 29-Jan-2018 15:27

Hey Louis,

Currently we don't parse/separate the multipart parts for you (you should log a bug for this).

What you can currently do is to add  manual mapping so that the request body is passed into the method as a multipart entity, and then you'll have to split the multipart entity part.

If you can post the <service-name>.gen file in the WEB-INF/openedge folder of the webapp (its default location), then I can help you with the tweaks you'll need.

Posted by jts-law on 29-Jan-2018 15:59

Peter,

I wasn't sure if I was going to get a reply on this issue so I just opened up a case this afternoon.  If I upload my gen file to the case can you access it?

Louis

Posted by Peter Judge on 29-Jan-2018 16:08

Yes, that’ll work just fine.

Posted by jts-law on 29-Jan-2018 16:22

Excellent, I just uploaded a .zip file with the .gen file along with my EventHandler class (in case you need to see it).  The case is 00432333.  Thanks!

Posted by jts-law on 02-Feb-2018 13:47

Thanks Peter, the .map file you provided works great once I got my environment updated.

Now, how do you recommend returning errors back to KUIB?  The upload widget has an error event (docs.telerik.com/.../upload and it looks like the only information I can return is responseText, status, and statusText.  With the ABL method only having a single input value of OpenEdge.Net.MultipartEntity, I'm not sure how to return error information (determined by my validation and processing logic).

Louis Winter

Posted by Peter Judge on 05-Feb-2018 08:42

Louis,
 
From the docs you linked, it looks like the operations (error/success) expect the same JSON responses
Event Data
e.files Array
 
Lists the files that were uploaded or removed.
 
Each file has:
 
    name
    extension - The file extension including the leading dot. For example, .jpg, .png, an so on.
    size - The file size in bytes. If not available, the value is null.
    uid - The unique identifier of the file or batch of files.
 
e.operation String
 
The upload or remove operation.
e.XMLHttpRequest Object
 
Represents either the original XHR that is used for the operation or a stub that contains:
 
    responseText
    status
    statusText
 
Before you access any other fields, verify that this is an actual XHR.
 
The docs aren’t clear on how you signal an error vs success (I’d think a status code). You can do this with a custom map file too.
 
You can build the whole JSON yourself (easiest for now, I think) by tweaking your method’s signature to be
  METHOD PUBLIC INTEGER UploadFile(INPUT mpEntity AS OpenEdge.Net.MultipartEntity,
                                   OUTPUT pResponse AS JsonObject):
 
And the mapping entry to
{
  "services": {
    "UI": {
      "version": "1.0.0",
      "operations": {
        "/UploadFile": {
          "POST": {
            "contentType": "application/json",
            "entity": {
              "name": "UploadFileClass",
              "function": "UploadFile",
              "arg": [
                {
                  "ablName": "",
                  "ablType": "INTEGER",
                  "ioMode": "RETURN",
                  "msgElem": {"type": "StatusCode", "name": null}
                },
                {
                  "ablName": "mpEntity",
                  "ablType": "CLASS OpenEdge.Net.MultipartEntity",
                  "ioMode": "INPUT",
                  "msgElem": {"type": "BODY", "name": null}
                },
                {
                  "ablName": "pData",
                  "ablType": "CLASS Progress.Json.ObjectModel.JsonObject",
                  "ioMode": "OUTPUT",
                  "msgElem": {"type": "BODY", "name": null}
                }
              ]
            }
          }
        }
      },
      "schemas": null
    }
  }
}
 
 
 
 

Posted by jts-law on 07-Feb-2018 14:40

Thanks Peter, the changes to the map file are working perfectly.

Louis

Posted by jts-law on 13-Feb-2018 09:20

Peter,

Are there any settings or some way to speed up the MultipartEntity REST call?  My method works in that I can save the file being uploaded, but I noticed a large pause in the interface.  The following log file entries show what's happening.  Check out the time between the MPARTENT log entry and the next entry which appears to be when my upload method is actually called (1 minute and 47 seconds).

[18/02/13@09:00:07.959-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.InternalWebRouter DEBUG] Request for path "/JTS/web/pdo/UI/UploadProfitAcctCat" using template "/pdo/" and handler "OpenEdge.Web.DataObject.DataObjectHandler"

[18/02/13@09:00:07.967-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.InternalWebRouter DEBUG] Debug mode: ON

[18/02/13@09:00:07.983-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.InternalWebRouter DEBUG] Handler instance OpenEdge.Web.DataObject.DataObjectHandler_4209 used for handler OpenEdge.Web.DataObject.DataObjectHandler

[18/02/13@09:00:08.133-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     INFO: Current session client type MULTI-SESSION-AGENT does not support named logs

[18/02/13@09:00:08.199-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DataObjectHandler DEBUG] Using mapped operation for POST service path UploadProfitAcctCat: OpenEdge.Web.DataObject.MappedOperation_3688: POST svc:UI v1.0.0 uri:UploadProfitAcctCat: type:Class ; name:Progress.Lang.Object, type-of:Progress.Lang.Object, fn:, numargs:2, num-schemas:0, name:

[18/02/13@09:00:08.352-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     INFO: Current session client type MULTI-SESSION-AGENT does not support named logs

[18/02/13@09:00:08.357-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DataObjectHandler INFO] Service UI logging performed by OpenEdge.Web.DataObject.DataObjectHandler.UI at DEBUG

[18/02/13@09:00:08.365-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] "Accept" value: */*; q=0.5, application/json

[18/02/13@09:00:08.367-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Operation ContentType: application/json

[18/02/13@09:00:08.426-0600] P-021284 T-016484 1 AS-4 MPARTENT       DEBUG FILE=C:\OpenEdge\WRK\oepas1\temp\mpe-4354.txt

[18/02/13@09:01:55.422-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Business entity UploadProfitAcctCat (type-of Progress.Lang.Object) invoked by OpenEdge.Web.DataObject.DataObjectHandler_4209 as target type Class

[18/02/13@09:01:55.481-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Using business entity 4409 of type UploadProfitAcctCat

[18/02/13@09:01:55.484-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Using entity UploadProfitAcctCat_4409 for operation OpenEdge.Web.DataObject.MappedOperation_3688: POST svc:UI v1.0.0 uri:UploadProfitAcctCat: type:Class ; name:Progress.Lang.Object, type-of:Progress.Lang.Object, fn:, numargs:2, num-schemas:0, name:

[18/02/13@09:01:55.591-0600] P-021284 T-016484 1 AS-4 -- (Procedure: 'Logit JTSConfig' Line:451) [5] UploadProfitAcctCat:UploadAcctCat() Received 1 parts

[18/02/13@09:01:57.647-0600] P-021284 T-016484 1 AS-4 LogMgrWrtr     [OE.W.DO.DOH.UI DEBUG] Cached entity "UploadProfitAcctCat" removed for service "UI" 1.0.0

Louis

Posted by Peter Judge on 13-Feb-2018 12:13

Louis,

Would you mind contacting tech support? And could you send them the request (including the multipart body)?

Posted by jts-law on 13-Feb-2018 12:16

Will do.

Louis

This thread is closed