Set up Sling Dynamic Include

Last update: 2024-01-25
  • Topics:
  • APIs
    View more on this topic
  • Created for:
  • Experienced
    Developer

A video walk-through of installing and using Apache Sling Dynamic Include with AEM Dispatcher running on Apache HTTP Web Server.

 Transcript

In this video we’ll take a look at installing, configuring and using Sling Dynamic Include. Sling Dynamic Include, or SDI, is a project that was contributed by Cognifide to the Apache Sling Project. The purpose of SDI is to dynamically replace sling includes with either server side includes, edge side includes or even JavaScript includes. This can be a very powerful tool, especially in the context of aem’s dispatcher, as it pushes cache life granularity to the component level versus the page level. After watching this video, make sure to read through the Sling Dynamic Include documentation site I have pulled up here. It’s currently on the Cognifide get help repository but will be moving to the Apache Sling documentation site. It does a great job of going through installing, using and configuring sling dynamic include along with all the various options.

So let’s try SDI out. For this example, I have created a simple time component that just prints the current time. I have created a page that has a text component, a custom time component which just prints the time out and another text component. As you can see I’m accessing this directly on the aem publisher so as I refresh this page the time changes. What we’ll want to do is figure out how we can allow all the page to be cacheable except for our time component which you want to be dynamic and update based on the current time. The first thing we’re going to do is download and install the Sling Dynamic Include bundle. For this we’ll head over to the Apache Sling downloads page, and if we scroll to the bottom, we have the Dynamic Include module. We’ll want whatever the latest version is. Currently it’s 3.0.0. So let’s download this bundle. We’ll want to make sure that we install this on all of the instances that will be using SDI. If you look through the SDI documentation, it will actually show you how to include this as part of your application bundle as well, but for this video we’ll manually upload it.

Lets verify that it’s active. And there we go. It’s active. So lets go to our config manager then click on the web console and go to OSGi configuration and again let’s just search for dynamic include. We have a configuration and a synthetic resource filter. You can ignore the synthetic resource filter. What we want to do is add configurations. So lets click on this. And we have a number of options. Keep in mind that this is a OSGi configure factors so you can have multiple configurations for SDI. The first option is to enable this particular configuration for SDI. The second is the base path that this configuration will listen to and because our page is under content, that should be fine but if we wanted to we could even scope it further. So let’s do that. Resource types will be the resource types of the sling includes that this will apply to. For this, what we’ll want to do is understand the resource type that’s used for this time component. And we can find this by going to the CRXDE lite and drilling down into the page definition and we have our time component here and if we take a look at our properties we’ll see that the resource type is simple component content time. So I’ll just copy and paste this. Do note you can have multiple sling resource types for a single configuration. For this we’ll just use the single one. Our include types are Apache SSI, ESI and Javascript. We’ll be using the SSI for this example. Adding a comment simply adds a comment within the markup that’s generated that specifies what is being included. This will be debogging this a little bit in the resource code to see how this works. Let’s enable this. The filter selector is a software that will be added to the htp request for this particular component resource. We’ll leave this as nocache and we’ll look at how we need to configure dispatcher to respect it. Component TTL is a time to live cache header. This will work on versions of dispatcher version 4.1.11 or greater. I will be taking a look at this after we look at how the nocache is handled. Required header defines a request header that must be present for SDI to be invoked. You typically want to leave this as the default as you only want requests coming from the dispatcher or the web distributor to be processed by SDI. By default, SDI ignores request with get parameters so you can specify parameters that should be ignored. This allows SDI to process requests that contain get parameters specified in this list. For this case, we don’t need any of the these so let’s leave this blank. And, lastly, include path rewriting runs the included path through the resource revolver map function if you have any sort of mappings in place. And, since we don’t have any of these in play we’ll leave this unchecked as well. Based on this configuration, any components included with the simple components content time resource type that exists under the base path of content we retail us en should be SSI’d in with the nocache selector. Let’s check this out. We’ll save this.

