AEM Maven project structure

An quick look at an AEM Maven project’s structure and sub-projects and what they’re used for.

So I want to take you through an AEM project structure. AEM projects are multi-module maven projects, so they are comprised of a top level reactor project that kind of binds everything together in a number of sub projects. And we’ll go through these and discuss what their purposes are. Because this is a multi-module maven project, there is a top level of a reactor project, and this is represented by the top level pom.xml file. The main purpose is to define any common plugins, dependencies, versions, or variables that might be used throughout any of the sub projects and have a centralized place to manage all of those. So lets jump into the maven sub projects. Let’s start top to bottom, so we’ll start with the “all” project. The purpose of the “all” project is to generate a single deployable artifact that represents this project. So drilling into this, is really just a POM file and if you inspect the POM file, all it really does is define a bunch of embeds that are put into an “all” AEM package zip file. So essentially, anything that we want deployed as part of this application needs to be enumerated and embedded in this “all” package. So this commonly includes the AEM package for the ui.apps project, the ui.content project. This also includes the OSGi bundled jar file, as well as any OSGi configuration, AEM packages. And this can also include other “all” packages provided by vendors or third parties. Next up is the analyze project. And just as a small disclaimer, this project may go away in the near future and become absorbed by the “all” packages pom.xml. So this project is just a simple POM file and all it does is configure the execution of the AEM analyzer Maven plugin. And this plugin simply scans the generated artifact of the “all” package, which is that final deployable artifact AEM, and verifies that all lines stay in best practices. And this plugin is pretty handy because it will often call out non-obvious issues that could cause problems when deploying to amazon cloud service. But as I mentioned before, if you don’t have this project, it’s very likely that it has been absorbed into the all projects pom.xml, and you can go in there and check for that if need be. Next up is the core package. And this is the Maven sub project that generates the project OSGi bundle, which is the Java artifact that’s deployed, the AEM. core project contains Java code, Java unit tests and stacked resources, Just like you would imagine. But it’s also worth calling out that this will generate an OSGi bundle, a jar file rather than just a regular jar. And that’s what allows us to be deployed and run in AEM. And the way it generates an OSGi bundle, is by using the BND Maven plugin to generate their requisite manifest file that describes the OSGi bundle. So if you need to make advanced configurations to the bundles manifests, you can do that in the core project’s pom.xml under the BND Maven plugin configuration.
Obviously, this Java project can contain your usual Java abstractions and patterns like POJO, static util classes, builders, et cetera. But this is also where AEM’s idiosyncratic java implementations are added as well. So often in AEM projects, much of your code will be developed as OSGi components or services, or sling models. And there’s a number of other Java base building blocks provided by the JCR, or API, or sling, or even AEM, that you can implement and build upon.
Next is dispatcher. So this is pretty straight forward as it contains all of the allowed Apache web server and AEM dispatcher module configuration that will be deployed as part of this app. So com configurations added to this project, our Apache vhosts configurations for various domains that the app might serve, as well as dispatcher cache, and filter allow/deny rules.
Just a quick call out, If you’re going to be using Apache modules, make sure that they’re listed on AEM supported module list. If they aren’t on the supported list, then obviously they won’t be able to work. next up is the it.test sub project. So this is the name implies. It contains integration tests for the application. And integration tests are Java based tests that interact with a running AEM environment over HTTP. You can think of IT tests as sort of a middle ground between the unit tests, which are run in the context of Maven build against mock AEM abstractions. And the full-blown UI tests, which use headless browsers to interact with a running AEM instance.
Next up is the UI apps project, and this contains two main things. The first is code or config that belong under apps. And this is most commonly AEM component implementations. So these could be core component proxies, custom AEM components, including the HTL scripts, dialogues, client libs, or any of the allowed overlays of libs that allow you to tweak some of the out of the box pavior. So basically, this is anything that is considered code or code based configuration that isn’t Java code, since, Java code should be in the core project we discussed earlier. There’s one notable exception, which is OSGi configurations, which should be put in the UI config project, we’ll discuss later. And then second, OCC index definitions should also be in the UI apps project. So anything under the /occ index folder should also be added to this project as well. The UI app structure project as the name implies, is coupled with the ui.apps project, and the UI structure project defines the JCR structure under apps that the ui.apps project deploys notes into. this is a little bit confusing at first, but it becomes increasingly important in complex applications, that include vendor package that also deploy under apps. Since, when defined correctly, the UI app structure definitions help AEM understand how to safely install multiple packages to apps without overwriting one another. It’s worth noting that the repository structure definition, which is a numerated in the pom.xml, is almost always updated in tandem with changes to the ui.apps projects, filter.xml file.
The UI configuration project contains OSGi configuration notes organized by remote. And they should be placed in “/apps/<project_name>/osgiconfig/config” with any attached run mode. As mentioned before, this is the exception to the rule that all nodes under apps belong in the ui.apps project. Keep in mind, OSGi configurations should be defined using the new JSON format. And that AEM is cloud service environment, and secret value variables can be used.
The UI content project can be thought of as the counterpart to the UI apps project and contains all node definitions that are not part of /apps or /occ index. Be careful about what you put in the UI content project though. The reason for this is, this entire multi-module Maven project that we’re talking about is managed in git. However, the nodes in the UI content package technically can get changed at runtime, in AEM, because they’re not under apps, and anything not under apps can get changed on runtime. So depending on how the UI content package’s “filter.xml” is defined, you can run into problems where either; On every code deploy, changes made to these nodes at runtime, are overwritten by what’s in git.
Or Changes made at runtime, end up superseding the changes made to this project managing git. Resulting in changes defined by developers not getting deployed to AEM. Which again, depending on what they are, can result in problems. So a good rule of thumb is to minimize the content definitions in the UI content package, and to ensure that anything defined in it is not modifiable in AEM at runtime. And that’s usually by applying permissions to it. That said, this project is a great place to put some more complex configurations and baseline structures such as AEM site template types under the conf folder. Or even more complex baseline content structures, such as baseline folders or pages that have some extra properties that become too arduous to manage using repo in it.
Next up is the ui.frontend project, and we’ll only touch on this briefly, but the intent of this project is to create a place where all front end code for AEM can be developed using the modern front end tool chains. And then the resulting artifacts are copied into defined client lib folders in the UI apps project under the /apps folder. Lastly, is the UI test project, which contains any UI tests that you might create. This project leverages the WDIO, JavaScript UI automation testing framework, and spins up a headless browser using Docker to execute these tests. These tests are usually best reserved for testing things that rely on client side JavaScript, CSS application, or even pathing click-throughs, as it does use the headless browser to mimic the experience of true web browser execution.
Okay, well, that’s about it for our review of the AEM multi-module Maven project structure. Obviously, there are many details we didn’t cover here, but I hope this helps you get your bearings and understand what all the sub projects are and what they’re used for. -