Skip to content

Commit

Permalink
Merge pull request #1050 from drewwills/UP-4964
Browse files Browse the repository at this point in the history
UP-4964:  Fix configuration of BranchingRenderingPipeline on uP5
  • Loading branch information
drewwills authored Nov 22, 2017
2 parents 28a4440 + c876312 commit 57b15da
Show file tree
Hide file tree
Showing 27 changed files with 1,038 additions and 421 deletions.
14 changes: 7 additions & 7 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,13 @@ below.

## Sections

* [Building / Deploying uPortal](building-and-deploying-uportal.md)
* [Implementing uPortal](implement/README.md)
* [uPortal System Administration](sysadmin/README.md)
* [Developer's Guide](developer/README.md)
* [Supported web browsers](SUPPORTED_BROWSERS.md)
* [Accessibility](ACCESSIBILITY.md)
* [Project Committers](COMMITTERS.md)
1. [Building / Deploying uPortal](building-and-deploying-uportal.md)
2. [Implementing uPortal](implement/README.md)
3. [uPortal System Administration](sysadmin/README.md)
4. [Developer's Guide](developer/README.md)
5. [Supported web browsers](SUPPORTED_BROWSERS.md)
6. [Accessibility](ACCESSIBILITY.md)
7. [Project Committers](COMMITTERS.md)

## External Links

Expand Down
15 changes: 8 additions & 7 deletions docs/implement/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
This section covers topics related to implementing the portal: adding your
users, groups, layouts, *etc.*

1. [Authentication](authentication/README.md)
2. [User Attributes](user-attributes/README.md)
3. Groups and Permissions (TBD)
4. Layout Management (TBD)
5. Content (TBD)
6. [Frontend](frontend/README.md)
7. [Security](security.md)
1. uPortal Core Subsystems
1. [Authentication](authentication/README.md)
2. [User Attributes](user-attributes/README.md)
3. Groups and Permissions (TBD)
4. Layout Management (TBD)
5. Content (TBD)
2. [Frontend](frontend/README.md)
3. [Security](security.md)
3 changes: 3 additions & 0 deletions docs/implement/frontend/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Frontend Implementation / Customization
uPortal offers a flexible ability to customize the look and feel of the user experience.

## Topics

* [Skinning uPortal](SKINNING_UPORTAL.md)
* [Configuring the uPortal Rendering Pipeline](RENDERING_PIPELINE.md)
* [Using Angular](USING_ANGULAR.md)
190 changes: 190 additions & 0 deletions docs/implement/frontend/RENDERING_PIPELINE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
# Configuring the uPortal Rendering Pipeline

uPortal implements rendering of complete pages using a _pipeline_: a nested structure of discrete,
pluggable elements that each implement the same Java interface. The word "pipeline" is suitable
because it invokes the concepts of _movement_ and _throughput_, but in software this design is also
known as the [Decorator Pattern][].

The Java interface at the center of the uPortal Rendering Pipeline is `IPortalRenderingPipeline`.
Instances of `IPortalRenderingPipeline` are Spring-managed beans. The primary rendering pipline
bean is assigned an id (in Spring) of `portalRenderingPipeline`. Components in other parts of the
portal (outside the Rendering Pipeline) use this bean (exclusively) to interact with rendering in
the portal.

The `IPortalRenderingPipeline` interface defines only one method:

``` java
public void renderState(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException;
```

## uPortal Standard Pipeline

The "standard" rendering pipeline is the one that comes with uPortal out-of-the-box: by default,
uPortal 5 uses the same rendering pipeline configuration as uPortal 4.3 -- based on an instance of
`DynamicRenderingPipeline` that contains a number of _components_.

The components within `DynamicRenderingPipeline` also each implement a single interface:
`CharacterPipelineComponent`, which itself extends
`PipelineComponent<CharacterEventReader, CharacterEvent>`. (The standard rendering pipeline is
hard-wired for XML/XSLT.) Each component implements a discrete step in the rendering of a page
request.

The standard pipeline includes (as of this writing) the following components (steps):

1. `analyticsIncorporationComponent`
2. `portletRenderingIncorporationComponent`
3. `portletRenderingInitiationCharacterComponent`
4. `themeCachingComponent`
5. `postSerializerLogger`
6. `staxSerializingComponent`
7. `postThemeTransformLogger`
8. `themeTransformComponent`
9. `preThemeTransformLogger`
10. `themeAttributeIncorporationComponent`
11. `portletRenderingInitiationComponent`
12. `structureCachingComponent`
13. `postStructureTransformLogger`
14. `structureTransformComponent`
15. `preStructureTransformLogger`
16. `structureAttributeIncorporationComponent`
17. `portletWindowAttributeIncorporationComponent`
18. `dashboardWindowStateSettingsStAXComponent`
19. `postUserLayoutStoreLogger`
20. `userLayoutStoreComponent`

The order of processing for these pipeline components is essentially _backwards_: bottom to top.

## Using `RenderingPipelineBranchPoint` Beans

uPortal adopters may configure the Rendering Pipeline to suit their needs. Most common use cases
can be satisfied using `RenderingPipelineBranchPoint` beans. Rendering branch points are Java
objects (Spring-managed beans) that tell some (or all) HTTP requests to follow a different path.
Rendering branch points follow the standard uPortal 5 configuration strategy for Spring-managed
beans: if you supply a properly-configured bean of the correct type (_viz._
`RenderingPipelineBranchPoint`) to the Spring Application Context, uPortal will _discover_ it and
_do the right thing_. (uPortal will provide it as a dependency to the components that know what
to do with it.)

uPortal evaluates `RenderingPipelineBranchPoint` beans, if present, in the specified order. If a
branch indicates that it _should_ be followed, it _will_ be followed, and no further branches will
be tested. If no branch is followed, the standard rendering pipeline will be used.

`RenderingPipelineBranchPoint` beans accept the following configuration settings:

| Property | Type | Required? | Notes |
| -------- | ---- |:---------:| ----- |
| `order` | `int` | N* | Defines the sequence of branch points when more than one are present (in which case `order` is required). Branches with lower `order` values come before higher values. |
| `predicate` | `java.util.function.Predicate<HttpServletRequest>` | Y | If the `predicate` returns `true`, the branch will be followed; otherwise the next branch will be tested. |
| `alternatePipe` | `IPortalRenderingPipeline` | Y | The rendering path that will be followed if the `predicate` returns `true`. |

### Examples

The following examples illustrate some typical uses for `RenderingPipelineBranchPoint` beans. Each
of these examples can be configured in
`uPortal-start/overlays/uPortal/src/main/resources/properties/contextOverrides/overridesContext.xml`.

#### Example 1: Redirect Unauthenticated Users to CAS/Shibboleth

This example illustrates a commonly-requested feature: disallow unauthenticated access to the
portal.

``` xml
<bean id="guestUserBranchPoint" class="org.apereo.portal.rendering.RenderingPipelineBranchPoint">
<property name="predicate">
<bean class="org.apereo.portal.rendering.predicates.GuestUserPredicate" />
</property>
<property name="alternatePipe">
<bean class="org.apereo.portal.rendering.RedirectRenderingPipelineTerminator">
<property name="redirectTo" value="${org.apereo.portal.channels.CLogin.CasLoginUrl}" />
</bean>
</property>
</bean>
```

#### Example 2: Integrate uPortal-home

This example illustrates required uPortal Rendering Pipeline configuration for integration with
[uPortal-home][].

``` xml
<bean id="redirectToWebMaybe" class="org.jasig.portal.rendering.RenderingPipelineBranchPoint">
<property name="order" value="1" />
<property name="predicate">
<bean class="org.jasig.portal.rendering.predicates.GuestUserPredicate" />
</property>
<property name="alternatePipe" ref="redirectToWeb" />
</bean>

<bean id="maybeRedirectToExclusive" class="org.jasig.portal.rendering.RenderingPipelineBranchPoint">
<property name="order" value="2" />
<property name="predicate">
<bean class="java.util.function.Predicate" factory-method="and" factory-bean="focusedOnOnePortletPredicate">
<constructor-arg>
<bean class="java.util.function.Predicate" factory-method="and" factory-bean="urlNotInExclusiveStatePredicate">
<constructor-arg>
<bean class="org.jasig.portal.rendering.predicates.RenderOnWebFlagSetPredicate" />
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</property>
<property name="alternatePipe" ref="redirectToWebExclusive" />
</bean>

<!-- if the request is for a simple content portlet, redirect to
uPortal-home to render that portlet statically. -->
<bean id="maybeRedirectToWebStatic" class="org.jasig.portal.rendering.RenderingPipelineBranchPoint">
<property name="order" value="3" />
<property name="predicate">
<bean class="java.util.function.Predicate" factory-method="and" factory-bean="focusedOnOnePortletPredicate">
<constructor-arg>
<bean class="java.util.function.Predicate" factory-method="and" factory-bean="urlInMaximizedStatePredicate">
<constructor-arg>
<ref bean="webAppNameContainsSimpleContentPortletPredicate" />
</constructor-arg>
</bean>
</constructor-arg>
</bean>
</property>
<property name="alternatePipe" ref="redirectToWebStatic" />
</bean>

<!-- Common Predicates -->

<bean id="focusedOnOnePortletPredicate" class="org.jasig.portal.rendering.predicates.FocusedOnOnePortletPredicate" />

<bean id="urlNotInExclusiveStatePredicate" class="org.jasig.portal.rendering.predicates.URLInSpecificStatePredicate">
<property name="state" value="EXCLUSIVE" />
<property name="negated" value="true" />
</bean>

<bean id="urlInMaximizedStatePredicate" class="org.jasig.portal.rendering.predicates.URLInSpecificStatePredicate">
<property name="state" value="MAX" />
</bean>

<bean id="webAppNameContainsSimpleContentPortletPredicate" class="org.jasig.portal.rendering.predicates.WebAppNameContainsStringPredicate">
<property name="webAppNameToMatch" value="SimpleContentPortlet" />
</bean>

<!-- Pipeline Terminators -->

<bean id="redirectToWeb" class="org.jasig.portal.rendering.RedirectRenderingPipelineTerminator">
<property name="redirectTo" value="${angular.landing.page}" />
</bean>

<bean id="redirectToWebExclusive" class="org.jasig.portal.rendering.RedirectRenderingPipelineTerminator">
<property name="redirectTo" value="${angular.landing.page}exclusive/" />
<property name="appender" value="fname" />
</bean>

<!-- Redirect to uPortal-home,
instructing uPortal-home to render a particular portlet statically. -->
<bean id="redirectToWebStatic" class="org.jasig.portal.rendering.RedirectRenderingPipelineTerminator">
<property name="redirectTo" value="${angular.landing.page}static/" />
<property name="appender" value="fname" />
</bean>
```

[Decorator Pattern]: https://en.wikipedia.org/wiki/Decorator_pattern
[uPortal-home]: https://github.com/uPortal-Project/uportal-home
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
*/
package org.apereo.portal.rendering;

import com.google.common.base.Predicate;
import java.io.IOException;
import java.util.function.Predicate;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
Expand All @@ -30,7 +30,10 @@
* proceed down the false branch.
*
* @since 4.2
* @deprecated In favor of {@link RenderingPipelineBranchPoint}, which supports configuration of the
* same components/features in the uP5 style.
*/
@Deprecated
public class BranchingRenderingPipeline implements IPortalRenderingPipeline {

protected final Logger logger = LoggerFactory.getLogger(getClass());
Expand All @@ -51,7 +54,7 @@ public void renderState(final HttpServletRequest request, final HttpServletRespo
// render either the true or false pipe, depending on the trueness or falseness of the
// predicate

if (predicate.apply(request)) {
if (predicate.test(request)) {
logger.trace("Branching to the true pipe [{}].", truePipe);
truePipe.renderState(request, response);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

/** Describes the entry point into the uPortal rendering pipeline. */
public interface IPortalRenderingPipeline {

/**
* <code>renderState</code> method orchestrates the rendering pipeline which includes worker
* dispatching, and the rendering process from layout access, to channel rendering, to writing
Expand All @@ -31,6 +32,6 @@ public interface IPortalRenderingPipeline {
* @param res the <code>HttpServletResponse</code>
* @exception PortalException if an error occurs
*/
public void renderState(HttpServletRequest req, HttpServletResponse res)
void renderState(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
public interface PipelineComponent<R, E> {

/** Get the cache key for the request */
public CacheKey getCacheKey(HttpServletRequest request, HttpServletResponse response);
CacheKey getCacheKey(HttpServletRequest request, HttpServletResponse response);

/** Get the event reader and corresponding cache key for the request */
public PipelineEventReader<R, E> getEventReader(
PipelineEventReader<R, E> getEventReader(
HttpServletRequest request, HttpServletResponse response);
}
Loading

0 comments on commit 57b15da

Please sign in to comment.