Retail site that is being served through my local dispatcher so I’m accessing this on aem publish local which goes through a very basic dispatcher configuration and I will go to the time page and you will see that we don’t even have our time component. So everything else is rendering correctly, however the time component doesn’t exist. What we can do here is right click and view page source. And as we scroll down here we’ll see we have a SDI inlcude and this is because we checked the comment check box. And it’s saying that it is going to try to include content we retails us en time jcr content root responsivegrid time with the nocache selector, and we can see that it is rewriting this component because this is the actual SSI directive that our Apache web server will try to evaluate. So the question is why is Apache web server not actually evaluating our include. And, the reason is very simple. It’s because we have actually enabled includes on our Apache web server. Let’s jump over to our terminal here. I will move over to my configuration directive for the Apache web server. First thing we’re gonna do is enable the module for includes. So, for this we can search for our include module and as you can see it’s commented out here. So let’s just go ahead and comment this. The next thing we need to do is enable includes on our vhost. Let’s edit our vhost file.

We have fairly generic vhost file here in order to enable includes for this vhost script you do two things. First is to add include to the options. Secondly, we need to specify what files types we want to be processed by our includes filter. So we set the add output filter includes and we only want .html files to be processed, so let’s save that. We’ll restart our Apache web server. Now let’s head back to our browser and let’s refresh this. There we go. Now we’re actually getting this component included by the web server and, again, we can take a look at the source. I’ll search for SDI as that’s part of the comment here. And we can see now that we have a comment that says that we have an SDI include being invoked and we actually have all of the .html from that time component being written directly into the page. So this is excellent. But let’s go back, keep in mind the time. Let’s refresh the page again.

And you’ll see the time is not updating. And this is because the outer part of the page is being cached as we’d want it to, but, unfortunately, this SDI include is also being cached. Let’s just take a look at the source and see what’s happening. The SDI include is including this particular url and we have this nocache select that we specified in OSGi config and the intent here is this nocache selector is going to tell dispatcher that this request shouldn’t be served from the cache. Again, our problem is we never told dispatcher about this particular selector. We have to go back to our dispatcher config.

We need to go down to our rules section and we have to add another rule that specifies that anything with the nocache selector should not be cached. So I have this nocache rule. It says anything that matches *.nocache.html deny cache deny.

We have to restart our Apache web server anytime we make changes to our dispatcher configurations so let’s do that.

Refresh. So, 11:27:23. And I keep refreshing.

And there we go. It is bypassing the cache for this request however the page itself is being served from the cache. So, this is excellent.

The other thing we can do is we can go from having a nocache at all to setting a TTL, or a time to live on the cache resource. We can verify this by going to the cache in the file system. So here’s my doc group. We can look in content we retail us en time and add jcr content but we don’t have the path down to the time component. So we know that it’s not being served from cache at all. We can also check out the cache html for the time page. We can search for our SDI and we can see that the cached file has our comment and it has the SSI include that Apache web server will interpret and request whenever this particular file is served up. So what we’ve done is we’ve affected the cached everything except for the time component which we now include. Okay. Let’s check out how we use the other feature that we talked about earlier which is the TTL feature. Let’s go ahead and go back to our configuration manager, look our configuration again. We’ll go ahead and modify our existing configuration and what we’re gonna want to do now is set a TTL. And this is going to be in seconds so I’m going to set a ten second TTL so, affectively, every ten seconds a new version of the component should be served up. So our second increment should be approximately 10 seconds based on how fast I hit refresh. For this, we want to make sure that we don’t have any sort of conflicts with our nocache selector here so I’m going to set this just a ttl. This actually has no baring on anything. This could foo.

It could be bar. But I’m going to set it at ttl just to make it clear. But this is being cached at a ttl. So, I’m going to save this. And just to make sure that everything is clean, I’m going to leave everything in the cache.

There we go. Our cache is clear. Go back to our page. So now we’re trying to set the ten second ttl on this particular page. Let’s go ahead and refresh this the first time. So, ten seconds from now we should have a new number but between ten seconds it should stay the same. So about ten seconds has passed already. So we’ll refresh this. We should expect to see that this number has changed to about 40. I’m going to keep refreshing just to make sure I hit that ten and no luck. Let’s check this out. The reason for this is because even though we set the ttl on SDI, we haven’t specified the ttl to be enabled in our dispatcher config. What we can do is go back to our dispatcher at any time down below our rules section that we were just at. Let me search for this. We have a section called enable ttl and remember this is introduced in dispatcher 4.1.11. Set this to one to enable the ttl based caching. So let’s go ahead and save this. Restart Apache. Let’s just go ahead and delete the cache again. Make sure everything is clear.

