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

Crash on Kafka consume when key is string with recordType: JSON #657

Closed
Tobolov opened this issue Apr 4, 2024 · 4 comments
Closed

Crash on Kafka consume when key is string with recordType: JSON #657

Tobolov opened this issue Apr 4, 2024 · 4 comments
Assignees
Labels
documentation-todo https://github.com/authorjapps/zerocode/wiki/Documentation-Steps feature-request New feature which can be introduced fixed-and-released

Comments

@Tobolov
Copy link

Tobolov commented Apr 4, 2024

When consuming a Kafka records with recordType: JSON, records with a plain string as a the key can't be deserialized.

Scenario to reproduce:

---
scenarioName: Demo
steps:
  - name: do_produce
    url: "kafka-topic:THE_TOPIC"
    operation: produce
    request:
      recordType: JSON
      records:
        - key: ${RANDOM.UUID}
          value:
            appName: App X
    verify:
      status: Ok
  - name: do_consume
    url: "kafka-topic:THE_TOPIC"
    operation: consume
    request:
      consumerLocalConfigs:
        recordType: JSON
        commitSync: true
        showRecordsConsumed: true
        maxNoOfRetryPollsOrTimeouts: 3
    verify:
      size: 1
      records:
        - key: ${$.do_produce.request.records[0].key}
          value:
            appName: App X

Exception:

ava.lang.RuntimeException: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('d' (code 100)): Expected space separating root-level values
 at [Source: (String)"1dd2e6c2-9d40-4c75-b735-c83911b6b652"; line: 1, column: 3]
	at org.jsmart.zerocode.core.kafka.client.BasicKafkaClient.execute(BasicKafkaClient.java:51)
	at org.jsmart.zerocode.core.engine.executor.ApiServiceExecutorImpl.executeKafkaService(ApiServiceExecutorImpl.java:59)
	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.executeApi(ZeroCodeMultiStepsScenarioRunnerImpl.java:485)
	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.executeRetry(ZeroCodeMultiStepsScenarioRunnerImpl.java:252)
	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.executeRetryWithSteps(ZeroCodeMultiStepsScenarioRunnerImpl.java:191)
	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.executeSteps(ZeroCodeMultiStepsScenarioRunnerImpl.java:173)
	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.runScenario(ZeroCodeMultiStepsScenarioRunnerImpl.java:136)
	at org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner.runLeafJsonTest(ZeroCodeUnitRunner.java:223)
	at org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner.runChild(ZeroCodeUnitRunner.java:127)
	at org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner.runChild(ZeroCodeUnitRunner.java:51)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner.run(ZeroCodeUnitRunner.java:107)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)
Caused by: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('d' (code 100)): Expected space separating root-level values
 at [Source: (String)"1dd2e6c2-9d40-4c75-b735-c83911b6b652"; line: 1, column: 3]
	at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2477)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:750)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:674)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportMissingRootWS(ParserMinimalBase.java:722)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._verifyRootSpace(ReaderBasedJsonParser.java:1830)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._parseUnsignedNumber(ReaderBasedJsonParser.java:1425)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:805)
	at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4854)
	at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:3219)
	at org.jsmart.zerocode.core.kafka.helper.KafkaConsumerHelper.readJson(KafkaConsumerHelper.java:307)
	at org.jsmart.zerocode.core.kafka.receive.KafkaReceiver.appendNewRecords(KafkaReceiver.java:124)
	at org.jsmart.zerocode.core.kafka.receive.KafkaReceiver.receive(KafkaReceiver.java:96)
	at org.jsmart.zerocode.core.kafka.client.BasicKafkaClient.execute(BasicKafkaClient.java:38)
	... 23 more

java.lang.RuntimeException: ZeroCode Step execution failed. Details:java.lang.RuntimeException: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('d' (code 100)): Expected space separating root-level values
 at [Source: (String)"1dd2e6c2-9d40-4c75-b735-c83911b6b652"; line: 1, column: 3]

	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.executeRetry(ZeroCodeMultiStepsScenarioRunnerImpl.java:379)
	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.executeRetryWithSteps(ZeroCodeMultiStepsScenarioRunnerImpl.java:191)
	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.executeSteps(ZeroCodeMultiStepsScenarioRunnerImpl.java:173)
	at org.jsmart.zerocode.core.runner.ZeroCodeMultiStepsScenarioRunnerImpl.runScenario(ZeroCodeMultiStepsScenarioRunnerImpl.java:136)
	at org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner.runLeafJsonTest(ZeroCodeUnitRunner.java:223)
	at org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner.runChild(ZeroCodeUnitRunner.java:127)
	at org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner.runChild(ZeroCodeUnitRunner.java:51)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.jsmart.zerocode.core.runner.ZeroCodeUnitRunner.run(ZeroCodeUnitRunner.java:107)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
	at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55)

