Tag Archives: content architecture

Sling Context-Aware configuration (part 5): thoughts on a production layout

In the past blog posts of this series I outlined some of the capabilities of the Sling Context-Aware configuration. I was focussing on the demo aspect of it, and ignored aspects of it which are relevant when we talk about the use of it in an production environment.

(Note: There is not too much experience using Sling CA Config in wider production use. In this blog post I discuss these based on my experience with the product I gained in many projects; and I assume that it will work. If you have different experience with, I am interested to hear from them!)

For example I placed the configuration editor in /content/ca-config/en/configuration-page, while the configuration itself was located somewhere in /conf. Also the WCM.io editor can only edit the configuration for the context it is located in; that means, that your editor at /content/ca-config/configuration-page cannot modify the configuration applicable to the content context /content/ca-config/en, but you have to have a dedicated configuration editor located in that context.

Let’s stick with /conf in this blog post . Every code and every user which needs to consume configuration has to have read access to /conf; and to make inheritance working, you have to have read access to the configuration you are inheriting from as well. Generally spoken, you need to provide read access to a large part of /conf to all users. Which is typically not a problem.

But if you want to prevent access to certain parts of /conf but still be able to use them as part of Context Aware Configuration you have to trick a bit.
Imagine the case, that you want to store password data for certain backend system in CA-Config. You want to make them read- and writable only to the group which administers this backend access, but not for other users. But nevertheless all users should be able to use this backend service.

In that case the best way is to hide the access to the backend system in an OSGI service which utilizes a service-user to access these CA-Config resource in /conf. Whenever an user access this backend system, he will utilize this service and its service-user to read the configuration, and therefor this region of /conf can be locked down.

In the next blog post I want to show you another aspect of “making CA-Config production ready”: Publishing configuration.

Sling Context-Aware configuration (part 3): using a UI

In the last post I gave you a small tour how you can create your context-aware configuration. And you always used CRXDE Lite to do changes on your configuration. Which is ok for testing and during development, but as this configuration is made to be changed (otherwise we might have put it into OSGI, do you remember?), we need to provide a better way to do it. Something suited also for less-technical users.

