TongchengOpenSource / smart-doc

Smart-doc is a java restful api document generation tool. Smart-doc is based on interface source code analysis to generate interface documentation, completely zero-injection.

Home Page:https://smart-doc-group.github.io/#/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NPE in JsonBuildHelper

muyuanjin opened this issue · comments

Your Environment(您的使用环境,您期望的结果,社区已开启国际化推广,请文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)

  • smart-doc version: 3.0.4
  • plugin version (e.g. smart-doc-maven-plugin or smart-doc-gradle-plugin): 3.0.4
  • build tool version(maven or gradle): maven 3.9.5
  • jdk version: 17

Expected Behavior(您期望的结果,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)

Current Behavior(当前结果,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)

[ERROR] 
java.lang.NullPointerException: Cannot invoke "String.length()" because "fieldGicName" is null
    at com.ly.doc.helper.JsonBuildHelper.buildJson (JsonBuildHelper.java:395)
    at com.ly.doc.template.IRestDocTemplate.requestParams (IRestDocTemplate.java:643)
    at com.ly.doc.template.IRestDocTemplate.buildEntryPointMethod (IRestDocTemplate.java:452)
    at com.ly.doc.template.IRestDocTemplate.processApiData (IRestDocTemplate.java:96)
    at com.ly.doc.template.SpringBootDocBuildTemplate.renderApi (SpringBootDocBuildTemplate.java:53)
    at com.ly.doc.template.IDocBuildTemplate.getApiData (IDocBuildTemplate.java:51)
    at com.ly.doc.builder.HtmlApiDocBuilder.buildApiDoc (HtmlApiDocBuilder.java:71)
    at com.ly.doc.plugin.mojo.HtmlMojo.executeMojo (HtmlMojo.java:48)
    at com.ly.doc.plugin.mojo.BaseDocsGeneratorMojo.execute (BaseDocsGeneratorMojo.java:168)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:906)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:206)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:77)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:568)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:283)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:226)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:407)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:348)
    at org.codehaus.classworlds.Launcher.main (Launcher.java:47)

Possible Solution(bug解决建议,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)

Steps to Reproduce (Bug产生步骤,请尽量提供用例代码。社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)

The "field" that raises NPE is located in the default method with generics of an interface under annotation. :

@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@JacksonAnnotationsInside
@JsonSerialize(using = Enums.EnumsJsonSerializer.class)
@JsonDeserialize(using = Enums.EnumsJsonDeserializer.class)
public @interface Enums {
//...
    interface Serialize<T extends Enum<T> & Serialize<T>> {
        default String getSerializationName() {
            return ((Enum<?>) this).name();
        }

        default Integer getSerializationId() {
            return ((Enum<?>) this).ordinal();
        }

        @SuppressWarnings("unchecked")
        default Class<T> getOriginalClass() { // this "field"  causes NPE
            return (Class<T>) this.getClass();
        }
        //...
    }
//...
}

Context(Bug影响描述,社区已开启国际化推广,请用文心一言、讯飞星火等辅助翻译成英文,减少社区开发者的工作)

try it with apideploy?

@muyuanjin Could you provide a more detailed use case to assist the community in more effectively resolving issues? If you could help fix this problem, we would greatly welcome your contribution.

The following is a local test that can reproduce this problem :

    /**
     * com.ly.doc.helper.JsonBuildHelper#buildJson
     * issue:NPE in JsonBuildHelper #789
     */
    @Test
    void testBuildJsonWithNPE() throws IOException {
        ApiConfig apiConfig = new ApiConfig();
        JavaProjectBuilder projectBuilder = JavaProjectBuilderHelper.create();
        Assertions.assertNotNull(projectBuilder.getClassByName(getClass().getName()));
        JavaClass taskType = projectBuilder.getClassByName(Task.class.getName());
        Assertions.assertNotNull(taskType);
        Assertions.assertFalse(taskType.getMethods().isEmpty());
        ProjectDocConfigBuilder builder = new ProjectDocConfigBuilder(apiConfig, projectBuilder);
        Assertions.assertNull(builder.getClassByName(getClass().getName()));
        Assertions.assertNotNull(builder.getClassByName(Task.class.getName()));
        Assertions.assertFalse(builder.getClassByName(Task.class.getName()).getMethods().isEmpty());
        JsonBuildHelper.buildJson(Task.class.getName(),
                Task.class.getCanonicalName(),
                false, 0, new HashMap<>(16), new HashSet<>(), builder
        );
    }

    interface Serialize<T extends Serialize<T>> {
        default String getSerializationName() {
            return ((Enum<?>) this).name();
        }

        default Integer getSerializationId() {
            return ((Enum<?>) this).ordinal();
        }

        @SuppressWarnings("unchecked")
        default Class<T> getOriginalClass() {
            return (Class<T>) this.getClass();
        }
    }

    public static class Task implements Serialize<Task> {
        private String taskType;

        public String getTaskType() {
            return taskType;
        }

        public void setTaskType(String taskType) {
            this.taskType = taskType;
        }
    }