ankraft / ACME-oneM2M-CSE

An open source CSE Middleware for Education.
https://acmecse.net/
BSD 3-Clause "New" or "Revised" License
23 stars 16 forks source link

Creating Flex Container without specifiying Resource ID #92

Closed tsengia closed 1 year ago

tsengia commented 1 year ago

Hi, I'm not sure if this is truely a bug, or if I am not fully understanding oneM2M. I am attempting to create a FlexContainer using a custom definition that I've placed in the init folder. My flex container definition is below (ignore the line numbers of the left):

  1 [
  2     {
  3         "type": "traffic:trfint",
  4         "lname": "trafficLightIntersection",
  5         "cnd": "edu.psu.cse.traffic.trafficLightIntersection",
  6
  7         "attributes": [
  8             {
  9                 "sname":"id",
 10                 "lname": "identifier",
 11                 "type":"string",
 12                 "car":"1"
 13            },
 14            {
 15                 "sname":"bts",
 16                 "lname": "bluetoothState",
 17                 "type":"string",
 18                 "car":"1"
 19            },
 20            {
 21                 "sname":"l1s",
 22                 "lname": "light1State",
 23                 "type":"string",
 24                 "car":"1"
 25            },
 26            {
 27                 "sname":"l2s",
 28                 "lname": "light2State",
 29                 "type":"string",
 30                 "car":"1"
 31            }
 32         ]
 33     }
 34 ]

The REST request that I'm sending is here:

{
    "my-flex-cnt": {
        "acpi": [
            "/id-in/acpCreateACPs"
        ],
        "cnd": "traffic:trfint",
        "rn": "light1-rn",
        "id": "thingy91intersectionA",
        "bts": "connected",
        "l1s": "yellow",
        "l2s": "red"
    }
}

This results in the following error and stack trace:

Traceback (most recent call last):                                       Utils.py:875
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/services/HttpServer.py", line 215, in
                   _handleRequest
                       responseResult = CSE.request.handleRequest(dissectResult.request)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/services/RequestManager.py", line 124, in
                   handleRequest
                       return self.requestHandlers[request.op].ownRequest(request)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/services/RequestManager.py", line 179, in
                   createRequest
                       res = CSE.dispatcher.processCreateRequest(request, request.headers.originator)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/services/Dispatcher.py", line 493, in
                   processCreateRequest
                       if not (nres := Factory.resourceFromDict(deepcopy(request.pc),
                   pi=parentResource.ri, ty=ty)).resource:      # something wrong, perhaps wrong type
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/Factory.py", line 208, in
                   resourceFromDict
                       return Result(status = True, rsc = RC.OK, resource = factory[1](resDict, tpe, pi,
                   create))
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/Factory.py", line 98, in
                   <lambda>
                       T.FCNT                      : (FCNT,                lambda dct, tpe, pi, create :
                   FCNT(dct, pi = pi, fcntType = tpe, create = create)),
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/FCNT.py", line 66, in __init__
                       super().__init__(T.FCNT, dct, pi, tpe = fcntType, create = create)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/AnnounceableResource.py", line
                   21, in __init__
                       super().__init__(ty, dct, pi, tpe = tpe, create = create, inheritACP =
                   inheritACP, readOnly = readOnly, rn = rn,)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/Resource.py", line 107, in
                   __init__
                       self.setAttribute('ri', Utils.uniqueRI(self.tpe), overwrite = False)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/etc/Utils.py", line 39, in uniqueRI
                       return f'{noNamespace(prefix)}{uniqueID()}'
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/etc/Utils.py", line 110, in noNamespace
                       _, found, tail = id.partition(':')
                   AttributeError: 'NoneType' object has no attribute 'partition'

                   Traceback (most recent call last):
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/services/HttpServer.py", line 215, in
                   _handleRequest
                       responseResult = CSE.request.handleRequest(dissectResult.request)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/services/RequestManager.py", line 124, in
                   handleRequest
                       return self.requestHandlers[request.op].ownRequest(request)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/services/RequestManager.py", line 179, in
                   createRequest
                       res = CSE.dispatcher.processCreateRequest(request, request.headers.originator)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/services/Dispatcher.py", line 493, in
                   processCreateRequest
                       if not (nres := Factory.resourceFromDict(deepcopy(request.pc),
                   pi=parentResource.ri, ty=ty)).resource:      # something wrong, perhaps wrong type
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/Factory.py", line 208, in
                   resourceFromDict
                       return Result(status = True, rsc = RC.OK, resource = factory[1](resDict, tpe, pi,
                   create))
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/Factory.py", line 98, in
                   <lambda>
                       T.FCNT                      : (FCNT,                lambda dct, tpe, pi, create :
                   FCNT(dct, pi = pi, fcntType = tpe, create = create)),
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/FCNT.py", line 66, in __init__
                       super().__init__(T.FCNT, dct, pi, tpe = fcntType, create = create)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/AnnounceableResource.py", line
                   21, in __init__
                       super().__init__(ty, dct, pi, tpe = tpe, create = create, inheritACP =
                   inheritACP, readOnly = readOnly, rn = rn,)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/resources/Resource.py", line 107, in
                   __init__
                       self.setAttribute('ri', Utils.uniqueRI(self.tpe), overwrite = False)
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/etc/Utils.py", line 39, in uniqueRI
                       return f'{noNamespace(prefix)}{uniqueID()}'
                     File "/home/ec2-user/ACME-oneM2M-CSE/acme/etc/Utils.py", line 110, in noNamespace
                       _, found, tail = id.partition(':')
                   AttributeError: 'NoneType' object has no attribute 'partition'

Following this trace I found a section of code in resources/Resource.py that seems to be the root cause of this error. On line 90 of Resource.py, the self.tpe assignment is skipped if the resource being created is a FlexContainer:
https://github.com/ankraft/ACME-oneM2M-CSE/blob/ddd62345e89c9ce1be48c0425c1149243c1495ef/acme/resources/Resource.py#L90-L91

Later in the same function, a resourceID is assigned using self.tpe: https://github.com/ankraft/ACME-oneM2M-CSE/blob/ddd62345e89c9ce1be48c0425c1149243c1495ef/acme/resources/Resource.py#L106-L107

Because self.tpe was never set, this results in the NoneType object has no attribute 'partition'

Is this expected behavior? Am I allowed to request the creation of a FlexContainer without giving a resourceID in my request? Or do I have to specify the resourceID in the request?

Thanks!

tsengia commented 1 year ago

Nevermind, I found the error in my request. Closing.

ankraft commented 1 year ago

Thanks for reporting this. Though you might have found an issue on your side the CSE still should not crash when encountering an, I guess, illformed resource or specialisation type, but return gracefully an error message. I will look into this.

ankraft commented 1 year ago

This fixes this issue in the development branch. It also returns a meaning full dbg message.