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

[AsyncAPI] NullPointerException in MapperContentUtil.java #271

Closed
gaby-roland opened this issue Aug 18, 2023 · 11 comments · Fixed by #274
Closed

[AsyncAPI] NullPointerException in MapperContentUtil.java #271

gaby-roland opened this issue Aug 18, 2023 · 11 comments · Fixed by #274
Assignees
Labels
bug Something isn't working

Comments

@gaby-roland
Copy link

I keep getting NullPointerException errors originating in MapperContentUtil.
Specifically, line 390.

         if (value.has(REF)) {
            typeObject = MapperUtil.getRef(value, prefix, suffix);
          }
          field.setImportClass(getImportClass(typeObject));
          field.setDataType(typeObject);
          final String[] path = MapperUtil.splitName(value.get(REF).textValue());

It looks like on the last line in the snippet, value.get(REF) is null, which explains why a few line before it there is a if (value.has(REF)), but this check is not taken into consideration on 390 and value.get(REF) is assumed to be non-null.

I saw this error whenever I try have an object nested inside another object, for example in the yaml below, someOtherObject is nested inside of userSignedUpPayload:

asyncapi: "2.0.0"
info:
  title: Demo API
  version: "1.0.0"

channels:
  user/signedup:
    subscribe:
      operationId: emitUserSignUpEvent
      message:
        $ref : '#/components/messages/UserSignedUp'

components:
  messages:
    UserSignedUp:
      name: userSignedUp
      title: User signed up event
      summary: Inform about a new user registration in the system
      contentType: application/json
      payload:
        $ref: '#/components/schemas/userSignedUpPayload'

  schemas:
    userSignedUpPayload:
      type: object
      properties:
        firstName:
          type: string
          description: "foo"
        lastName:
          type: string
          description: "bar"
        email:
          type: string
          format: email
          description: "baz"
        createdAt:
          type: string
          format: date-time
        someOtherObject:
          type: object
          properties:
            property1:
              type: string
            property2:
              type: integer

This causes the following error:

Caused by: java.lang.NullPointerException
    at com.sngular.api.generator.plugin.asyncapi.util.MapperContentUtil.setFieldType (MapperContentUtil.java:390)
    at com.sngular.api.generator.plugin.asyncapi.util.MapperContentUtil.processFieldObjectList (MapperContentUtil.java:245)
    at com.sngular.api.generator.plugin.asyncapi.util.MapperContentUtil.processFieldObject (MapperContentUtil.java:156)
    at com.sngular.api.generator.plugin.asyncapi.util.MapperContentUtil.getFields (MapperContentUtil.java:128)
    at com.sngular.api.generator.plugin.asyncapi.util.MapperContentUtil.buildSchemaObject (MapperContentUtil.java:82)
    at com.sngular.api.generator.plugin.asyncapi.util.MapperContentUtil.mapComponentToSchemaObject (MapperContentUtil.java:66)
    at com.sngular.api.generator.plugin.asyncapi.AsyncApiGenerator.fillTemplateFactory (AsyncApiGenerator.java:538)
    at com.sngular.api.generator.plugin.asyncapi.AsyncApiGenerator.processSubscribeMethod (AsyncApiGenerator.java:524)
    at com.sngular.api.generator.plugin.asyncapi.AsyncApiGenerator.processOperation (AsyncApiGenerator.java:336)
    at com.sngular.api.generator.plugin.asyncapi.AsyncApiGenerator.processFileSpec (AsyncApiGenerator.java:172)
@jemacineiras
Copy link
Contributor

HI @gaby-roland,

Looks like you found a hole in our AsyncApi specification support. I'll check it and provide a solution ASAP.

Cheers

@jemacineiras jemacineiras self-assigned this Aug 18, 2023
@jemacineiras jemacineiras added the bug Something isn't working label Aug 19, 2023
@jemacineiras
Copy link
Contributor

HI @gaby-roland,

I provide a fix in a branch attached to this issue. Do you mind test if it works for you?

Cheers

@gaby-roland
Copy link
Author

Hi @jemacineiras

I pulled and built your branch. It seems to get a bit farther now, but I get this error now:

