Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to send message with glee when payload is an object with an allOf of two or more objects #720

Closed
dankar opened this issue Feb 14, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@dankar
Copy link

dankar commented Feb 14, 2024

Describe the bug

I have a message and it's payload consists of an object that is composed of an allOf with two objects in it. When I try to send this message it fails validation, even though I think it's correct. If the allOf only contains one object it works as expected.

Funnily enough, if I try to send an empty object as message, it complains about the missing keys. But if I add them I get the error message described.

How to Reproduce

I have this API spec:

asyncapi: 3.0.0
info:
  title: Test
  version: 1.0.0
  description: Test
defaultContentType: application/json
servers:
  local:
    host: 'localhost:1883'
    protocol: mqtt
channels:
  setParamResult:
    address: setParamResult
    messages:
      setParamResult:
        $ref: '#/components/messages/setParamResult'
operations:
  setParamResultOperation:
    action: send
    channel:
      $ref: '#/channels/setParamResult'
components:
  schemas:
    value:
      type: object
      additionalProperties: false
      title: value
      required: [valueString]
      properties:
        valueString:
          type: string
    correlationId:
      type: object
      additionalProperties: false
      title: correlationId
      required: [id]
      properties:
        id:
          type: string
    setParamResultPayload:
      title: setParamResult
      allOf:
        - $ref: '#/components/schemas/correlationId'
        - $ref: '#/components/schemas/value'
  messages:
    setParamResult:
      payload:
        $ref: '#/components/schemas/setParamResultPayload'

And this is the code in a lifecycle file:

export default async function ({
  glee,
  serverName,
  server,
  connection,
}) {
	return {
		send: [{
			payload: { id: "asdasd", valueString: "tjo" },
		channel: "setParamResult",
		server: "local"
		}]
	}
}

export const lifecycleEvent = 'onConnect'

This is the error I get:

↗ setParamResult was sent to local
{
  id: 'asdasd',
  valueString: 'tjo'
}
x One of your functions is producing a malformed event or there has been an error processing it. Please review the error below:
ADDTIONAL PROPERTY should NOT have additional properties

  1 | {
  2 |   "id": "asdasd",
> 3 |   "valueString": "tjo"
    |   ^^^^^^^^^^^^^ 😲  valueString is not expected to be here!
  4 | }

ADDTIONAL PROPERTY should NOT have additional properties

  1 | {
> 2 |   "id": "asdasd",
    |   ^^^^ 😲  id is not expected to be here!
  3 |   "valueString": "tjo"
  4 | }

ONEOF should match exactly one schema in oneOf

> 1 | {
    | ^
> 2 |   "id": "asdasd",
    | ^^^^^^^^^^^^^^^^^
> 3 |   "valueString": "tjo"
    | ^^^^^^^^^^^^^^^^^
> 4 | }
    | ^^ 👈🏽oneOf should match exactly one schema in oneOf

Expected behavior

I'm fairly sure I shouldn't be getting any errors.

@dankar dankar added the bug Something isn't working label Feb 14, 2024
@KhudaDad414
Copy link
Member

@dankar, I think I spotted the issue in your schema. The problem is with using allOf and setting additionalProperties: false at the same time. Here's why:

  • allOf is strict: With allOf, your message has to match both schemas.
  • No extra properties allowed: That additionalProperties: false setting makes things tricky because it means absolutely no other properties can exist.

Your schemas are fighting each other in a paradox.

Change additionalProperties to true in one of your schemas. That'll make things a bit more flexible and should fix the error.

Let me know if that works! 😊

@dankar
Copy link
Author

dankar commented Mar 21, 2024

@KhudaDad414 Thank you for your answer. I'm then a bit unsure of how to specify what I want: I do want the message to contain all of those objects, but absolutely nothing else.

Is it then not possible to specify that?

@KhudaDad414
Copy link
Member

I guess the best bet would be to combine your schemas into one schema. something like:

{
  "additionalProperties": false,
  "title": "setParamResult",
  "type": "object",
  "required": [
    "id",
    "valueString"
  ],
  "properties": {
    "id": {
      "type": "string"
    },
    "valueString": {
      "type": "string"
    }
  }
}

if this is not a choice then I am not exactly sure if it's possible with allOf.
I am closing the issue for now.

@dankar
Copy link
Author

dankar commented Mar 21, 2024

I would think that it's against the purpose of using these kinds of tools. I want to be able to reuse objects as much as possible, instead of implementing them over and over. These examples were simple, but in reality I have numerous big objects that are used tens of times in different messages. The only caveat in this case is that I want to have the message fully defined, and not allow any additional properties in any part of it.

But of course, it's up to you, I just thought I should report it :)

@KhudaDad414
Copy link
Member

@dankar, you are correct. this is a limitation. but since we are using JSON Schema there is nothing we can do to address this issue. you can open an issue in the JSON Schema and if they change things things are going to work here automatically.
All I want to say is there there is nothing that we can do here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants