Enric Naval was presented with an opportunity he couldn't pass up: a plump scholarship, real-world programming experience, and some spending money. All he had to do was give up sixteen measly hours each week for some work-study in the college's IT department. How hard could that be? According to this figure I just made up, 63% of college students spend at least that much time each day in World of Warcraft.

Enric's job didn't seem too hard, either. All he had to do was maintain the Student Registration System. How hard could that be? It's not like the Student Registration System really changes; all it needs is student, class, and schedule data imported. Maintenance should be a cinch.

At least, that might be the case at other colleges. At WTFU, the "Student" adjective in "Student Registration System" refers to not only the target users of the system, but also to those who build and maintain it. And really, who better to build and maintain a production application than those armed with only a few programming classes under their belt?

Designed and built by an army of work-study students, the complexity of this system is unimaginable. Like an old painting, the system has been written, re-written, and re-written again, all without ever starting on a fresh canvas. With no versioning in place, thousands of code files lay side by side with several different MAKE files, the newest of which is named "new-new2-BUILDSITE-real." But despite all this, the system worked. And it needed to continue working.

One of the areas that Enric maintained was the redirect logic. The idea was that, instead of using something like navigation, a central Servlet would be used to redirect users to the appropriate page following an action. For example, users working on the start page in activity 5 woud get redirected to the task page for the same activity. Then they would get redirected to the process page. All fairly simple stuff ... in concept.

Somewhere down the line, one of the developers had an idea "guess" redirect users, meaning that if another developer accidently misspelled a page name, the user would still go to the correct page instead of seeing a page-not-found error. This, and several other similar features, led to redirect logic spanning several thousand lines of code.

Presented to you is only a small subset of this redirect code. The entire redirect servlet is but a drop in the bucket in the context of the Student Registration System ...

public final class RedirServlet extends CoreServlet { public final void doGet(HttpServletRequest req, HttpServletResponse res) { res.setContentType( "text/plain" ); res.setStatus(res.SC_MOVED_TEMPORARILY); res.setHeader( "Location" , doRedirect(req.getServletPath())); } private final String doRedirect( String page ) { //default redir String redir = "/unknown_redir.jsp" ; //find/return redirect (1-4 unused) int n = parseRedirIndex( page ); if ( n == 5 ) { redir = doRedirect_a5 ( page ); } else if ( n == 6 ) { redir = doRedirect_a6 ( page ); } else if ( n == 7 ) { redir = doRedirect_a7 ( page ); } else if ( n == 8 ) { redir = doRedirect_a8 ( page ); } /* snip */ else if ( n == 51 ) { redir = doRedirect_a51( page ); } else if ( n == 52 ) { redir = doRedirect_a52( page ); } else if ( n == 53 ) { redir = doRedirect_a53( page ); } return redir; } private final String doRedirect_a5( String page ) { if ( page.equals( "a5-intro.jsp" ) ) return "../activity-5/a5-introduction.jsp" ; else if ( page.equals( "a5-introduction.jsp" ) ) return "../activity-5/a5-introduction.jsp" ; else if ( page.equals( "a5-intorduction.jsp" ) ) return "../activity-5/a5-introduction.jsp" ; /* snipped a whole bunch of cases */ else if ( page.startsWith( "a5-task-2-3" ) ) return "../tasks/r.jsp?redir=../activity-5/task-2-4.jsp" ; else if ( page.startsWith( "a5-task-3-3" ) ) return "../tasks/r.jsp?redir=../activity-5/task3/taskC.jsp" ; /* snipped a whole bunch more cases */ else if ( page.equals( "conclusions-5.jsp" ) ) return "../conclusions3/incident5.jsp" ; else if ( page.equals( "conclusions-specific-5.jsp" ) ) return "../conclusions3/incident5.jsp" ; else if ( page.equals( "conclusions-general-5.jsp" ) ) return "../conclusions3/incident5.jsp" ; else return "../activity-5/process.jsp" ; } /* snipped several thousand lines */ public final String doRedirect_a53( String page ) { if ( page.equals( "a53-intro.jsp" ) ) return "../activity-generic/introduction53.jsp" ; /* snip */ else if ( page.startsWith( "professor-data" ) ) { if ( page.endsWith( "-class.jsp" ) ) return "/classes/index.jsp" ; else if ( page.endsWith( "ES102-class.jsp" ) ) return "/classes/class-ES102.jsp" ; /* snip */ else if ( page.endsWith( "PS442-class.jsp" ) ) return "/classes/class-PS442.jsp" ; } else return "../activity-53/reprocess2.jsp" ; } }