Steffen Seifert (of the Adobe partner Pro!Vision) started the project wcm.io and contributed there a lot of interesting stuff and extensions for AEM. And they also developed an editor for CA-Config (http://wcm.io/caconfig/editor/index.html).

Ok, so let’s use it. The integration is very simple:

  • Add the dependency to the io.wcm.caconfig.editor.page package and add it as subpackage to your ui.apps package.
  • Add a static template which uses “wcm-io/caconfig/editor/components/page/editor” as resourceType.
  • And use this template.

(I added these steps to my github example code at https://github.com/joerghoh/cqdump/tree/master/ca-config-example).

When you open this page at /content/ca-config/en/configuration.html, you see all available configurations for this bucket and when you click on the configuration you can edit it (including saving back to the correct location in the repository).

 

 

 

 

Cases like “the user does not have the permission to write this configuration” are also handled gracefully.

So the WCM.io configuration editor gives you a nice way to let users edit configuration without using CRXDE Light.

In the next blog post I want to introduce configuration inheritance which can help you to reduce the amount of configuration work.

Sling Context-Aware configuration (part 2)

Update (April 30th, 2018): I changed the name of the configuration item to align with with future development. Next to this change I also added a few bugfixes in the git repo.

In the last 2 blog (1,2) posts I talked about why a more content-oriented and content-centric way to store configuration is useful. And I also described 2 scenarios in which CA-Config can actually be used. Now I want to demonstrate how Sling Context-Aware Configuration can actually be used.

Let’s take the example from last blog post: For the approval workflow we want to configure the approval group externally via Sling CA-Config, so it can be configured per subtree/page. I use AEM 6.3 here, but it should work with 6.2 as well.

In the next steps I will guide you through the steps required to implement these steps. For reference the complete project is available at https://github.com/joerghoh/cqdump/tree/master/ca-config-example.

  • Create a structure in /conf where you would like to store your configuration. In my example the content lives in /content/ca-config with the subites “en” and “fr”, and for /conf I choose /conf/ca-config/content/.
  • Create a property “sling:configRef” with the value “/conf/ca-config/content” at /content/ca-config/jcr:content/. This links your content to the configuration.

In the CA-Config lingua you created a configuration bucket at /conf/ca-config/content, which is referenced by /content/ca-config.

caconfig-configRefs

And that’s it. Now every lookup through Sling CA-Config will lookup there.

Now let’s create some code which is using such a configuration. I created a DynamicParticipant WorkflowStep named “CaConfigParticipantStepChooser“, which assigns the workflow to a group defined by CA-Config. As you can see there a POJO class “CaConfigParticipantStepChooserConfig” is used to store the config read from CA-Config.

caconfig-wfstep

When you run this code, it will try to lookup the config property “approverGroup” (which is derived from the field name in CaConfigurationParticipantStepChooserConfig), but it returns the default value “admin”, as we haven’t provided any configuration value yet.

Now let’s assume that this workflow step, if it is executed on content below /content/ca-config, should assign the workflow to the group “content-authors“. Create a folder “/conf/ca-config/content/sling:configs” and add a node with the name “de.joerghoh.cqdump.caconfig.workflow.CaConfigParticipantStepChooserConfig“; add the property “approverGroup” and set it to the value “content-authors“.

caconfig-configsetting

To validate this setting there is a small tool in the OSGI webconsole.

  • Goto localhost:4502/system/console/slingcaconfig (in the navigation it’s “Sling” => “Context-Aware Configuration”)
  • enter “/content/ca-config” as content path
  • Enter “de.joerghoh.cqdump.caconfig.workflow.CaConfigParticipantStepChooserConfig” as “Other config name”.
  • And press “OK”.

 

It will display that that for this configuration name a property “approverGroup” with the value “content-authors” can be resolved. Which is exactly what we want.

When you test the workflow now, the workflow will be assigned correctly to the “content-authors” group.

To demonstrate the flexibility of context-aware configuration, let’s create a new folder /conf/ca-config/content/fr/sling:configs, add a node “de.joerghoh.cqdump.caconfig.workflow.CaConfigParticipantStepChooserConfig” and add a property “approverGroup” with the value “contributors“. Additionally add the property”sling:configRef” with the value “/conf/ca-config/content/fr” to the /content/ca-config/fr page. When you start the workflow now on /content/ca-config/fr the workflow will be assigned to the contributors group. And of course this also works for every page below /content/ca-config/fr.

(An important remark here: The paths are choosen arbitrarily. Especially in /conf you are very flexible, and the structure there does not necessarily need to match the structure below /content. I just choose the same structure for a better understanding of this example, and for convenience reason I recommend you to do the same.)

Congratulations, you are now able to use Sling Context-Aware Configuration! You can now freely package /content to move it to another stage, and the per-stage approver groups do not need to be re-adjusted.

But to be honest, this is a very simple way, and it has some drawbacks:

  • You need to use CRXDE to maintain the properties in /conf.
  • The need to create sling:configRef nodes for all buckets.

Let’s try to address these topics another time, in the next blog post.

 

 

 

Information architecture & content architecture

Recently I had a discussion in the AEM forums about how to reuse content. During this discussion I was reminded again at the importance of the way how you structure content in your repository.

For this often the term “information architecture” is used, but from my point of view that’s not 100% correct. Information architecture handles the various aspect how your website itself is structured (in terms of navigation, layout but also content). It’s most important aspect is the efficient navigation and consumption of the content on the website by end users (see the wikipedia article for it, ). But it doesn’t care about aspects like content reuse (“where do I maintain the footer navigation”), relations between websites (“how can I reduce work to maintain similar sites”), translations or access control for the editors of these systems.

Therefor I want to introduce the term “content architecture“, which deals with questions like that. The information architecture has a lot of influence, but it’s solely focused on the resulting website; the content architecture focusses on way, how such sites can be created and maintained efficiently.

In the AEM world the difference can be made visible very easily: You can see the information architecture on the website, while you can see the content architecture within CRXDE Lite. Omitting any details: The information architecture is the webpage, the content architecture the repository tree.
If you have some experience with AEM you know that the structure of the website typically matches some subtree below /content. But in the repository tree you don’t find a “header” node at the top of every subtree of a “jcr:content” node of a page, same with the footer. This piece of the resulting rendered website is taken from elsewhere, but not maintained as part of every page, although the information architecture mandates, that every page has a header and a footer.

Besides that the repository also holds a lot of other supporting “content”, which is important for a information architecture but not directly mandated by it. You have certain configuration which controls the rendering of a page; for example it might control which contact email address is displayed at the page footer. From an information architecture point of view it’s not important, where it is stored; but from a content architecture it is very important, because you might have the chance to control it at a single location, which then takes effect for all pages. Or at multiple locations, which result in changing it for individual pages. Or in a per-subtree configuration, where all pages below a certain page are affected. Depending on the requirement this will result in different content architectures.

Your information architecture will influence your content architecture (in some areas it even be a 1:1 relation), but the content architecture goes way beyond it, and deals with other “*bilities” like “manageability”, “evolvability” (how future proof is the content if there will be changes to information architecture?) or “customizability” (how flexible in terms of individualization per page/subsite is my content architecture?).

You can see, that it’s important to be aware of the content architecture, because it will have a huge influence on your application. Your application typically has a lot if built-in assumptions about the way content is structured. For example: “The child nodes below the content root node form the first-level navigation of the site”. Or “the homepage of the site uses a template called ‘homepage'” (which is btw also not covered by any information architecture, but an essential part of the content architecture).

In the JCR world there is the second rule of David’s model: “Drive the content hierarchy, don’t let it happen”. That’s the rule I quote most often, and even though it’s 10 years old, it’s still very true. Because it focusses on the aspect of managing the content tree (= content architecture), and that you should decide carefully considering the consequences of it.

And rest assured: It’s easier to change your application than to change the content tree! (At least if it’s designed properly. If it isn’t, … It’s even harder to change them both.)