Using a job scheduler I have to create a json file in the dam that fetch the properties of a content fragment, which is always in the dam
Solved! Go to Solution.
Views
Replies
Total Likes
1. OSGi Service to Process Content Fragment and Save JSON as DAM Asset
This service reads properties from a Content Fragment, converts them to JSON, and uploads the JSON as an asset in the DAM.
@component(service = ServiceA.class, immediate = true)
public class ServiceA {
private static final Logger LOG = LoggerFactory.getLogger(ServiceA.class);
private static final String DAM_JSON_PATH = "/content/dam/generated-json/";
@reference
private ResourceResolverFactory resourceResolverFactory;
/**
* Converts a Content Fragment to JSON and saves it as an asset in DAM
*/
public void processContentFragment(String contentFragmentPath) {
try (ResourceResolver resolver = getServiceResourceResolver()) {
Resource cfResource = resolver.getResource(contentFragmentPath);
if (cfResource == null) {
LOG.error("Content Fragment not found at: {}", contentFragmentPath);
return;
}
ContentFragment contentFragment = cfResource.adaptTo(ContentFragment.class);
if (contentFragment == null) {
LOG.error("Invalid Content Fragment at path: {}", contentFragmentPath);
return;
}
String jsonContent = convertContentFragmentToJson(contentFragment);
saveJsonAsDamAsset(resolver, jsonContent, contentFragmentPath);
} catch (Exception e) {
LOG.error("Error processing Content Fragment: {}", e.getMessage(), e);
}
}
/**
* Converts Content Fragment to JSON
*/
private String convertContentFragmentToJson(ContentFragment contentFragment) throws IOException {
Map<String, Object> data = new HashMap<>();
contentFragment.getElements().forEachRemaining(element ->
data.put(element.getName(), element.getValue().getValue()));
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(data);
}
/**
* Saves JSON as a DAM asset
*/
private void saveJsonAsDamAsset(ResourceResolver resolver, String jsonContent, String contentFragmentPath) throws IOException {
AssetManager assetManager = resolver.adaptTo(AssetManager.class);
if (assetManager == null) {
LOG.error("Could not adapt to AssetManager.");
return;
}
String jsonAssetPath = DAM_JSON_PATH + getJsonFileName(contentFragmentPath);
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(jsonContent.getBytes())) {
Asset asset = assetManager.createAsset(jsonAssetPath, inputStream, "application/json", true);
if (asset != null) {
LOG.info("JSON asset created at {}", jsonAssetPath);
}
}
}
/**
* Generate a unique JSON file name
*/
private String getJsonFileName(String contentFragmentPath) {
return contentFragmentPath.replace("/content/dam/", "").replace("/", "_") + ".json";
}
/**
* Get service user resource resolver
*/
private ResourceResolver getServiceResourceResolver() throws LoginException {
Map<String, Object> params = new HashMap<>();
params.put(ResourceResolverFactory.SUBSERVICE, "content-fragment-service");
return resourceResolverFactory.getServiceResourceResolver(params);
}
}
2. Sling Job to Execute the Service
A Sling Job will call the above service to process Content Fragments.
@component(
service = JobConsumer.class,
property = {
JobConsumer.PROPERTY_TOPICS + "=com/example/jobs/processContentFragment"
}
)
public class ContentFragmentJob implements JobConsumer {
private static final Logger LOG = LoggerFactory.getLogger(ContentFragmentJob.class);
@reference
private ContentFragmentToJsonService contentFragmentToJsonService;
@Override
public JobResult process(Job job) {
String contentFragmentPath = job.getProperty("contentFragmentPath", String.class);
if (contentFragmentPath == null) {
LOG.error("Content Fragment path not provided in job.");
return JobResult.FAILED;
}
LOG.info("Processing Content Fragment: {}", contentFragmentPath);
contentFragmentToJsonService.processContentFragment(contentFragmentPath);
return JobResult.OK;
}
}
3. How to Trigger the Sling Job
A Sling Job can be manually triggered from the Java code, or via a scheduler, workflow, or event listener.
@component(service = ContentFragmentJobTrigger.class)
public class ContentFragmentJobTrigger {
private static final Logger LOG = LoggerFactory.getLogger(ContentFragmentJobTrigger.class);
private static final String JOB_TOPIC = "com/example/jobs/processContentFragment";
@reference
private JobManager jobManager;
public void triggerJob(String contentFragmentPath) {
Map<String, Object> jobProperties = new HashMap<>();
jobProperties.put("contentFragmentPath", contentFragmentPath);
jobManager.addJob(JOB_TOPIC, jobProperties);
LOG.info("Job triggered for Content Fragment: {}", contentFragmentPath);
}
}
However, I would also consider another approach with servlet that will be mapped to some selector. It will allow you to request content fragment path with selector and json extension and get required data without persisting it. For example: /content/dam/cfs/my-cf.consumer-1.json.
This is because AssetManager.createAsset is working in AEM on prem, but it's deprecated in AEMaaCS.
Best regards,
Kostiantyn Diachenko.
Hi @Vodjakxa ,
Let me rephrase your question. You have content fragment and you need to read properties from content fragment and save them as a separate asset (JSON) to the DAM. Is that right?
Then I have the following questions:
1) Are you using AEM on prem or AEMaaCS?
2) Is it supposed that some consumer will get this JSON file from AEM?
Could you please explain your request more detailed?
Best regards,
Kostiantyn Diachenko.
Views
Replies
Total Likes
1. OSGi Service to Process Content Fragment and Save JSON as DAM Asset
This service reads properties from a Content Fragment, converts them to JSON, and uploads the JSON as an asset in the DAM.
@component(service = ServiceA.class, immediate = true)
public class ServiceA {
private static final Logger LOG = LoggerFactory.getLogger(ServiceA.class);
private static final String DAM_JSON_PATH = "/content/dam/generated-json/";
@reference
private ResourceResolverFactory resourceResolverFactory;
/**
* Converts a Content Fragment to JSON and saves it as an asset in DAM
*/
public void processContentFragment(String contentFragmentPath) {
try (ResourceResolver resolver = getServiceResourceResolver()) {
Resource cfResource = resolver.getResource(contentFragmentPath);
if (cfResource == null) {
LOG.error("Content Fragment not found at: {}", contentFragmentPath);
return;
}
ContentFragment contentFragment = cfResource.adaptTo(ContentFragment.class);
if (contentFragment == null) {
LOG.error("Invalid Content Fragment at path: {}", contentFragmentPath);
return;
}
String jsonContent = convertContentFragmentToJson(contentFragment);
saveJsonAsDamAsset(resolver, jsonContent, contentFragmentPath);
} catch (Exception e) {
LOG.error("Error processing Content Fragment: {}", e.getMessage(), e);
}
}
/**
* Converts Content Fragment to JSON
*/
private String convertContentFragmentToJson(ContentFragment contentFragment) throws IOException {
Map<String, Object> data = new HashMap<>();
contentFragment.getElements().forEachRemaining(element ->
data.put(element.getName(), element.getValue().getValue()));
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.writeValueAsString(data);
}
/**
* Saves JSON as a DAM asset
*/
private void saveJsonAsDamAsset(ResourceResolver resolver, String jsonContent, String contentFragmentPath) throws IOException {
AssetManager assetManager = resolver.adaptTo(AssetManager.class);
if (assetManager == null) {
LOG.error("Could not adapt to AssetManager.");
return;
}
String jsonAssetPath = DAM_JSON_PATH + getJsonFileName(contentFragmentPath);
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(jsonContent.getBytes())) {
Asset asset = assetManager.createAsset(jsonAssetPath, inputStream, "application/json", true);
if (asset != null) {
LOG.info("JSON asset created at {}", jsonAssetPath);
}
}
}
/**
* Generate a unique JSON file name
*/
private String getJsonFileName(String contentFragmentPath) {
return contentFragmentPath.replace("/content/dam/", "").replace("/", "_") + ".json";
}
/**
* Get service user resource resolver
*/
private ResourceResolver getServiceResourceResolver() throws LoginException {
Map<String, Object> params = new HashMap<>();
params.put(ResourceResolverFactory.SUBSERVICE, "content-fragment-service");
return resourceResolverFactory.getServiceResourceResolver(params);
}
}
2. Sling Job to Execute the Service
A Sling Job will call the above service to process Content Fragments.
@component(
service = JobConsumer.class,
property = {
JobConsumer.PROPERTY_TOPICS + "=com/example/jobs/processContentFragment"
}
)
public class ContentFragmentJob implements JobConsumer {
private static final Logger LOG = LoggerFactory.getLogger(ContentFragmentJob.class);
@reference
private ContentFragmentToJsonService contentFragmentToJsonService;
@Override
public JobResult process(Job job) {
String contentFragmentPath = job.getProperty("contentFragmentPath", String.class);
if (contentFragmentPath == null) {
LOG.error("Content Fragment path not provided in job.");
return JobResult.FAILED;
}
LOG.info("Processing Content Fragment: {}", contentFragmentPath);
contentFragmentToJsonService.processContentFragment(contentFragmentPath);
return JobResult.OK;
}
}
3. How to Trigger the Sling Job
A Sling Job can be manually triggered from the Java code, or via a scheduler, workflow, or event listener.
@component(service = ContentFragmentJobTrigger.class)
public class ContentFragmentJobTrigger {
private static final Logger LOG = LoggerFactory.getLogger(ContentFragmentJobTrigger.class);
private static final String JOB_TOPIC = "com/example/jobs/processContentFragment";
@reference
private JobManager jobManager;
public void triggerJob(String contentFragmentPath) {
Map<String, Object> jobProperties = new HashMap<>();
jobProperties.put("contentFragmentPath", contentFragmentPath);
jobManager.addJob(JOB_TOPIC, jobProperties);
LOG.info("Job triggered for Content Fragment: {}", contentFragmentPath);
}
}
However, I would also consider another approach with servlet that will be mapped to some selector. It will allow you to request content fragment path with selector and json extension and get required data without persisting it. For example: /content/dam/cfs/my-cf.consumer-1.json.
This is because AssetManager.createAsset is working in AEM on prem, but it's deprecated in AEMaaCS.
Best regards,
Kostiantyn Diachenko.
Views
Likes
Replies
Views
Likes
Replies