How to create a Json file using job?
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
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
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.
@8220494(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/";
@3214626
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.
@8220494(
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);
@3214626
private ContentFragmentToJsonService contentFragmentToJsonService;
@9944223
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.
@8220494(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";
@3214626
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.
Enter your E-mail address. We'll send you an e-mail with instructions to reset your password.