For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt, and this page is available as Markdown at https://nhanbe.id.vn/aem/articles/10-authoring-publishing-dispatcher-code-env.md.

Understand the boundaries and execution flow differences between AEM Author, Publish, Dispatcher, and CDN.

AEM - Code Execute flow

Problem statement

Just because code runs on Author doesn't mean it will run correctly on Publish. Do you know the boundaries between these environments?

Note: Sling/Java code still executes on Publish. A CDN like Cloudflare does not execute Sling code; it only caches and serves the responses generated by the Publisher.

Code Execution Flow

  • Publish Environment
  • Author Environment

If a request hits the Publisher, Java code will execute. If a request is served directly from the Dispatcher or CDN cache, Java code will not execute.


Separation of Concerns Across 4 Layers

1. Java / Sling Correctness

Code must run independently on Publish. Check: Sling Models, Servlets, OSGi Services, Schedulers, Event Handlers, ResourceResolvers, and Service Users.

Do not rely on conditions or paths that only exist on Author.

Example:

resolver.getResource("/content/cq:tags/...");

or

resolver.getResource("/conf/...");

These paths or nodes might not exist on Publish.

Just because Author has resources at:

/content/foo
/conf/foo
/content/cq:tags/foo

does not mean Publish has them.


2. Author vs. Publish Content

Author and Publish instances have separate JCR repositories.

Example:

Author initial state:

/content/mysite/en
    title = "Hello"

You update it to:

title = "Hello World"

Author reflects the change immediately, but Publish will still show title = "Hello" until the page is published/replicated.


3. Dispatcher Security & Filters

Example:

@SlingServletPaths("/bin/product")
  • Author directly: http://localhost:4502/bin/product works.
  • Publish directly: http://localhost:4503/bin/product works.
  • Through Dispatcher: https://site.com/bin/product returns 403 or 404.

Reason: The Dispatcher filter blocks requests by default:

/filter {
    /0001 { /type "deny" /url "*" }
}

and /bin/product has not been explicitly allowed yet.


4. CDN & Caching

The caching chain is: Cloudflare (CDN) -> Dispatcher -> Publisher. If content is cached at the CDN or Dispatcher level, requests won't hit the Publisher, so cache invalidation/flushing is required when updating dynamic logic or content.


Tips & Best Practices

  • Add request-correlated logging during development:
log.debug(
    "ProductModel executing. path={}, selector={}, user={}",
    request.getResource().getPath(),
    request.getRequestPathInfo().getSelectorString(),
    request.getResourceResolver().getUserID()
);