Uploaded image for project: 'Sakai'
  1. Sakai
  2. SAK-36854

Samigo event name refactor/standardization causing NPE on assessment submission

    XMLWordPrintable

    Details

    • 12 status:
      Resolved
    • 11 status:
      Resolved
    • Previous Issue Keys:
      SAM-3244
    • Test Plan:
      Hide

      Please add a Test Plan here.

      Show
      Please add a Test Plan here.

      Description

      Steps to reproduce:
      1) create and publish a quiz
      2) take the quiz as student/access user, while watching the logs
      3) on submission, notice the following NPE in the logs

      WARN [http-nio-8450-exec-6] org.sakaiproject.event.impl.ClusterEventTracking.postEvent postEvent, notifyObservers(), event: 0:sam.assessment.submit@siteId=a632532f-351f-4493-82de-94499e100685, submissionId=3[m, 2]
      java.lang.NullPointerException
              at org.sakaiproject.samigo.impl.SamigoObserver.stringToHashMap(SamigoObserver.java:78)
              at org.sakaiproject.samigo.impl.SamigoObserver.update(SamigoObserver.java:55)
              at java.util.Observable.notifyObservers(Observable.java:159)
              at org.sakaiproject.event.impl.BaseEventTrackingService.notifyObservers(BaseEventTrackingService.java:111)
              at org.sakaiproject.event.impl.ClusterEventTracking.postEvent(ClusterEventTracking.java:330)
              at org.sakaiproject.event.impl.BaseEventTrackingService.post(BaseEventTrackingService.java:286)
              at org.sakaiproject.event.cover.EventTrackingService.post(EventTrackingService.java:133)
              at org.sakaiproject.tool.assessment.ui.bean.delivery.DeliveryBean.submitForGrade(DeliveryBean.java:1627)
              at org.sakaiproject.tool.assessment.ui.bean.delivery.DeliveryBean.submitForGrade(DeliveryBean.java:1555)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.lang.reflect.Method.invoke(Method.java:498)
              at org.apache.el.parser.AstValue.invoke(AstValue.java:247)
              at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:267)
              at org.apache.jasper.el.JspMethodExpression.invoke(JspMethodExpression.java:74)
              at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
              at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
              at javax.faces.component.UICommand.broadcast(UICommand.java:387)
              at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:475)
              at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:756)
              at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82)
              at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
              at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
              at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
              at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
              at com.corejsf.UploadFilter.doFilter(UploadFilter.java:135)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
              at org.sakaiproject.util.RequestFilter.doFilter(RequestFilter.java:411)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
              at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:720)
              at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:466)
              at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:391)
              at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:318)
              at org.sakaiproject.jsf.util.SamigoJsfTool.dispatch(SamigoJsfTool.java:318)
              at org.sakaiproject.jsf.util.JsfTool.doPost(JsfTool.java:260)
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
              at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:720)
              at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:466)
              at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:358)
              at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:318)
              at org.sakaiproject.tool.impl.ActiveToolComponent$MyActiveTool.forward(ActiveToolComponent.java:513)
              at org.sakaiproject.portal.charon.SkinnableCharonPortal.forwardTool(SkinnableCharonPortal.java:1488)
              at org.sakaiproject.portal.charon.handlers.SiteHandler.doToolBuffer(SiteHandler.java:1227)
              at org.sakaiproject.portal.charon.handlers.SiteHandler.bufferContent(SiteHandler.java:1061)
              at org.sakaiproject.portal.charon.handlers.SiteHandler.doSite(SiteHandler.java:490)
              at org.sakaiproject.portal.charon.handlers.SiteHandler.doGet(SiteHandler.java:266)
              at org.sakaiproject.portal.charon.handlers.SiteHandler.doGet(SiteHandler.java:154)
              at org.sakaiproject.portal.charon.handlers.WorksiteHandler.doPost(WorksiteHandler.java:69)
              at org.sakaiproject.portal.charon.SkinnableCharonPortal.doPost(SkinnableCharonPortal.java:1172)
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
              at org.sakaiproject.util.RequestFilter.doFilter(RequestFilter.java:460)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
              at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
              at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
              at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
              at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
              at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
              at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
              at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
              at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
              at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
              at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
              at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
              at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502)
              at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
              at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
              at java.lang.Thread.run(Thread.java:748)
      

      In SAM-3012 / SAM-2669, the event names utilized in Samigo were refactored in an effort to standardize the format. This caused an unintended NPE being generated in the logs because there is a listener (SamigoObserver.java) that's listening for three specific events that happen on submission of an assessment. This listener is responsible for unpacking the relevant data from the Event, and passing it off to SamigoETSProviderImpl.java to facilitate email notifications.

      The problem is that originally, SamigoObserver was listening for "sam.assessmentSubmitted" (as well as two others that aren't relevant for this ticket). This event was only fired in one specific place, which guaranteed that the necessary data would be packed into the Event's resource attribute.

      However, in SAM-3012 / SAM-2669, "sam.assessmentSubmitted" was removed in favour of the previously existing "sam.assessment.submit". This historical event is generated in another place as well; so now SamigoObserver is being triggered for "sam.assessment.submit" events that it was originally not intended to listen for. It tries to parse out the data it needs from the Event's resource attribute and NPEs in the stringToHashMap() method.

      We can't just NPE-proof SamigoObserver.stringToHashMap() because it then will just blow up in SamigoETSProviderImpl when it goes to retrieve values in the HashMap it expects to be there.

      The solution is to create a new (standardized format) event for the one specific place that was previously firing the "sam.assessmentSubmitted" event, and also change SamigoListener to listen for this new event rather than the generic "sam.assessment.submit" event.

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  bjones86 Brian Jones
                  Reporter:
                  bjones86 Brian Jones
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  2 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:

                    Git Source Code