ls1intum / Artemis

Artemis - Interactive Learning with Automated Feedback
https://docs.artemis.cit.tum.de
MIT License
484 stars 287 forks source link

NullPointerException in ExerciseHintService occur when one or more tests are not executed #5392

Closed martinmo closed 2 years ago

martinmo commented 2 years ago

Describe the bug

We are seeing NullPointerExceptions in our server logs, right after Artemis receives a new build result with tests that have not been executed. The cause seems to be that in such a case, the positive field of the Feedback corresponding to the test is null and this is not always accounted for.

To Reproduce

  1. Submit a solution that leads to one or more test cases not getting executed. For example, for a Python exercise it is enough to import some unknown package (import does_not_exist).
  2. Wait a little bit for the CI to finish the build job and report its result back to Artemis.
  3. See the NullPointerException in the Artemis server log

Expected behavior

Test results containing test cases which haven't been executed for some reason are handled gracefully by Artemis.

Screenshots

No response

What browsers are you seeing the problem on?

Other (specify in "Additional context")

Additional context

The error is not visible to the user and only appears in the server log.

Relevant log output

2022-07-12 12:37:08.969  INFO 4416 --- [.1-8080-exec-12] d.t.i.w.artemis.web.rest.ResultResource  : Artemis received a new result for build plan DDIPY01S22E01-*******
2022-07-12 12:37:09.147  INFO 4416 --- [.1-8080-exec-12] d.t.i.w.artemis.web.rest.ResultResource  : The new result for DDIPY01S22E01-******* was saved successfully
2022-07-12 12:37:09.231 ERROR 4416 --- [.1-8080-exec-10] o.z.problem.spring.common.AdviceTraits   : Internal Server Error
java.lang.NullPointerException: null
        at java.base/java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
        at java.base/java.util.Spliterators$IteratorSpliterator.tryAdvance(Spliterators.java:1856)
        at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
        at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230)
        at java.base/java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.allMatch(ReferencePipeline.java:637)
        at de.tum.in.www1.artemis.service.hestia.ExerciseHintService.isTaskSuccessfulInSubmission(ExerciseHintService.java:215)
        at de.tum.in.www1.artemis.service.hestia.ExerciseHintService.subsequentNumberOfSubmissionsForTaskWithStatus(ExerciseHintService.java:226)
        at de.tum.in.www1.artemis.service.hestia.ExerciseHintService.lambda$getAvailableExerciseHints$5(ExerciseHintService.java:166)
        at java.base/java.util.stream.Collectors.lambda$uniqKeysMapAccumulator$1(Collectors.java:180)
        at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
        at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
        at de.tum.in.www1.artemis.service.hestia.ExerciseHintService.getAvailableExerciseHints(ExerciseHintService.java:166)
        at de.tum.in.www1.artemis.service.hestia.ExerciseHintService$$FastClassBySpringCGLIB$$e5d818ea.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy.invokeMethod(CglibAopProxy.java:386)
        at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:85)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:704)
        at de.tum.in.www1.artemis.service.hestia.ExerciseHintService$$EnhancerBySpringCGLIB$$4a495801.getAvailableExerciseHints(<generated>)
        at de.tum.in.www1.artemis.web.rest.hestia.ExerciseHintResource.getAvailableExerciseHintsForExercise(ExerciseHintResource.java:259)
        at de.tum.in.www1.artemis.web.rest.hestia.ExerciseHintResource$$FastClassBySpringCGLIB$$84e11bb8.invoke(<generated>)
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
        at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:61)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
        at de.tum.in.www1.artemis.web.rest.hestia.ExerciseHintResource$$EnhancerBySpringCGLIB$$cab98e05.getAvailableExerciseHintsForExercise(<generated>)
        at jdk.internal.reflect.GeneratedMethodAccessor861.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
        ...
bassner commented 2 years ago

cc @Hialus @ole-ve