Root cause:
On KafkaConsumerHelper.java#L307, we run JsonNode keyNode = objectMapper.readTree(keyStr);. This expects the key to be a supported JSON element. The value1dd2e6c2-9d40-4c75-b735-c83911b6b652 is not a supported JSON element, however "1dd2e6c2-9d40-4c75-b735-c83911b6b652" would be.


JSON equivalent:

{
  "scenarioName": "Demo",
  "steps": [
    {
      "name": "do_produce",
      "url": "kafka-topic:THE_TOPIC",
      "operation": "produce",
      "request": {
        "recordType": "JSON",
        "records": [
          {
            "key": "${RANDOM.UUID}",
            "value": {
              "appName": "App X"
            }
          }
        ]
      },
      "verify": {
        "status": "Ok"
      }
    },
    {
      "name": "do_consume",
      "url": "kafka-topic:THE_TOPIC",
      "operation": "consume",
      "request": {
        "consumerLocalConfigs": {
          "recordType": "JSON",
          "commitSync": true,
          "showRecordsConsumed": true,
          "maxNoOfRetryPollsOrTimeouts": 3
        }
      },
      "verify": {
        "size": 1,
        "records": [
          {
            "key": "${$.do_produce.request.records[0].key}",
            "value": {
              "appName": "App X"
            }
          }
        ]
      }
    }
  ]
}
baulea added a commit to baulea/zerocode that referenced this issue Apr 4, 2024
- fix recordType JSON authorjapps#657
- use objectMapper to convert from POJO to JSON instead of toString()
- misspelled recordType
- topic "demo-p6" is used in another test, replace by "demo-p7"
@authorjapps
Copy link
Owner

@Tobolov , understood the issue.

  1. You have a String key(with alpha-numeric) and JSON value already produced into the Kafka topic. Then, consuming failed due to deser failed at objectMapper.readTree(keyStr) as you have spotted.

Just checking about your test usecase, did you produce the messages that way(mentioned in No. 1)
or
another application has produced that way, then you are only consuming?

@Tobolov
Copy link
Author

Tobolov commented Apr 9, 2024

Thanks for the swift reply @authorjapps!
Yep, issue correctly identified.

I first identified the issue when I had another application produce a record with an alpha-number key and a JSON value in response to a HTTP request.

That said, I will have also have tests quite similar in nature to the one included in the bug report. The only notable difference being the key will be some-prefix-${RANDOM.UUID}.

@nirmalchandra
Copy link
Collaborator

nirmalchandra commented Apr 12, 2024

Thanks for the swift reply @authorjapps! Yep, issue correctly identified.

I first identified the issue when I had another application produce a record with an alpha-number key and a JSON value in response to a HTTP request.

That said, I will have also have tests quite similar in nature to the one included in the bug report. The only notable difference being the key will be some-prefix-${RANDOM.UUID}.

@Tobolov , we will be sorting this out soon in the next release.

Until the fix is in place, the below work-around could be used(temporarily fix only if feasible) :
While producing(either your test scenario or another application), produce like this:
e.g.

"key": "\"ALPHA-001\"",

instead of "key": "ALPHA-001",

I am aware that this may not be very convinient if the message is produced by another application(internal or external to your system), but may be an alternative(for temporarily until the PR is merged) if your one of your test step is doing the PRODUCE.

A working example is here for reference, for the the this test scenario.

@authorjapps
Copy link
Owner

authorjapps commented Apr 22, 2024

TODO:
Documentation: Update here.

Available in version: 1.3.43.

Release Details:
https://github.com/authorjapps/zerocode/releases/tag/1.3.43

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation-todo https://github.com/authorjapps/zerocode/wiki/Documentation-Steps feature-request New feature which can be introduced fixed-and-released
Projects
None yet
Development

No branches or pull requests

3 participants