Context Aware Configuration Extension | Community
Skip to main content
June 11, 2025
Solved

Context Aware Configuration Extension

  • June 11, 2025
  • 2 replies
  • 504 views

Hello Community

 

We have a required to Customize CA Config where we need to have property in all the CA Configs and use this for our business functionality

 

Example as below. As shown isGlobalPropetry is repeating for N CAConfigs. Is there a way to have this available for any CA Config we will have for both present and the future ones?

public @interface CAConfig1 { @Property(label = "Some label 1", description = "Some description 1", order = 30) String property1(); @Property(label = "Global Property", description = "Some description", order = 50) boolean isGlobalPropetry() default true; } public @interface CAConfig2 { @Property(label = "Some label 2", description = "Some description 2", order = 30) String property2(); @Property(label = "Global Property", description = "Some description", order = 50) boolean isGlobalPropetry() default true; } public @interface CAConfig3 { @Property(label = "Some label 3", description = "Some description 3", order = 30) String property3(); @Property(label = "Global Property", description = "Some description", order = 50) boolean isGlobalPropetry() default true; } . . . . . . . public @interface CAConfigN { @Property(label = "Some label N", description = "Some description N", order = 30) String propertyN(); @Property(label = "Global Property", description = "Some description", order = 50) boolean isGlobalPropetry() default true; }

 

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by user70744

hi @santoshsai 

Had a good idea from @arunpatidar where we can use filters to add a specific property to be available in all the CAs. Attached a sample code which worked. 

Thanks @arunpatidar 

