Blueprint Developer Manual / Version 2307
Table Of ContentsBasic concept
Fragments of responses generated by the Content Application Engine may depend on a context, for example session data or the time of day. If fragments of a response may not be valid for every request, and responses are cached by reverse proxies (like Varnish or a CDN), it's necessary to exclude those parts from the response and load them separately using techniques like AHAH / Ajax or ESI.
To load the fragments, a link scheme and a matching handler handling the bean's type are needed.
CAE Implementation
In order to support loading of fragments in a generic and almost transparent way, beans are
wrapped in a (com.coremedia.blueprint.cae.view.DynamicInclude
) bean when
they are included in the view layer. Whether the bean is wrapped or not is decided using
Predicate<RenderNode>
implementations that are called with the
current RenderNode
. A RenderNode
represents the
current "self" object and the view it's supposed to be rendered in. If any of the available
predicates evaluate to true, the bean and view is wrapped as described above.
public class DynamicPredicate implements DynamicIncludePredicate { //only use DynamicInclude if view matches. private static final String VIEW_NAME="myView"; public boolean apply(RenderNode input) { if (input == null) { return false; } else if (input.getBean() instanceof MyBean && VIEW_NAME.equals(input.getView())) { return true; } return false; } }
Example 6.3. Predicate Example
The predicate has to be added to a predefined Spring bean in order to be evaluated:
<customize:append id="addMyDynamicPredicates" bean="dynamicIncludePredicates"> <list> <bean id="myPredicate“ class=“DynamicPredicate"/> </list> </customize:append>
Example 6.4. Predicate Customizer Example
Render fragment placeholder
After wrapping the bean, the DynamicInclude
is then rendered by the
Content Application Engine.
DynamicInclude
beans are rendered just as other beans by the Content Application Engine.
By default, the view DynamicInclude.ftl
is used to render the beans. It
will either add a placeholder DOM element that can be used to load the fragment using AHAH, or
an <esi:include>
tag, depending on whether there is a reverse
proxy telling the CAE to do so using the Surrogate-Capability
header.
This is described in the
Edge
Architecture Specification.
Links to dynamic fragments
In order to generate a link for either AHAH or ESI, a separate link scheme must be created for each bean type that should be included dynamically.
If the fragment depends on the context (for example, Cookies, session or the time of day), the
link scheme must have the prefix /dynamic/
(see
UriConstants$Prefixes
) so that a preconfigured interceptor will set all
Cache headers necessary that downstream proxies never cache those fragments. Matching Apache and
Varnish rewrite rules are provided by CoreMedia Blueprint.
@Link(type = MyBean.class,
view = "fragment",
uri = "/dynamicfragment/mybean")
public UriComponents buildFragmentLink(Cart cart,
UriTemplate uriPattern,
Map<String, Object> linkParameters,
HttpServletRequest request) {
UriComponentsBuilder result =fromPath(uriPattern.toString());
//parameter "targetView" needs to be added
result.queryParam("targetView",linkParameters.get("targetView"));
return result.build();
}
Example 6.5. Dynamic Include Link Scheme Example
Handling dynamic fragments
These links have to be handled by using a handler. The handler has to use the
RequestParam
"targetView"
to be able to construct
a ModelAndView
matching the values as originally intended in the
include
including the original bean.
@RequestMapping(value="/dynamicfragment/{mybean}") public ModelAndView handleFragmentRequest( @PathVariable("mybean") String mybean, @RequestParam(value = "targetView") String view) { Object myBean = resolve(mybean); //do not create Page, return bean directly (!) ModelAndView modelWithView = createModelWithView(myBean, view); return modelWithView; }
Example 6.6. Dynamic Include Handler Example
Preserve view parameters for dynamic fragments
When including fragments dynamically expect the same behaviour as for server side includes. This means that the view parameters which may include all kinds of objects need to be passed to subsequent templates.
To preserve these parameters a hashed string representation of the parameters will be appended by
the IncludeParamsAppendingLinkTransformer
as includeParams
query parameter to the asynchronous call.
When receiving the call, the IncludeParamsFilter
will retrieve the view parameters back from the
query parameter.
Note
Custom URI paths, considered by the IncludeParamsAppendingLinkTransformer
may be configured
via cae.link-transformer.uri-paths
property.
A server side secret for the hash generation has to be configured via cae.hashing.secret
property.
Have a look at Table 3.1, “Configuration Properties with Prefix cae” in Deployment Manual for further information.
Warning
If the server side secret for the hash generation is not configured, the CAE generates a secret and prints it to the log. You may copy the secret value to your config. If the secret changes then hashes change and may break HTTP caching.
The following types of view parameters are supported for dynamic fragments:
primitives (
boolean
,int
,float
,long
)String
ContentBeans
Content
Maps and Collections of the above types.
Additional custom types may be configured via the cae.link-transformer.serializer-classes
property.
Caution
For every custom type an IdScheme
registered at the IdProvider
is
presumed.