Pipelines need Valves
In which I articulate preliminary design for uPortal rendering pipeline plugins to enable branching and terminating in redirects.
This solution is now coded and deployed to MyUW test tiers and configured to apparent good effect.
The generic, re-usable, composable components in this solution potentially applicable across many uPortal adopters are now proposed for inclusion in the uPortal codebase for uPortal 4.2, though some issue tracker issues (which each link Pull Requests with actual code).
- UP-4259 : Add
- UP-4260 : Add
- UP-4261 : Add
- UP-4263 : Add
What problem are you trying to solve?
When the user is using the Bucky theme (via an associated
bucky profile), when the Rendering Pipeline is called upon to render a not-just-one-portlet-maximized experience, the request handling needs to escape the confines of the Rendering Pipeline and simply redirect the browser to go back to that lovely new
In the MyUW redesign, there's an awesome new responsively-designed web UI implemented in AngularJS. This UI replaces the traditional invocation of the uPortal rendering pipeline to render a bunch of portlets in
NORMAL window state on your portal landing page, instead implementing that landing page in straight up
JSON web services for its dynamism.
In the new world, there's a
/web path that is this awesome new AngularJS stuff, and there's a
/portal path that is the classic uPortal rendering pipeline portlets stuff. And hey, there are some great portlets in this portal and some interactions from the AngularJS front end navigate to them, rendering them one-at-a-time in
MAXIMIZED window state.
So, there will be a period of time in which the portal is both supporting a Classic experience using
mUniversality and none of this AngularJS stuff (very conservative, same experience you may know and love in MyUW today) and a Beta experience using a new forked-from-
Respondr theme (named "
Bucky"). Within the Beta experience, some interactions are handled client-side by awesome new AngularJS stuff, and many interactions are simply to render a traditional portlet, maximized.
However, no intended interactions under
Bucky involve using the uPortal rendering pipeline to do anything other than render a single portlet at a time. Any request to render a dashboard-style multiple-normal-window-state portlets page under
Bucky is running amok and should be redirected back to the lovely new AngularJS landing page implementation.
BranchingRenderingPipeline that either continues the pipeline processing down the traditional pipeline or branches to a
RedirectRenderingPipelineTerminator, depending upon whether the
Request represents one for the new Bucky theme or not AND on whether the
Request represents one for a mosaic/dashboard of portlets or one for a single portlet.
Things to Code
falsePipe(also an IPortalRenderingPipeline)
<HttpServletRequest> >) :
Predicates to be consulted to determine whether to proceed with the
falsePipe. If all of the
true, then proceed down the
truePipe, otherise proceed down the
(May need other dependencies for parsing the theme name out of the
true if the active profile
fname for the user session in the
Request has exactly the injected
(It turns out you can read the active profile fname out of the request via a
UserPreferencesManager which can be handily
@Autowired injected by Spring.)
true if the request addresses just one portlet,
(It turns out you can figure out the focused-ness of a request by asking a
UrlSyntaxProvider about its
UrlState, and that that Provider can be handily
Issues a redirect.
String): the path to which to redirect.
Locally in MyUW, we pop in this new
BranchingRenderingPipeline into our locally customized renderingPipelineContext.xml Spring configuration, plugging in a
ProfileFNamePredicate configured to predicate on the profile having the
fname "bucky" and a
FocusedOnOnePortletPredicate, with the logic properly wired up through the static factory methods in
Predicates, and then routing to the existing rendering pipeline as one pipe and to the newly added
RedirectRenderingPipelineTerminator (redirecting to
/web) as the other pipe.
- These objects are eminently unit testable.
- All of these Java classes are suitable for inclusion in Apereo uPortal itself and can be useful to other uPortal adopters. While this can (will!) be configured to Solve the Local Problem, the technology isn't Bucky-specific and becomes part of the rendering pipeline plumber's toolbox for solving the next problem, quite possibly without having to touch any of this Java.
- This solution requires zero implementation-local changes to uPortal Java files, which means no changes (to framework Java files) to hang out in the MyUW repo and require future merging.
- This should Just Work in a pretty deep way, in that edge cases (specifying a different profile via parameter at login? Addressing a portlet by fname? Using a print window state?) eventually amount to asking the Rendering Pipeline to render and so all those edge cases result in either simply proceeding through the traditional rendering pipeline or can be shunted back to AngularJS where they belong.
- a locally forked Spring context file. That's probably a necessary reality -- those files are configuration after all.
- I'm probably supposed to be thinking in terms of rendering pipeline
Components rather than whole rendering pipelines, but it's more straightforward doing this logic before things get turned into streams and events and all that stuff.
This design does feel a wee bit like