LTI-Stealthed tool in assignments: if the admin removes the site from the stealthed tool, and instructor tries to edit the assignment stacktrace

Description

If the admin adds stealthed tools to External Tools, then adds some sites that will be allowed to use the tools, the instructor can then use the external tool through assignments.

In this case, after the instructor has added an assignment, a student submitted, the grade was released, and then the admin removed the site ID from the stealthed tool.

Everything looks good on the student side, with appropriate messages, the student who submitted does see their grade/comment, but the button to launch the external tool is no longer present.

On the instructor side, though, things are not going so well. If the instructor clicks to edit the LTI assignment, the page refreshes, (not opening the assignment), and a message displays “*Alert:* Assignment <assignment name> has submissions.”

Looking in the server logs, there is a stacktrace. I have been having issues uploading videos to Jira, so here is a link in case the upload doesn’t work: https://drive.google.com/file/d/16JaV9172LFtgB-Uz_j6kHmKpQluXCxDp/view?usp=sharing

do you have any suggestions how this could be gracefully handled on the assignments page?

10-Apr-2025 12:03:30.423 WARN [http-nio-20025-exec-309] o.s.c.VelocityPortletPaneledAction.actionDispatch Exception calling method doEdit_assignment java.lang.reflect.InvocationTargetException (Caused by java.lang.NullPointerException: Cannot invoke "java.util.Map.get(Object)" because "tool" is null) java.lang.reflect.InvocationTargetException: null at jdk.internal.reflect.GeneratedMethodAccessor7108.invoke(Unknown Source) ~[?:?] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?] at java.base/java.lang.reflect.Method.invoke(Method.java:569) ~[?:?] at org.sakaiproject.cheftool.VelocityPortletPaneledAction.actionDispatch(VelocityPortletPaneledAction.java:749) [sakai-velocity-tool-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.cheftool.VelocityPortletPaneledAction.processAction(VelocityPortletPaneledAction.java:558) [sakai-velocity-tool-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.cheftool.ToolServlet.doGet(ToolServlet.java:228) [sakai-velocity-tool-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.cheftool.VelocityPortletPaneledAction.doGet(VelocityPortletPaneledAction.java:1086) [sakai-velocity-tool-25-SNAPSHOT.jar:25-SNAPSHOT] at javax.servlet.http.HttpServlet.service(HttpServlet.java:529) [servlet-api.jar:4.0.FR] at org.sakaiproject.vm.ComponentServlet.service(ComponentServlet.java:56) [sakai-velocity-tool-25-SNAPSHOT.jar:25-SNAPSHOT] at javax.servlet.http.HttpServlet.service(HttpServlet.java:623) [servlet-api.jar:4.0.FR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:199) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144) [catalina.jar:9.0.102] at org.sakaiproject.util.RequestFilter.doFilter(RequestFilter.java:451) [sakai-kernel-api-25-SNAPSHOT.jar:25-SNAPSHOT] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:642) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:416) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:321) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:285) [catalina.jar:9.0.102] at org.sakaiproject.tool.impl.ActiveToolComponent$MyActiveTool.forward(ActiveToolComponent.java:508) [sakai-kernel-impl-25-SNAPSHOT.jar:?] at org.sakaiproject.portal.charon.SkinnableCharonPortal.forwardTool(SkinnableCharonPortal.java:1364) [sakai-portal-impl-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.portal.charon.handlers.SiteHandler.doToolBuffer(SiteHandler.java:1284) [sakai-portal-impl-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.portal.charon.handlers.SiteHandler.bufferContent(SiteHandler.java:1118) [sakai-portal-impl-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.portal.charon.handlers.SiteHandler.doSite(SiteHandler.java:546) [sakai-portal-impl-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.portal.charon.handlers.SiteHandler.doGet(SiteHandler.java:311) [sakai-portal-impl-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.portal.charon.handlers.SiteHandler.doGet(SiteHandler.java:209) [sakai-portal-impl-25-SNAPSHOT.jar:25-SNAPSHOT] at org.sakaiproject.portal.charon.SkinnableCharonPortal.doGet(SkinnableCharonPortal.java:786) [sakai-portal-impl-25-SNAPSHOT.jar:25-SNAPSHOT] at javax.servlet.http.HttpServlet.service(HttpServlet.java:529) [servlet-api.jar:4.0.FR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:623) [servlet-api.jar:4.0.FR] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:199) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144) [catalina.jar:9.0.102] at org.sakaiproject.util.RequestFilter.doFilter(RequestFilter.java:501) [sakai-kernel-api-25-SNAPSHOT.jar:25-SNAPSHOT] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144) [catalina.jar:9.0.102] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) [tomcat-websocket.jar:9.0.102] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:168) [catalina.jar:9.0.102] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:144) [catalina.jar:9.0.102] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168) [catalina.jar:9.0.102] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) [catalina.jar:9.0.102] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) [catalina.jar:9.0.102] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130) [catalina.jar:9.0.102] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) [catalina.jar:9.0.102] at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:761) [catalina.jar:9.0.102] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [catalina.jar:9.0.102] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346) [catalina.jar:9.0.102] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:396) [tomcat-coyote.jar:9.0.102] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) [tomcat-coyote.jar:9.0.102] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:937) [tomcat-coyote.jar:9.0.102] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1793) [tomcat-coyote.jar:9.0.102] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) [tomcat-coyote.jar:9.0.102] at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) [tomcat-util.jar:9.0.102] at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-util.jar:9.0.102] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) [tomcat-util.jar:9.0.102] at java.base/java.lang.Thread.run(Thread.java:840) [?:?] Caused by: java.lang.NullPointerException: Cannot invoke "java.util.Map.get(Object)" because "tool" is null at org.sakaiproject.assignment.tool.AssignmentAction.doEdit_assignment(AssignmentAction.java:10600) ~[classes/:?] ... 54 more

