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;
}
Solved! Go to Solution.
Views
Replies
Total Likes
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();
}
}
}
.
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.
Views
Replies
Total Likes
Agree. and we were thinking if there is any good solution for this rather than repeating
Views
Replies
Total Likes
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();
}
}
}
.