Hi All,
Just saw a presentation on LTI (Learning Tools Interoperability), a standard for web services for VLEs/Learning Tools/your favourite acronym implementing SSO and pushing grades around. The premise is that you conform to the standard and you can talk to anyone else that implements it. Looks like there's LTI support on Blackboard, Sakai and Moodle, so the implication is that you could write one module and plug into all of them. There are already php, Java and .NET libraries available, but no perl modules.
Does this sound like something WebWork devs would be interested in?
Website here
http://www.imsglobal.org/lti/
As far as I understand it, Basic LTI is just SSO and Full LTI is SSO + gradebook.
cheers,
Boyd
Hi Boyd,
This does look very interesting.
As you probably know, there is currently interoperability between Moodle and WeBWorK. There is also a Blackboard plugin now in the works, and I believe a project is just getting started at Indiana University to integrate WeBWorK with Sakai.
However, there are all very separate projects, and it would be fantastic to only have to maintain one module to get interoperability between webwork and the major LMS systems. In fact, even if the separate plugins can provide more functionality for those specific systems, it would be nice to have a generic plugin that works for any compliant LMS.
If you have some ideas about how to implement this (or even if you don't ) - I'd suggest starting a conversation about it on the development mailing list, which you can join here:
http://webwork.maa.org/mailman/listinfo/webwork-devel
Jason
This does look very interesting.
As you probably know, there is currently interoperability between Moodle and WeBWorK. There is also a Blackboard plugin now in the works, and I believe a project is just getting started at Indiana University to integrate WeBWorK with Sakai.
However, there are all very separate projects, and it would be fantastic to only have to maintain one module to get interoperability between webwork and the major LMS systems. In fact, even if the separate plugins can provide more functionality for those specific systems, it would be nice to have a generic plugin that works for any compliant LMS.
If you have some ideas about how to implement this (or even if you don't ) - I'd suggest starting a conversation about it on the development mailing list, which you can join here:
http://webwork.maa.org/mailman/listinfo/webwork-devel
Jason
There is also a project underway at UBC to integrate WeBWorK with Blackboard. This is being done at our Centre for Teaching, Learning and Technology (CTLT). I'm not sure of the status, as there is some uncertainty about the future direction vis-a-vis the "official" LMS, and I also suspect that the intersection of the set of WeBWorK users and Blackboard users is empty.
However, such practical considerations have never stood in the way of Corporate IT Decisions(TM).
In any case, I'll try to make sure the folks there are aware of this discussion, if they are not already in the loop.
Hi Djun,
We've got a webwork-blackboard building block that is pretty far along:
http://webwork.maa.org/viewvc/bbplugin/trunk/BuildingBlock_Missouri/
I used a beta version of it this summer and the 2.0 version works well enough, but the 2.1 version has some bugs we need to fix to make it usable, and our student developer left for greener pastures. I think I can fix some of the bugs, and our development group in IT is finding another java developer, but we would be happy to collaborate with the UBC group too.
Jason
We've got a webwork-blackboard building block that is pretty far along:
http://webwork.maa.org/viewvc/bbplugin/trunk/BuildingBlock_Missouri/
I used a beta version of it this summer and the 2.0 version works well enough, but the 2.1 version has some bugs we need to fix to make it usable, and our student developer left for greener pastures. I think I can fix some of the bugs, and our development group in IT is finding another java developer, but we would be happy to collaborate with the UBC group too.
Jason
Great! Thanks, Jason.
I will pass this information along to Andrea and Pan at UBC.
Djun
Hi Jason,
This is Pan from UBC. I'm playing with your building block. I have installed it and set it up. When I try to create an assignment, I got the error below. It doesn't give me much details to do the troubleshooting. I also checked the log files roughly and there is no trace of this exception. Do you know which log I should look at? Do you have any idea? Thanks.
PS: I'm using packaged 2.1 version from SVN (http://webwork.maa.org/viewvc/bbplugin/trunk/BuildingBlock_Missouri/Prod/Webwork_2.1.zip?view=log).
/webwork/create.jsp(54,2) '${webworkUtil.webworkCoursesList}' Error reading 'webworkCoursesList' on type edu.missouri.WebworkUtil
org.apache.jasper.el.JspValueExpression.getValue(JspValueExpression.java:107)
org.apache.jsp.webwork.create_jsp._jspx_meth_c_005fset_005f1(create_jsp.java:444)
org.apache.jsp.webwork.create_jsp._jspx_meth_c_005fif_005f3(create_jsp.java:413)
org.apache.jsp.webwork.create_jsp._jspService(create_jsp.java:118)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
sun.reflect.GeneratedMethodAccessor350.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:162)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:283)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.B2ContextFilter.doFilter(B2ContextFilter.java:121)
sun.reflect.GeneratedMethodAccessor382.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.ContentTypeFilter.doFilter(ContentTypeFilter.java:57)
sun.reflect.GeneratedMethodAccessor381.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.XssServletFilter.doFilter(XssServletFilter.java:138)
sun.reflect.GeneratedMethodAccessor379.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.RequestSessionFilter.doFilter(RequestSessionFilter.java:238)
sun.reflect.GeneratedMethodAccessor378.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.SSLProxyFilter.doFilter(SSLProxyFilter.java:39)
sun.reflect.GeneratedMethodAccessor377.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:567)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:769)
org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:698)
org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891)
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
java.lang.Thread.run(Thread.java:662)
org.apache.jsp.webwork.create_jsp._jspx_meth_c_005fset_005f1(create_jsp.java:444)
org.apache.jsp.webwork.create_jsp._jspx_meth_c_005fif_005f3(create_jsp.java:413)
org.apache.jsp.webwork.create_jsp._jspService(create_jsp.java:118)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
sun.reflect.GeneratedMethodAccessor350.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:162)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:283)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.B2ContextFilter.doFilter(B2ContextFilter.java:121)
sun.reflect.GeneratedMethodAccessor382.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.ContentTypeFilter.doFilter(ContentTypeFilter.java:57)
sun.reflect.GeneratedMethodAccessor381.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.XssServletFilter.doFilter(XssServletFilter.java:138)
sun.reflect.GeneratedMethodAccessor379.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.RequestSessionFilter.doFilter(RequestSessionFilter.java:238)
sun.reflect.GeneratedMethodAccessor378.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
blackboard.platform.servlet.SSLProxyFilter.doFilter(SSLProxyFilter.java:39)
sun.reflect.GeneratedMethodAccessor377.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:269)
java.security.AccessController.doPrivileged(Native Method)
javax.security.auth.Subject.doAsPrivileged(Subject.java:517)
org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:301)
org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:243)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:56)
org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:189)
java.security.AccessController.doPrivileged(Native Method)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:185)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:567)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:769)
org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:698)
org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891)
org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
java.lang.Thread.run(Thread.java:662)
Hi Pan,
As it happens, we have been having the same issue with this version. We are meeting tomorrow to test the 2.2 version, which unfortnunately is not yet in the SVN repository. I'll get back to you after our meeting for an update. Hopefully we can also get the 2.2 version up on the svn tomorrow.
Jason
Is this a moodle bug? or a bug in the WeBWorK plugin module for moodle?
It's the bug in webwork building block. We try to use the building block to bridge blackboard learn and webwork.
Thanks Jason. Fortunately, I have solved this problem by digging the logs. There are some permission settings in bb-manifest.xml that define which host the building block is allow to resolve/connect to. After changing the host to our dev webwork hostname, it works.
However, we found some other bugs, such as:
1. Messages.getLabel('Default.Space') couldn't get " " from messages.properties so that when creating the assignment from webwork, it fails. The exception tells me it's broken around DataTime.parse. I had to print out the value passed to DateTime.parse to figure it out.
2. After creating the assignment from webwork, the icon is missing on the content page and the title for the assignment is showing URL in the text and not clickable.
3. If I try to delete assignment and add it back in, I got error message saying failed to publish data to learn.
That's what I got so far.
Bill Wheeler at Indiana University is also interested in LTI. I think we can modify the existing webservice to handle requests from an LTI instance.
As Jason mentioned we already have this interoperability with moodle and with blackboard, although even here further features would be desirable.
We're definitely interested in pursuing this option.
-- Mike
Dear Boyd (et al.),
At Indiana University Bloomington, we've been using LTI Basic (i.e., LTI 1.0) to authenticate from Sakai to WeBWorK since last September, i.e., the 2011-12 academic year. On the WeBWorK side, the primary new software is a Perl module WeBWorK::Authen::LTIBasic.
We have a test site that other institutions can use to test the LTI interfaces in their local Course Management Systems (e.g., Sakai, Blackboard, Moodle, Canvas, etc.).
For details, please go to the Administrators page in MAA WeBWorK Wiki and look under the Authentication section for the LTI Basic page.
Sincerely,
Bill
At Indiana University Bloomington, we've been using LTI Basic (i.e., LTI 1.0) to authenticate from Sakai to WeBWorK since last September, i.e., the 2011-12 academic year. On the WeBWorK side, the primary new software is a Perl module WeBWorK::Authen::LTIBasic.
We have a test site that other institutions can use to test the LTI interfaces in their local Course Management Systems (e.g., Sakai, Blackboard, Moodle, Canvas, etc.).
For details, please go to the Administrators page in MAA WeBWorK Wiki and look under the Authentication section for the LTI Basic page.
Sincerely,
Bill