Attachments

10
  • 18 Apr 2025, 05:05 PM
  • 18 Apr 2025, 05:05 PM
  • 18 Apr 2025, 05:05 PM
  • 18 Apr 2025, 05:05 PM
  • 16 Apr 2025, 03:11 AM
  • 16 Apr 2025, 03:11 AM
  • 11 Apr 2025, 04:49 PM
  • 11 Apr 2025, 04:44 PM
  • 11 Apr 2025, 04:44 PM
  • 10 Apr 2025, 04:43 PM

Activity

Andrea Schmidt last week

I will set this to verified because the stacktrace is gone, the message displays inside the student’s submission grading page, and I have now tested removing the stealthed tools from the site, then re-adding and had a student submit to the assignment that had not submitted before (that part is not in the video).

Here is a video that shows after a student had been graded, another submitted but was not graded, then the admin removed the stealthed tools. The admin then re-added the stealthed tools and everything is working as expected.

https://drive.google.com/file/d/1BwDECXdRIATNKmY8gsDAZBhVyn1nvQyr/view?usp=sharing

It would be good to have a meeting if anything else can be done to make it obvious to the instructor that the tool has been deleted. Also, I want to note that I did not edit the assignments, I just re-added the site to the same stealthed tools.

If other tests are needed, please let me know.

Wilma Hodges last week

That makes sense. If there is a way to reconnect the same tool, that would be nice, since I could see a scenario where the admin accidentally stealths a tool in a site without realizing that there are submissions. If it isn’t possible to connect a different tool, then a message letting instructors know they can’t do that would be good, so they don’t wonder. Let me know when you’d like to chat about this so we can work out the best way to handle it.

Charles R Severance April 20, 2025 at 1:18 AM

and - We should talk before we write a bunch of impossible improvements. I am happy to improve messages and certainly want to make sure we don’t have a bunch of trace backs. But the way this all work - there is no practical way to put Humpty-Dumpty back together again. My initial feeling is that if the LTI assignment has submissions and the too has been removed, it should not be edited. Perhaps the only recovery is to re-connect the exact same tool to the site. If we start auto-patching stuff it is more likely to break worse and worse. By in a sense freezing it there is a slight chance that we can re-associate the tool with the site (not install a new tool - reconnect the exact same tool). But we need to talk - this is a little too complex to work through in Jira comments.

Andrea Schmidt April 18, 2025 at 5:05 PM

Tested on 26x: https://trunk-maria.nightly.sakaiproject.org/, build: de519265

There is no longer a stacktrace and when grading the assignment, the message displays in the student’s submission:

External tool item is missing or improperly configured.

However, none of the other alerts (or even the Deleted text from Wilma’s suggestions are present. See the following screenshots. do you want a new Jira for those enhancements?

Automation for Jira April 16, 2025 at 3:12 AM

A pull request has been created, "SAK-51359 Adssignments/LTI remove the site from a stealthed tool in a…", you can see it at https://github.com/sakaiproject/sakai/pull/13616

Fixed

Priority

25 Status

Components

Assignee

Reporter

Environment

26x: https://trunk-maria.nightly.sakaiproject.org/, build: 25x: https://qa25-maria.nightly.sakaiproject.org/, build: f3fb9cf5
Created April 10, 2025 at 4:31 PM
Updated 2 hours ago
Resolved April 16, 2025 at 1:55 PM