The idea for this talk came for different reasons. First of all, being a trainer I noticed that even after a training people seem to struggle over the fact on where to start with a brand new project. The training team has acknowledged this fact and was thinking about a way on how to integrate this into the existing training schedule or provide a separate "small" modular training for it. Another reason this seemed to be more important recently was with the whole 4.5 migration effort - as we supervised a few projects being migrated with the currently available means we saw that it can be confusing on how to apply our migration strategy if the project is not set up in a way as we usually recommend it. This was a first attempt to see whether this base setup is really an issue and whether it should be part of the training and how.
Participate and give feedback
You are completely new to the Magnolia world and believe this is too advanced already? You have already implemented a project and want to share your experiences with this setup or your own setup? You have attended a training and were also struggling with your first setup? Do not hesitate to add a comment and discuss whatever you would like to see us do in the future concerning this matter. This is your chance to influence a big part of the possible future trainings and/or workshops!
Digging into the presentation
I will reiterate why we believe certain settings and behaviors are best practice or where it depends on your project scope what you could benefit from most. This will follow the main setup of the presentation.
Base Setup - Starting from scratch
- Use maven archetypes if possible.
- Module QuickStart
→ This will help you speed up the initial setup process. There are a lot of things that need to be repeated and are always the same for projects, this is where the archetypes can facilitate starting a new project from scratch. You start with creating a project, which will create a parent POM and the webapp (overlaying
magnolia-empty-webapp). When you go inside the newly created project folder and relaunch the
mvn archetype:generatecommand, it will automatically add the newly created modules to the parent POM as modules.
If you cannot use maven, make sure you read the official Documentation about modules and follow the same JAR structure and behavior so you can make full use of the Magnolia features.
- Module QuickStart
- General layout: parent POM, webapp, module(s), theme(s).
→ Separate your modules (a theme is nothing but a special module) according to their features. A standard layout that we often use is: webapp / theme module / module containing all the templates and their model classes.
- Blog post series: "Don't build / configure / deploy Magnolia, ..."
- Don’t build Magnolia: build your projects.
- Don’t configure Magnolia: let your projects configure it.
- Don’t deploy Magnolia: deploy your project.
→ These blog posts will really help you structure your projects better and speed up the development process.
- Before even starting the project:
- Security concept
→ Who will be able to see which templates? Who can publish and who can only edit or create pages? Do you have users that will only be allowed to access and modifiy specific parts of the website? These are all questions that you should clarify before starting the project. Depending on what your project consists of, this might be crucial on how you set up everything.
→ How many languages will be available for the site? What is going to be the default language? Which language (most often the default language which contains ALL of the content) is going to be the fallback language? This is also a very crucial question that needs to be answered before starting your projects. It is quite a big effort to change the default language after content has already been entered to make sure the content is not lost.
- Security concept
→ One of the key files for Magnolia. If you have read through the previously mentioned blog posts, you have certainly stumbled upon the
magnolia.propertiesfile in Don’t deploy Magnolia: deploy your project. What you also might have realized through this is that you don't need multiple webapps for deploying the same project on different servers. Read through the Single war file, multiple configurations page on our official documentation site. There are so many things that you can configure there that will help you with the development process. Adding additional bootstraps, setting the persistence manager, automatic updating/bootstrapping and so on. Beware of the fact that you should only commit and release changes that are meant for the productive state! More details on the
magnolia.repositories.homelocation will follow under "Developping in your IDE".
→ You have one or more public sites that need to be updated? You need to scale up your system with another public instance? No problem, you can find the setup for subscribers under Configuration > Subscribers. This is a classic case for different bootstraps in different environments in the single war deployment. You certainly would not want to have the productive site subscribers in your testing environment.
- Site configuration / definitions
→ The skeleton of your site(s). Very important settings for your site take place here. Domain names, workspace mappings, i18n configuration and the heart of your site: the template prototype and availability. If you want something to be configured globally, you are in the right place.
→ Especially in multilanguage setups, the messages files will save you some time later on if you set them up early. If your customer is not happy with a labelling, you can change its text in a proper localization file instead of having to change the template's configuration.
- How does the mechanism work?
- Extends & extends-override
- Documentation: Technical Guide - Configuration mechanisms
Documentation: Reference - Controls
→ Extending is like using a softlink for copying existing configuration. If both of the definitions are of the same type (for example
info.magnolia.module.templatingkit.templates.pages.STKPage) then you can "copy" a whole definition just by extending the desired node. Then you can add additional nodes to it or modify existing ones. By using the property
overrideyou can also override the extending configuration and hence remove tabs that you do not need for example.
Comparison of stkLargeArticle to stkArticle Usage of extends=override Since stkLargeArticle is extending stkArticle, we know that they are identical apart from the fact that stkLargeArticle contains a table of content and has a different dialog and title. If it had not been extended, one would have had to go through all of the properties and compare them to each other to find the difference. In this case we do not want the hidden control to be saved in JCR with stkExtrasPureLinkList. This can be achieved with extends=override. Note that if the hierarchy were deeper, extends=override is valid from the point where you put it. This can be useful if you want to extend stkArticle for example, but only make it possible to add stkTextImage as a component. See the example mentioned on the Documentation: Technical Guide - Configuration mechanisms page.
- Absolute and relative paths
→ Think about the scope of the extends when trying to decide whether you want to use relative or absolute paths. While it is easier to maintain absolute paths in the long run it can be useful to use relative paths as well. Imagine you have a custom dialog with a few tabs and the second tab extends the first one with
"../tabMain". Now you notice you have not moved the dialog in the correct folder, this means you would have to change the extends path if it were absolute. Since it is closed in itself and only extending relatively, you can simply move your dialog definition to the correct place. However, since you also set the dialog somewhere in a component or page, you will have to change the corresponding path there as well. Absolute paths can be terrible to read on smaller screens, but at least they provide you with an accurate information on where to find the extended node.
- What happened to "reference" and why was it abandoned
→ First of all, if you find a property called "reference" anywhere, you can simply replace it with "extends". Extends was introduced in Magnolia 4.3 (extends-override in Magnolia 4.4) and is supposed to replace the old "reference". You could only reference an entire tab or a single control, not a full definition (dialog, component, ...) and furthermore you had to take the referenced node as is. This meant that you could not add / modify / remove anything for this item. Extends gives you this flexibility which makes it a very powerful feature.
- Extends & extends-override
- Do not reinvent the wheel!
- Use existing configurations: STK, Form, ...
→ Hey, somebody else already did half of my work, why should I have to do it again? Extended form with additional fields, no problem! You can reuse logic, dialog definitions, the template script and much more. This will all speed up your development process.
- Extend even if there are no (current) local changes!
→ It was just mentioned how extending can speed up your development process, so why should you do something seemingly unnecessary that means more work for you now? It is simple, out of experience one can assume that change requests will come at a later point during development. Even if it only means having to change the title of stkArticle to "Content Template" for example. Or adding another available component to the list. These are all preparations so you do not have to fear change requests later on. They might seem small (such as changing a title) but if you do not extend now, you either have to do it later, which means you will have to go through all the websites and change the template from "stkArticle" to "myOwnArticle" or you have to inject a different i18nBasename or title for stkArticle, which is always ugly since on the next update, the configuration for stkArticle might get newly bootstrapped again and overwrite your modifications!
- Use existing configurations: STK, Form, ...
→ There is a bug in the search result template script? Ah, it was fixed for the next version of STK. STK is updated, you automatically get the fix as well (unless you use your own template script). There is a new feature that got added? You get it too, for "free".
No automatic notifications
|→ As you can see, getting new features without having to do anything can be an advantage but also a disadvantage if you have to follow a strict guideline for example.|
→ If similar templates use extends, it is easier to tell what the actual difference is in the end. New people will have an easier time getting into the project when they do not have to analyze property per property to make out what really defines the difference between two configurations.
|Automatic updates for bugfixes|
|Easy injection of own messages||Need to implement STK / other messages|
Developing in your IDE
- Module structure
→ If you cannot use the maven archetypes, make sure you can follow the standard module structure. Lots of things are automated like bootstrapping configs and samples, so if you follow the standard setup you will not have to write everything (such as version handling,...) from scratch.
- Bypass feature / Resources
→ If you have ever tried doing a lot of changes in the CSS on a running instance, you know how long it can take sometimes until the highlighter is completely loaded for styles.css. It is a huge file already with more than 6000 lines of code, so all in all this cannot be the preferred way of modifying css and js. The answer to this is: make use of the bypass feature. When your resource is already in the repository, you can navigate to its path, edit the item, go the advanced tab and check "Bypass". This will allow you to modify the ressource in question from within your development environment - provided you have the correct module ready and checked out.
- Templates vs. Inplace Templates
→ While it is inviting to modify the template scripts directly in the templates workspace (can be found under Templating Kit > Templates), this can be also "dangerous" if the changes or additions are not backported into your project. Unlike the resources from above, the template scripts do not have to exist in the repository in order to modify them from your IDE. So why have the inplace templates after all? A few very good reasons: first of all, you will simply be able to look at the templates of a running instance. In case there is a problem, you can already analyze if there is an issue with the corresponding template script without having to set up a complete IDE workspace to check out the project. Another good reason for the inplace templates are release cycles. It can happen that your slogan changes or you have to add an extra div to make the layout work. In bigger projects you cannot simply trigger a bugfix release that quickly since it has to pass QA, tests and so on. So for this you can make use of the inplace templates where you can already change it in the production environment, but then you should not forget about backporting those changes to your project. Otherwise it might be that these modifications are overridden with the next update.
- Export configurations
→ Especially in the beginning you will be doing a lot of dual work from within your IDE as well as the running instance, such as setting up a new page template. Once you are done with a configuration and it works, make sure that you export it to XML and put this so called bootstrap file into the corresponding module of your project. It is of good use to do so after every setup you have completed out of the simple reason that the next configuration might trash your instance, you cannot recover it and then you have to start from scratch again.
- Clean backup repository outside of webapp
→ Start up your initial project, let everything install (, enter the license for EE) and then shut down the server again. Go to the location where your repositories are stored and simply copy/duplicate the whole folder. Like this you can create a pristine environment that you can fall back to. While developping you might trash the whole configuration so Magnolia does not start anymore (faulty filter configurations can break the filter chain) and then you will be happy to not have to go through the whole install process again. Ideally this should not contain your modules yet, like that you can test the installation of your modules.
Another reason why it is recommended to keep the repositories outside of the webapp is that if you are developing with Eclipse and you delete the repositories from there, it will keep a version of the files. This could blow up .metadata very quickly depending on what your project contains.
DefaultModuleVersionHandler→ Ideally your modules will either use or extend the
DefaultModuleVersionHandlerso there are a few tasks that are automatically executed for you when installing or updating your project. You should definitely check out these two VersionHandlers to understand what is happening in general during an installation or update.
→ If you extend the
DefaultModuleVersionHandlerbut you want to add specific installation tasks for your module to the standard tasks, then the correct place to do this would be the extra install tasks. A typical task to add here would be the
TemplatesInstallTaskto make sure your template scripts get uploaded into the templates workspace. The only time you would want to override the basic install tasks is if you need to register your own data type (
RegisterNodeTypeTask) . In that case this needs to be done before the rest of your module's configuration is bootstrapped, especially if you create definitions or sample data that are of this new type). If you fail to do so, you might get errors during the installation of your module that will tell you that Magnolia does not know this type.
As the wording proposes, these functions are only executed on installation, not on update.
getDefaultUpdateTaskvs single deltas
→ In the constructor of your ModuleVersionHandler you can register deltas. This means you can register a single or a set of tasks to execute on an update to a specific version. This also means you can do an update from 1.1 to 1.3 and all the tasks from "1.1 to 1.2" and "1.2 to 1.3" are executed sequentially. Typically these tasks contain property changes / additions, bootstrapping a newly added definition and so on. On the other hand you have the possibility to add default update tasks that are executed on every update. Typically this is either empty (default behavior) or it contains tasks like
TemplatesInstallTaskin order to bring your template scripts up to date every single time (see Developing in your IDE > Templates vs. Inplace Templates from above for reference as to why this is needed). E.g.: You certainly do not want to have a task in there that changes the SMTP server address every single time you update the module.
In the future you will find a series of attachments regarding this topic here. For now there is the presentation from the unconference.