Upload
lydia-miles
View
236
Download
2
Tags:
Embed Size (px)
Citation preview
Sakai Enterprise Integration and Tool Enhancements at Georgia
Tech
Dan McCallum
Developer, Unicon, Inc
1. Overview
2. Source Control
3. Banner Integration
4. User Identity
5. Email Whitelisting
6. Other Enhancements
Overview
• Implementation planning session in Atlanta Dec 11 – 13, 2006.
• Development Feb – Mid-April, 2007.• TSquare (https://t-square.gatech.edu/) pilot
launched May 11, 2007.• Georgia Tech OIT and CETL provided SA,
DBA, QA, SME resources • Unicon and Aeroplane Software provided
development, SA, QA
Project Outline
• Content migration from WebCT (see http://bugs.sakaiproject.org/confluence/display/CONF07/Migration+Tool+for+WebCT+4.1)
• Automated Sakai worksite and enrollment provisioning from Banner (approx 5000 course sections for summer)
• Unique user identity management requirements• Other Sakai enhancements/extensions:
– Worksite email whitelist publication– TSquare Skin– Assignment auto-submission– SIS-related UI extensions– Improved support for cross-service database
transactions
Development Targets
Source Control
Source Code Overlay
A
communitycommunity
B
trunktrunk
B
A
locallocal
B
export
checkout
SVN
• Avoid complex vendor drops (burned in the past, esp 2.1 -> 2.2)
• Expected to make few modify community code
• Wanted to be able to easily identify modified community code
The Theory
• Just doesn’t scale• By the end of phase 1, just about every update
would fail or at least it seemed that way• Difficult to merge community maintenance
releases– Local mods always win– Updates don’t include latest community code
• Have to remember to check in “baseline” code prior to committing local mods
• Annoying, continual svn:ignore updates
The Reality
SCM – Phase 2
• Migrated to a conventional vendor drop approach tracking 2.4.x maintenance branch
• Manageable so long as drops are frequent and/or changesets are small.
Vendor Code Drop
A
vendorvendor
trunktrunk
B
locallocal
B
checkout
SVN
A
A
currentcurrent
dropXdropX
B
A
B
merge
Banner Integration
Architecture
GaTech Course Models – Independent
• Banner CourseSection == Sakai worksite• 75% of Banner courses
Independent Course Handling
JMS
CourseSection X
Crn: 11111Term: 200701
CourseSection Y
Crn: 22222Term: 200701
CourseSection Z
Crn: 11111Term: 200701
Banner
Send Course Create XML Messages
Worksite XCrn: 11111Term: 200701
Worksite XCrn: 11111Term: 200701
Handle Course Create XML Messages
Worksite YCrn: 22222Term: 200701
Worksite YCrn: 22222Term: 200701
Worksite ZCrn: 33333Term: 200701
Worksite ZCrn: 33333Term: 200701
Sakai
GaTech Course Models - Linked
• Courses have some dependency relationship known to the SIS
• E.g. a lecture with several “linked” labs• Grades typically reported under one course
within a linked set• 10% of Banner courses• Linkage data not conveyed in LDIS
messages
Linked Course Handling
JMS
CourseSection X
Crn: 11111Term: 200701
CourseSection Y
Crn: 22222Term: 200701
CourseSection Z
Crn: 11111Term: 200701
Banner
Send Course Create XML Messages
Worksite XCrn: 11111Term: 200701
Worksite XCrn: 11111Term: 200701
Section YCrn: 22222
Section YCrn: 22222
Section ZCrn: 33333
Section ZCrn: 33333
Handle Course Create XML Messages
Sakai
links
GaTech Course Models – Cross-Listed/Combined
• Multiple Banner CourseSections treated as a single entity, except for grading
• Two variations:– Cross-listed, i.e. “equivalencies”– Combined, i.e. ad-hoc peer course relationships
• 5%+ of Banner Courses
Crosslist Group XXID: XLSXX200701
Cross Listed Course Handling
JMS
CourseSection X
Crn: 11111Term: 200701
CourseSection Y
Crn: 22222Term: 200701
CourseSection Z
Crn: 11111Term: 200701
Banner
Send Course Create XML Messages
Worksite XXCrn: XLSXX200701Term: 200701
Worksite XXCrn: XLSXX200701Term: 200701
Section XCrn: 11111
Section XCrn: 11111
Section YCrn: 22222
Section YCrn: 22222
Handle Course Create XML Messages
Sakai
Section ZCrn: 33333
Section ZCrn: 33333
Candidate Enhancements
• Composite cross-listed worksite titles• Sakai-to-Banner gradebook push• Performance improvements• CM-backed implementation• Automated linked CourseSection handling• Sakai dashboarding, deep-linking from portal• Automated worksite aliasing
User Identity
GaTech AuthN
• Two basic problems:– Users with multiple login IDs need access to a single Sakai account– Identifier type ambiguity in UserDirectoryService and
UserDirectoryProvider method arguments
• Custom UserDirectoryProvider– Sets UserEdit.eid to a GUID read from LDAP– Heuristics for guessing at lookup key (i.e. user ID) types– Extends refactored JLDAPDirectorProvider in contrib (more flexible
attribute mapping, pluggable connection mgmt, parameter scrubbing, etc etc etc)
• Would be nice to see first-class distinction between authentication, integration and display user IDs
GaTech AuthZ
• Users’ access to Sakai controlled by LDAP “entitlements” attributes
• Entitlements enforced even if user authenticated via CAS
• GaTechUserDirectoryService.authorizeUserLogin(User)
• Custom AuthenticationManager post-processes user authentication
GaTech AuthN/AuthZ: LoginTool
doPost()
<<AuthenticationManager>>: GaTechUserAuthnComp
authenticate(:Evidence)
user : UserEditisGtDirectoryId(eid)
<<UserDirectoryService>>: GaTechUserDirectoryService
authenticate(:Evidence)
: AuthenticationManager
getUserByEid(eid)
<<UserDirectoryProvider>>: GaTechUserDirectoryProvider
authenticate(eid,pass)
getUserId(eid)
false
getUserByAccountId(user,eid)
new()
setEid(directoryId)
[LDAP search]
[set other attrs]
authenticateUser(eid,user,pass)
[LDAP bind]
true
user :: Authentication
authorizeUserLogin(user)
authorizeUserLogin(userLoginId)
[LDAP search]
true: Authentication
GaTech User Attributes
• GaTechUserDirectoryService.getUserByImsId(String) – New finder method for Banner services– Does UserDirectoryService interface need more generic search capability?
• Confidential user attributes– Masked by default in LDAP– Sakai tools responsible for “unmasking”, e.g. to disambiguate students in
the Gradebook• Minor mapping issues
– Wiki stores EIDs in short db columns – had to trim values provided by LDAP
– User mail-to email address not identical to lookup addresses• UserMembership Tool
– Doesn’t scale for large, remote user bases– Postponed tool deployment
Email Whitelisting
Exporting Worksite Email Addrs
• Need to publish addresses at which Sakai worksites receive email
• Implemented as passive services with an Axis wrapper
• Web services polled periodically by GaTech mail exchanger
SiteMailQueryService
/** * An interface defining a way to ask Sakai for all of the email * addresses that belong to its sites. */public interface SiteMailQueryService {
/** * * @return a Collection of objects that represent the email addresses of all
the sites in Sakai * * @see SiteMailAddresses */ Collection<SiteMailAddresses> getCurrentSiteMailAddresses();
}
GaTechSiteMailQueryServiceFacade
public interface GaTechSiteMailQueryServiceFacade {
/** * * @param sessionId the id for a currently valid Sakai * session, used as an authorization token * @return an array of all the email addresses assigned to * all the sites in Sakai * @throws AxisFault */ public String[] getCurrentSiteMailAddresses(String
sessionId) throws AxisFault;
}
Other Enhancements
Brand Application• Continuity of the Georgia Tech brand to Sakai
Brand Application• Elegant navigation
Brand Application• Cross browser consistency
Service Decorators
• Gradebook and Assignments• An alternative to extending or directly modifying concrete
service implementations• Results in more portable extensions – across institutions
and across Sakai versions• For example, schools already running a custom AssignmentService impl could reuse the Georgia Tech feature add without modifying either their code or BasicAutoSubmitAssignmentService
• Still need to modify components.xml, which usually involves a rebuild of that service
Assignment Auto-Submission
• Draft assignments automatically submitted as a side-effect of querying AssignmentService for Submissions
• Auto-submission boundary determined by “Accept Until” Assignment attribute (i.e. Assignment.closeTime).
• Optional – instructors can choose canonical or auto-submit mode when placing tool
• Another service wrapping exercise
Wrapping AssignmentServicepublic abstract class DecoratableAssignmentService implements
AssignmentService {
protected AssignmentService assignmentService;
public void setAssignmentService(AssignmentService assignmentService) { this.assignmentService = assignmentService; }
public AssignmentEdit addAssignment(String context) throws PermissionException { return assignmentService.addAssignment(context); }
public AssignmentContentEdit addAssignmentContent(String context) throws PermissionException { return assignmentService.addAssignmentContent(context); }
// etc etc etc…}
Injected delegate
pass-through
pass-through
Wrapping AssignmentServicepublic class BasicAutoSubmitAssignmentService extends DecoratableAssignmentService implements
AutoSubmitAssignmentService{
private boolean shouldAutoSubmitByDefault;
public AssignmentSubmission getSubmission(String submissionId) throws IdUnusedException, PermissionException { if (shouldAutoSubmit()) { AssignmentSubmission submission = assignmentService.getSubmission(submissionId); if (submission == null) { return null; } Assignment assignment = submission.getAssignment(); // is the assignment close time after now, // or is the assignment already submitted? if (assignment.getCloseTime().after(TimeService.newTime()) || submission.getSubmitted()) { return submission; } else { submit(submission, assignment.getCloseTime()); return assignmentService.getSubmission(submissionId); } } else { return super.getSubmission(submissionId); } }
public boolean shouldAutoSubmit() { try { Properties toolProps = ToolManager.getCurrentPlacement().getConfig(); return Boolean.parseBoolean(toolProps.getProperty("autoSubmit")); // the NullPointer exception means the service was called without // executing within a tool context, so we fall back to the default. } catch (NullPointerException npe) { return shouldAutoSubmitByDefault; } }
// ... Etc etc etc …
}
Placement-scopedAuto-submit
behavior
Auto-submit logic
Wrapping AssignmentService
<beans> <bean id="org.sakaiproject.assignment.impl.AssignmentService" class="org.sakaiproject.assignment.impl.DbAssignmentService" init-method="init" destroy-method="destroy" singleton="true"> <property name="memoryService"> <ref bean="org.sakaiproject.memory.api.MemoryService"/> </property> <property name="sqlService"> <ref bean="org.sakaiproject.db.api.SqlService"/> </property>
<!-- snip --> </bean>
<bean id="org.sakaiproject.assignment.api.AssignmentService" class="edu.gatech.sakai.assignment.BasicAutoSubmitAssignmentService" singleton="true"> <property name="assignmentService"> <ref bean="org.sakaiproject.assignment.impl.AssignmentService"/> </property> <property name="shouldAutoSubmitByDefault"> <value>false</value> </property> </bean> </beans>
Std bean config
Decoration
Wrapping Gradebookpublic class GaTechDeleteSuppressingGradebookContextObserver implements EntityProducer, ContextObserver {
private ContextObserver gradebookContextObserver; private EntityProducer gradebookEntityProducer; public void init() { EntityManager.registerEntityProducer(this, null); }
public Entity getEntity(Reference ref) { return gradebookEntityProducer.getEntity(ref); }
public void contextCreated(String context, boolean toolPlacement) { gradebookContextObserver.contextCreated(context, toolPlacement); }
// disabled cascaded deletion by NOT passing this call through public void contextDeleted(String context, boolean toolPlacment) { // do nothing }
// … etc etc etc …}
Technically, needn’t bethe same object
pass-throughs
Disabled cascadeddeletion
SIS Properties - Section Info Tool
Group Properties - Admin Sites Tool
JMX
• Banner services monitored and managed via JMX beans
• Very easy to configure and deploy with Spring and Tomcat
• Except that JMX RMI involves two ports, one of which floats
• Deployed a slightly modified version of a workaround originally published by George Lindholm
JConsole
Ant<property name="jmx.url" value="service:jmx:rmi://localhost:10889/jndi/rmi://localhost:10888/server" />
<target name="startJms" description="Show JMX Cluster state"> <jmx:open url="${jmx.url}"/>
<jmx:invoke name="LDIS:name=JmsMessageReceiver" operation="start"/>
<jmx:get name="LDIS:name=JmsMessageReceiver" attribute="Running" resultproperty="running" echo="false"/>
<echo> LDIS:name=JmsMessageReceiver Running: ${running} </echo></target>
Q&A