Refresh the first time since the cache is clear, we’ll get a full page load. So we’ve got 32:49. As I refresh this, it’s the same. And now we hit about ten seconds and it’s changed again so I can keep refreshing and about ten seconds, depending on how my refresh hits it, we should see that this has changed. So this component has a ten second cache life within the dispatcher cache. So, as you can see this is an incredibly powerful tool. You can use this for highly dynamic content. You can use this for partially dynamic content. You can use this for including resources that might not be naturally flushed via the stat level in the hierarchy. So this is an incredibly powerful tool. I definitely suggest you keep this in mind when building out and designing your content architecture for your aem sites implementations as it can do wonders for increasing your cache life of your pages.

NOTE

Ensure the latest version of AEM Dispatcher is installed locally.

  1. Download and install the Sling Dynamic Include bundle.

  2. Configure Sling Dynamic Include via the OSGi Configuration Factory at http://<host>:<port>/system/console/configMgr/org.apache.sling.dynamicinclude.Configuration.

    Or, to add to an AEM code-base, create the appropriate sling:OsgiConfig node at:

    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
        xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
        jcr:primaryType="sling:OsgiConfig"
        include-filter.config.enabled="{Boolean}true"
        include-filter.config.path="/content"
        include-filter.config.resource-types="[my-app/components/content/highly-dynamic]"
        include-filter.config.include-type="SSI"
        include-filter.config.add_comment="{Boolean}false"
        include-filter.config.selector="nocache"
        include-filter.config.ttl=""
        include-filter.config.required_header="Server-Agent=Communique-Dispatcher"
        include-filter.config.ignoreUrlParams="[]"
        include-filter.config.rewrite="{Boolean}true"
        />
    <!--
    * include-filter.config.include-type="SSI | ESI | JSI"
    * include-filter.config.ttl is # of seconds (requires AEM Dispatcher 4.1.11+)
    -->
    
  3. (Optional) Repeat the last step to allow for components on locked (initial) content of editable templates to be served via SDI as well. The reason for the additional configuration is that locked content of editable templates is served from /conf instead of /content.

    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
        xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
        jcr:primaryType="sling:OsgiConfig"
        include-filter.config.enabled="{Boolean}true"
        include-filter.config.path="/conf"
        include-filter.config.resource-types="[my-app/components/content/highly-dynamic]"
        include-filter.config.include-type="SSI"
        include-filter.config.add_comment="{Boolean}false"
        include-filter.config.selector="nocache"
        include-filter.config.ttl=""
        include-filter.config.required_header="Server-Agent=Communique-Dispatcher"
        include-filter.config.ignoreUrlParams="[]"
        include-filter.config.rewrite="{Boolean}true"
        />
    <!--
    * include-filter.config.include-type="SSI | ESI | JSI"
    * include-filter.config.ttl is # of seconds (requires AEM Dispatcher 4.1.11+)
    -->
    
  4. Update Apache HTTPD Web server’s httpd.conf file to enable the Include module.

    $ sudo vi .../httpd.conf
    
    LoadModule include_module libexec/apache2/mod_include.so
    
  5. Update the vhost file to respect include directives.

    $ sudo vi .../vhosts/aem-publish.local.conf
    
    <VirtualHost *:80>
    ...
       <Directory /Library/WebServer/docroot/publish>
          ...
          # Add Includes to enable SSI Includes used by Sling Dynamic Include
          Options FollowSymLinks Includes
    
          # Required to have dispatcher-handler process includes
          ModMimeUsePathInfo On
    
          # Set includes to process .html files
          AddOutputFilter INCLUDES .html
          ...
       </Directory>
    ...
    </VirtualHost>
    
  6. Update the dispatcher.any configuration file to support (1) nocache selectors and (2) enable TTL support.

    $ sudo vi .../conf/dispatcher.any
    
    /rules {
      ...
      /0009 {
        /glob "*.nocache.html*"
        /type "deny"
      }
    }
    
    TIP

    Leaving the trailing * off in the glob *.nocache.html* rule above, can result in issues in requests for sub-resources.

    /cache {
        ...
        /enableTTL "1"
    }
    
  7. Always restart Apache HTTP Web Server after making changes to its configuration files or the dispatcher.any.

    $ sudo apachectl restart
    
NOTE

If you are using Sling Dynamic Includes for serving edge-side includes (ESI), then make sure to cache relevant response headers in the dispatcher cache. Possible headers include the following:

  • “Cache-Control”
  • “Content-Disposition”
  • “Content-Type”
  • “Expires”
  • “Last-Modified”
  • “ETag”
  • “X-Content-Type-Options”
  • “Last-Modified”

Supporting materials

On this page