import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.sling.engine.EngineConstants; import org.osgi.service.component.annotations.Component; import javax.json.*; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import static org.apache.sling.engine.EngineConstants.SLING_FILTER_PATTERN; import static org.apache.sling.engine.EngineConstants.SLING_FILTER_SCOPE; @Component(   service = Filter.class,   immediate = true,   name = "CaConfigFilter",   property = {     SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST,     SLING_FILTER_PATTERN + "=" + "^/content/.*/jcr:content.configData.json"   } ) @Slf4j public class CaConfigFilter implements Filter {   private static final String GLOBAL_CONFIG_NAME = "isGlobalConfig";   @Override   public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)     throws IOException, ServletException {     final CharResponseWrapper wrappedResponse = new CharResponseWrapper((HttpServletResponse) response);     chain.doFilter(request, wrappedResponse);     final String originalContent = wrappedResponse.toString();     String configSourcePath = StringUtils.EMPTY;     boolean globalConfigExists = false;     try (final JsonReader jsonReader = Json.createReader(new StringReader(originalContent))) {       final JsonObject jsonObject = jsonReader.readObject();       final JsonArrayBuilder updatedProperties = Json.createArrayBuilder();       for (final JsonValue val : jsonObject.getJsonArray("properties")) {         final JsonObject prop = val.asJsonObject();         final String name = prop.getString("name", StringUtils.EMPTY);         if (GLOBAL_CONFIG_NAME.equals(name)) {           globalConfigExists = true;           final JsonObjectBuilder builder = Json.createObjectBuilder();           for (final String key : prop.keySet()) {             if (!"metadata".equals(key)) {               builder.add(key, prop.get(key));             }           }           builder.add("metadata", createGlobalConfigMetadata());           updatedProperties.add(builder.build());         } else {           updatedProperties.add(prop);         }         if (StringUtils.isBlank(configSourcePath) && prop.containsKey("configSourcePath")) {           configSourcePath = prop.getString("configSourcePath");         }       }       if (!globalConfigExists) {         updatedProperties.add(createGlobalConfigProperty(configSourcePath));       }       final JsonObject modifiedJson = Json.createObjectBuilder(jsonObject)         .add("properties", updatedProperties)         .build();       response.setContentType("application/json");       response.getWriter().write(modifiedJson.toString());     } catch (final Exception e) {       log.error("Error modifying configData JSON: {}", e.getMessage(), e);       response.getWriter().write(originalContent); // fallback     }   }   private JsonObject createGlobalConfigProperty(final String configSourcePath) {     return Json.createObjectBuilder()       .add("name", GLOBAL_CONFIG_NAME)       .add("value", false)       .add("effectiveValue", false)       .add("configSourcePath", configSourcePath)       .add("inherited", false)       .add("overridden", false)       .add("metadata", createGlobalConfigMetadata())       .add("default", false)       .build();   }   private JsonObject createGlobalConfigMetadata() {     return Json.createObjectBuilder()       .add("type", "Boolean")       .add("defaultValue", false)       .add("label", "Global Configuration")       .add("description", "Indicates if this is a global configuration.")       .build();   }   private static class CharResponseWrapper extends HttpServletResponseWrapper {     private final CharArrayWriter charWriter = new CharArrayWriter();     public CharResponseWrapper(final HttpServletResponse response) {       super(response);     }     @Override     public PrintWriter getWriter() {       return new PrintWriter(charWriter);     }     @Override     public String toString() {       return charWriter.toString();     }   } }

2 replies

SantoshSai
Community Advisor
Community Advisor
June 11, 2025

Hi @arung_,

To avoid repeating the same @Property (like isGlobalPropetry) across all Context-Aware Configs (CA Configs) in AEM, inheritance or composition would seem like a natural solution - Unfortunately, Java annotations do not support inheritance the same way classes do. That means you cannot extend or inherit annotation properties directly.

Santosh Sai
Level 3
June 12, 2025

Agree. and we were thinking if there is any good solution for this rather than repeating

user70744Accepted solution
Level 3
June 16, 2025

hi @santoshsai 

Had a good idea from @arunpatidar where we can use filters to add a specific property to be available in all the CAs. Attached a sample code which worked. 

Thanks @arunpatidar 

import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.sling.engine.EngineConstants; import org.osgi.service.component.annotations.Component; import javax.json.*; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import static org.apache.sling.engine.EngineConstants.SLING_FILTER_PATTERN; import static org.apache.sling.engine.EngineConstants.SLING_FILTER_SCOPE; @Component(   service = Filter.class,   immediate = true,   name = "CaConfigFilter",   property = {     SLING_FILTER_SCOPE + "=" + EngineConstants.FILTER_SCOPE_REQUEST,     SLING_FILTER_PATTERN + "=" + "^/content/.*/jcr:content.configData.json"   } ) @Slf4j public class CaConfigFilter implements Filter {   private static final String GLOBAL_CONFIG_NAME = "isGlobalConfig";   @Override   public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)     throws IOException, ServletException {     final CharResponseWrapper wrappedResponse = new CharResponseWrapper((HttpServletResponse) response);     chain.doFilter(request, wrappedResponse);     final String originalContent = wrappedResponse.toString();     String configSourcePath = StringUtils.EMPTY;     boolean globalConfigExists = false;     try (final JsonReader jsonReader = Json.createReader(new StringReader(originalContent))) {       final JsonObject jsonObject = jsonReader.readObject();       final JsonArrayBuilder updatedProperties = Json.createArrayBuilder();       for (final JsonValue val : jsonObject.getJsonArray("properties")) {         final JsonObject prop = val.asJsonObject();         final String name = prop.getString("name", StringUtils.EMPTY);         if (GLOBAL_CONFIG_NAME.equals(name)) {           globalConfigExists = true;           final JsonObjectBuilder builder = Json.createObjectBuilder();           for (final String key : prop.keySet()) {             if (!"metadata".equals(key)) {               builder.add(key, prop.get(key));             }           }           builder.add("metadata", createGlobalConfigMetadata());           updatedProperties.add(builder.build());         } else {           updatedProperties.add(prop);         }         if (StringUtils.isBlank(configSourcePath) && prop.containsKey("configSourcePath")) {           configSourcePath = prop.getString("configSourcePath");         }       }       if (!globalConfigExists) {         updatedProperties.add(createGlobalConfigProperty(configSourcePath));       }       final JsonObject modifiedJson = Json.createObjectBuilder(jsonObject)         .add("properties", updatedProperties)         .build();       response.setContentType("application/json");       response.getWriter().write(modifiedJson.toString());     } catch (final Exception e) {       log.error("Error modifying configData JSON: {}", e.getMessage(), e);       response.getWriter().write(originalContent); // fallback     }   }   private JsonObject createGlobalConfigProperty(final String configSourcePath) {     return Json.createObjectBuilder()       .add("name", GLOBAL_CONFIG_NAME)       .add("value", false)       .add("effectiveValue", false)       .add("configSourcePath", configSourcePath)       .add("inherited", false)       .add("overridden", false)       .add("metadata", createGlobalConfigMetadata())       .add("default", false)       .build();   }   private JsonObject createGlobalConfigMetadata() {     return Json.createObjectBuilder()       .add("type", "Boolean")       .add("defaultValue", false)       .add("label", "Global Configuration")       .add("description", "Indicates if this is a global configuration.")       .build();   }   private static class CharResponseWrapper extends HttpServletResponseWrapper {     private final CharArrayWriter charWriter = new CharArrayWriter();     public CharResponseWrapper(final HttpServletResponse response) {       super(response);     }     @Override     public PrintWriter getWriter() {       return new PrintWriter(charWriter);     }     @Override     public String toString() {       return charWriter.toString();     }   } }