Remote debugging the AEM SDK

Remote debugging lets you hook your Java IDE to a local AEM runtime and step through code execution, inspect variables and evaluate expressions on the fly. Needless to say, this is an incredibly powerful tool for an AEM developer to have in their back pocket. So, let’s check this out. The first thing to do is enable remote debugging on the local AEM runtime. This is done by starting the AEM SDK QuickStart Jar with an additional flag. I actually recommend getting into the habit of starting your local AEM runtime with this parameter, so remote debugging is always at your fingertips. What we’ll need to do, is add the -agentlib flag to the Java command used to start AEM. The only agentlib subparam you may want to change is address, which simply defines, which local port AEM will listen on for debug connections. This can be any available port on your machine. Here we’ll use 5005, as this is fairly standard and typically doesn’t conflict with other applications. Then simply add the -jar flag as usual. Note, that we’ll all be debugging an AEM author instance. AEM publish can be remote debugged as well. If you want to start both AEM author and publish with remote debugging at the same time, you’ll need to have them listen on different ports, by adjusting the address param we just discussed, to avoid conflicts. While waiting for AEM to start up, let’s head over to our IDE. So, most Java IDEs support remote debugging, but each configures this differently. So, review your IDEs’, remote debugging instructions. That said, I’ll quickly show you how this can be done in VS Code, to give you a sense of the raw debugging power it provides. VS Code, being plugin centric, requires the Java Extension Pack, which also includes the Java debugger.
First, let’s open our AEM project VS Code, since this contains the code we want to debug. Second, make sure the exact code to debug in VS Code is deployed to AEM. An easy way to ensure this, is by quickly building and deploying the project to the AEM runtime. If the code is different between the IDE and AEM, even if it’s just a few extra lines void space, it may confuse the debugger, as the line numbers don’t match up and it will make tracing through the code look incorrect. Third, we’ll set up the debugger connection. And again, this step, of course, varies for each different IDE, but the concept and information you need to provide is the same. In VS Code, click the debugger, and if you haven’t previously, create a launch.json file, which is stored in the project’s local dot vs code folder. Open the launch.json and tap the Add Configuration button. Select Java, Attach to Remote Program, which adds a new configuration entry. Let’s update the new configuration’s name to make it clear what we’re connecting to. Add the local AEM runtime’s host, which is localhost. Add the remote debug port AEM is listening on, which is set by the address parameter we passed him when starting AEM. So, 5005. And lastly, create a new key named project name and set this to the Maven project name that contains the Java code to debug, since our Java code is in the core project, the value is aem-guides-wknd.core. The project name config is required by VS Code in order to use watch expressions as we’ll see a little later. If you aren’t sure what your project name is, you can always check this under the Maven Projects panel. Save your changes to launch.json and we’re ready to debug.
We’ll head over to the debug view and select the newly added configuration from the dropdown.
Tap the Run button to connect to AEM and once the debugger is attached to the local AEM runtime, we’ll see a little control bar show up and some of the debug panels start populating with information. I’ll jump over to our core projects Java code and open up the BylineImpl Sling model Java class and add a few breakpoints by tapping the left gutter. What this means is when code execution in AEM hits the lines of code with breakpoints, the code execution will pause and wait for action to be taken in VS Code before resuming. Let’s keep this simple and add a breakpoint in the init PostConstruct method and another in the isEmpty.
Let’s load a page on AEM we know includes a Byline component and when we open the page this Java code is invoked and pauses when a breakpoint line is reached. Notice that the breakpoint has been hit and highlighted indicating code execution has been paused at this point. If we look at our web browser, we can see this as the page load spinner is displayed since we’ve blocked this thread. Again, different IDEs have different remote debug capabilities, but most can show local Java variables and their values and allow for custom watch expressions. Common code flow controls allow you to continue running the code until the next breakpoint. Step over the current line. Step in, which means you can step into method calls. Step out, meaning if you’ve stepped into a method call, you can step back out to the caller. Reset, which basically releases the thread from any further breakpoint obligations and then immediately reattaches. And disconnect, which detaches VS Code from the local AEM runtime completely. So, we’re still at our breakpoint in the init method. Let’s step over this line, so we can see what it sets the image variable to.
Looking at local variables we see it went from null to an ImageImpl object reference.
And our custom watch expression, shows us the image’s source. We can tap the continue button to move on to the next breakpoint, which is in isEmpty. Here, let’s step over each line to see how each isEmpty check is evaluated. At each step of the way, we can see the local variables or create watch expressions as needed to inspect our application state in more detail. Note, that if you keep stepping through eventually you’ll get to code that’s not yours and whose source may not even be available. Typically, if you reach this point, it’s best to continue running the code through to the next breakpoint. Unless, you were specifically looking for something outside of your code base. IDEs typically support Breakpoint management as well, which can be handy for toggling breakpoints on and off or moving a few or all of them.
When you’re finished with debugging, simply disconnect the debugger. Alright, even though in this video we use VS Code to show the power of remote debugging. It’s just as easy to set up for other job IDEs via IntelliJ, NetBeans or Eclipse. So take a spin over to their documentation for setup instructions and start remote debugging your code on AEM. -

The AEM SDK’s local quickstart allows remote Java debugging from your IDE, allowing you to step through live code execution in AEM to understand the exact execution flow.

To connect a remote debugger to AEM, the AEM SDK’s local quickstart must be started with specific parameters (-agentlib:...) allowing the IDE to connect to it.

$ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 -jar aem-author-p4502.jar
  • AEM SDK only supports Java 11
  • address specifies the port AEM listens on for remote debug connections and can be changed to any available port on the local development machine.
  • The last parameter (eg. aem-author-p4502.jar) is the AEM SKD Quickstart Jar. This can be either the AEM Author service (aem-author-p4502.jar) or the AEM Publish service (aem-publish-p4503.jar).

IDE set up instructions

Most Java IDE’s provide support for remote debugging of Java programs, however each IDE’s exact set up steps vary. Please review your IDE’s remote debugging set up instructions for the exact steps. Typically IDE configurations require:

  • The host AEM SDK’s local quickstart is listening on, which is localhost.
  • The port AEM SDK’s local quickstart is listening on for remote debug connection, which is the port specified by the address parameter when starting AEM SDK’s local quickstart.
  • Occasionally, the Maven project(s) that provide the source code to remote debug must be specified; this is your OSGi bundle maven projects project(s).

Set up instructions