Caused by: org.apache.maven.plugin.compiler.CompilationFailureException: Compilation failure
/C:/Development/Projects/apis/asyncapi/core/asyncapi-demo-service-api/target/generated-sources/apig
enerator/com/test/apis/asyncapi/demo/generated/types/SomeOtherObject.java:[1,63] <identif
ier> expected

When I look at my generated classes, it seems to be appending a . at the end of the package, like it's expecting 1 more package identifier. But the class is in com.test.apis.asyncapi.demo.generated.types (see line 1)
image

@jemacineiras
Copy link
Contributor

Hi @gaby-roland,
That is odd, I added a test with your schema and generates all files property (testNestedObjectIssue). Do you mind sharing the configuration part you have in the plugin?
Cheers

@gaby-roland
Copy link
Author

@jemacineiras Sure! Here is my plugin configuration in my pom.xml

      <plugin>
        <groupId>com.sngular</groupId>
        <artifactId>scs-multiapi-maven-plugin</artifactId>
        <version>${scs.multiapi.maven.plugin.version}</version>
        <executions>
          <execution>
            <phase>generate-sources</phase>
            <goals>
              <goal>asyncapi-generation</goal>
            </goals>
            <configuration>
              <specFiles>
                <specFile>
                  <filePath>${asyncapi.spec}</filePath>
                  <consumer>
                    <apiPackage>${project.groupId}.demo.generated.api.consumer</apiPackage>
                    <modelPackage>${project.groupId}.demo.generated.types</modelPackage>
                  </consumer>
                  <supplier>
                    <apiPackage>${project.groupId}.demo.generated.api.producer</apiPackage>
                    <modelPackage>${project.groupId}.demo.generated.types</modelPackage>
                  </supplier>
                </specFile>
              </specFiles>
            </configuration>
          </execution>
        </executions>
      </plugin>

@gaby-roland
Copy link
Author

This is the generate code structure btw, it looks like it places SomeOtherObject outside of the schemas package:
image

@jemacineiras
Copy link
Contributor

Thanks,

I found strange this part
<supplier> <apiPackage>${project.groupId}.demo.generated.api.producer</apiPackage> <modelPackage>${project.groupId}.demo.generated.types</modelPackage> </supplier>
But there is no producer part defined in the API definition.
That is correct?

@gaby-roland
Copy link
Author

Yeah I think that's because I just don't have any publish operations/channels, so that package is empty right now. I just have 1 subscribe channel for now in my demo but my operational code will have both.

jemacineiras added a commit that referenced this issue Aug 21, 2023
@jemacineiras
Copy link
Contributor

Yes, that was the problem. But I think I found the key, do you mind testing this fix?

@gaby-roland
Copy link
Author

Close, it now places the class inside the schemas package, but it seems everything is capitalized. The class name and the package, as seen in the screenshot:
image

This results in the other class failing to find SomeOtherObject
image

jemacineiras added a commit that referenced this issue Aug 21, 2023
jemacineiras added a commit that referenced this issue Aug 22, 2023
jemacineiras added a commit that referenced this issue Aug 22, 2023
@gaby-roland
Copy link
Author

With the latest changes, it seems like the supplier package and all the publish channels are completely missing.
Here is the same yaml as in the original problem, but with the added publish channel. I also updated my plugin configuration to add a <supplier> section. But the publish channels don't get generated.

asyncapi: "2.0.0"
info:
  title: Demo API
  version: "1.0.0"

channels:
  user/signedup:
    subscribe:
      operationId: emitUserSignUpEvent
      message:
        $ref : '#/components/messages/UserSignedUp'
    publish:
      operationId: onUserSignUp
      message:
        $ref: '#/components/messages/UserSignedUp'

components:
  messages:
    UserSignedUp:
      name: userSignedUp
      title: User signed up event
      summary: Inform about a new user registration in the system
      contentType: application/json
      payload:
        $ref: '#/components/schemas/userSignedUpPayload'

  schemas:
    userSignedUpPayload:
      type: object
      properties:
        firstName:
          type: string
          description: "foo"
        lastName:
          type: string
          description: "bar"
        email:
          type: string
          format: email
          description: "baz"
        createdAt:
          type: string
          format: date-time
        someOtherObject:
          type: object
          properties:
            property1:
              type: string
            property2:
              type: integer

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

Successfully merging a pull request may close this issue.

2 participants