lonely-lockley / archinsight

Simplicity in Code, Power in Design
https://archinsight.org
GNU Affero General Public License v3.0
51 stars 5 forks source link

Fix NPE in Translator when level is null #81

Closed lonely-lockley closed 4 months ago

lonely-lockley commented 4 months ago

Level declaration is not supposed to be null, but in some cases it happens in Translator service. No Insight source causing this issue available at this moment, so the bug has to be reproduced somehow.

13.03.2024 15:03:00.312 ERROR [virtual-executor814] i.m.http.server.RouteExecutor - Unexpected error occurred: Cannot invoke "com.github.lonelylockley.archinsight.model.ArchLevel.toString()" because the return value of "com.github.lonelylockley.archinsight.model.imports.AbstractImport.getLevel()" is null
java.lang.NullPointerException: Cannot invoke "com.github.lonelylockley.archinsight.model.ArchLevel.toString()" because the return value of "com.github.lonelylockley.archinsight.model.imports.AbstractImport.getLevel()" is null
    at com.github.lonelylockley.archinsight.link.Linker.rewriteImportsInternal(Linker.java:47)
    at com.github.lonelylockley.archinsight.link.Linker.rewriteImports(Linker.java:118)
    at com.github.lonelylockley.archinsight.link.Linker.checkIntegrity(Linker.java:194)
    at com.github.lonelylockley.archinsight.TranslatorService.translate(TranslatorService.java:68)
    at com.github.lonelylockley.archinsight.$TranslatorService$Definition$Intercepted.$$access$$translate(Unknown Source)
    at com.github.lonelylockley.archinsight.$TranslatorService$Definition$Exec.dispatch(Unknown Source)
    at io.micronaut.context.AbstractExecutableMethodsDefinition$DispatchedExecutableMethod.invoke(AbstractExecutableMethodsDefinition.java:442)
    at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:128)
    at com.github.lonelylockley.archinsight.tracing.ResponseTimeMeasuringInterceptor.intercept(ResponseTimeMeasuringInterceptor.java:26)
    at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:137)
    at com.github.lonelylockley.archinsight.$TranslatorService$Definition$Intercepted.translate(Unknown Source)
    at com.github.lonelylockley.archinsight.$TranslatorService$Definition$Exec.dispatch(Unknown Source)
    at io.micronaut.context.AbstractExecutableMethodsDefinition$DispatchedExecutableMethod.invokeUnsafe(AbstractExecutableMethodsDefinition.java:447)
    at io.micronaut.context.DefaultBeanContext$BeanContextUnsafeExecutionHandle.invokeUnsafe(DefaultBeanContext.java:4214)
    at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:263)
    at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:74)
    at io.micronaut.http.server.RouteExecutor.executeRouteAndConvertBody(RouteExecutor.java:480)
    at io.micronaut.http.server.RouteExecutor.lambda$callRoute$6(RouteExecutor.java:457)
    at io.micronaut.core.execution.ExecutionFlow.lambda$async$1(ExecutionFlow.java:87)
lonely-lockley commented 4 months ago

Could reproduce another problem seen in logs that I considered irrelevant

13.03.2024 14:46:03.176 ERROR [virtual-executor788] c.g.l.archinsight.parse.Parser - Error parsing source
java.lang.NullPointerException: Cannot invoke "org.antlr.v4.runtime.TokenSource.getInputStream()" because the return value of "org.antlr.v4.runtime.Token.getTokenSource()" is null
    at org.antlr.v4.runtime.DefaultErrorStrategy.getMissingSymbol(DefaultErrorStrategy.java:599)
    at org.antlr.v4.runtime.DefaultErrorStrategy.recoverInline(DefaultErrorStrategy.java:477)
    at org.antlr.v4.runtime.Parser.match(Parser.java:207)
    at com.github.lonelylockley.insight.lang.InsightParser.commentDeclaration(InsightParser.java:3164)
    at com.github.lonelylockley.insight.lang.InsightParser.containerElementDeclaration(InsightParser.java:1698)
    at com.github.lonelylockley.insight.lang.InsightParser.levelDeclaration(InsightParser.java:324)
    at com.github.lonelylockley.insight.lang.InsightParser.insight(InsightParser.java:192)
    at com.github.lonelylockley.archinsight.parse.Parser.parse(Parser.java:55)
    at com.github.lonelylockley.archinsight.parse.Parser.lambda$parseRepository$0(Parser.java:36)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
    at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
    at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:387)
    at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:667)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:160)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:174)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
    at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:765)
    at com.github.lonelylockley.archinsight.parse.Parser.parseRepository(Parser.java:34)

To reproduce this two files needed. One should import another. Imported file should not have level identifier:

container 

service a
    name = A
context b

import a from container a

system b
    name = B
    links:
        -> a

This would not render in normal situation, but a Render button was added lately that causes backend translation and render. Apparently, user starts clicking this button when the diagram does not update (because of errors).

lonely-lockley commented 4 months ago

Found a way to reproduce the main issue. Import statement without level declaration:

container a

service a
    name = A
context b

import a from a

system b
    name = B
    links:
        -> a

Once again, this should not render on backend because of syntax errors, but the new Render button forces this to happen