Skip to content

Commit 75c669e

Browse files
committed
Refactor AEM data parsing and job queuing
Improve robustness and logging across AEM connector and connector context: - aem-commons: Refactored DumAemObjectGeneric.setDataPath to validate input, traverse JSON path via traverseDataPath, extract attributes with extractAttributes, and centralize date parsing in putParsedDateAttribute. Adds detailed debug/warn/error logs and falls back to original value on parse failure. - aem-plugin model: Extended DumAemAttributeSpecification with additional JPA-mapped fields (name, type, mandatory, multiValued, description, facet, className) and enum mapping for field type; added a suppression for a Sonar rule. - aem-plugin service: DumAemJobService now checks the result of dumConnectorContext.addJobItem and logs success or error accordingly (for index and deIndex flows) and adds extra debug logging. - connector: Changed DumConnectorContext.addJobItem signature to return boolean and updated DumConnectorContextImpl to only queue items with non-null IDs, returning true/false and logging appropriate messages. These changes add validation, clearer logging, and safer job queue handling.
1 parent 7f9891f commit 75c669e

File tree

5 files changed

+113
-35
lines changed

5 files changed

+113
-35
lines changed

aem-commons/src/main/java/com/viglet/dumont/connector/aem/commons/DumAemObjectGeneric.java

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -224,33 +224,63 @@ private void getDataFolder(JSONObject jcrContentNode) {
224224
}
225225

226226
public void setDataPath(String dataPath) {
227-
if (dataPath != null) {
228-
JSONObject dataJson = this.jcrContentNode;
229-
for (String node : dataPath.split("/")) {
230-
if (dataJson.has(node)) {
231-
dataJson = dataJson.getJSONObject(node);
232-
} else {
233-
return;
227+
if (dataPath == null || dataPath.isEmpty()) {
228+
log.warn("Data path is null or empty for object at path: {}", this.path);
229+
return;
230+
}
231+
232+
JSONObject currentNode = traverseDataPath(this.jcrContentNode, dataPath);
233+
if (currentNode == null) {
234+
return;
235+
}
236+
237+
log.debug("Extracting attributes from data path: {} for object at path: {}", dataPath, this.path);
238+
extractAttributes(currentNode);
239+
}
240+
241+
private JSONObject traverseDataPath(JSONObject rootNode, String dataPath) {
242+
JSONObject currentNode = rootNode;
243+
for (String node : dataPath.split("/")) {
244+
if (currentNode.has(node)) {
245+
currentNode = currentNode.optJSONObject(node);
246+
if (currentNode == null) {
247+
log.warn("Node '{}' is not a JSONObject in data path '{}' for object at path: {}", node, dataPath,
248+
this.path);
249+
return null;
234250
}
251+
} else {
252+
log.warn("Node '{}' not found in data path '{}' for object at path: {}", node, dataPath, this.path);
253+
return null;
254+
}
255+
}
256+
return currentNode;
257+
}
258+
259+
private void extractAttributes(JSONObject currentNode) {
260+
for (String key : currentNode.keySet()) {
261+
if (key.endsWith("@LastModified")) {
262+
continue;
235263
}
236-
JSONObject finalDataJson = dataJson;
237-
dataJson.keySet().stream().filter(key -> !key.endsWith("@LastModified"))
238-
.forEach(key -> {
239-
Object value = finalDataJson.get(key);
240-
if (isDate(value.toString())) {
241-
try {
242-
TimeZone tz = TimeZone.getTimeZone(UTC);
243-
DateFormat dumontDateFormat = new SimpleDateFormat(DATE_FORMAT);
244-
dumontDateFormat.setTimeZone(tz);
245-
this.attributes.put(key, dumontDateFormat.format(
246-
aemJsonDateFormat.parse(value.toString()).getTime()));
247-
} catch (ParseException e) {
248-
log.error(e.getMessage(), e);
249-
}
250-
} else {
251-
this.attributes.put(key, value);
252-
}
253-
});
264+
Object value = currentNode.get(key);
265+
if (value instanceof String stringValue && isDate(stringValue)) {
266+
putParsedDateAttribute(key, stringValue);
267+
} else {
268+
this.attributes.put(key, value);
269+
}
270+
}
271+
}
272+
273+
private void putParsedDateAttribute(String key, String value) {
274+
try {
275+
TimeZone tz = TimeZone.getTimeZone(UTC);
276+
DateFormat dumontDateFormat = new SimpleDateFormat(DATE_FORMAT);
277+
dumontDateFormat.setTimeZone(tz);
278+
log.debug("Parsing date attribute: {} with value: {} for object at path: {}", key, value, this.path);
279+
this.attributes.put(key, dumontDateFormat.format(aemJsonDateFormat.parse(value).getTime()));
280+
} catch (ParseException e) {
281+
log.error("Failed to parse date for key '{}' with value '{}' at path '{}': {}", key, value, this.path,
282+
e.getMessage());
283+
this.attributes.put(key, value);
254284
}
255285
}
256286

aem/aem-plugin/src/main/java/com/viglet/dumont/connector/plugin/aem/persistence/model/DumAemAttributeSpecification.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@
77
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
88
import com.viglet.dumont.spring.jpa.DumUuid;
99
import com.viglet.turing.client.sn.job.TurSNAttributeSpec;
10+
import com.viglet.turing.commons.se.field.TurSEFieldType;
1011

1112
import jakarta.persistence.CollectionTable;
1213
import jakarta.persistence.Column;
1314
import jakarta.persistence.ElementCollection;
1415
import jakarta.persistence.Entity;
16+
import jakarta.persistence.EnumType;
17+
import jakarta.persistence.Enumerated;
1518
import jakarta.persistence.FetchType;
1619
import jakarta.persistence.Id;
1720
import jakarta.persistence.JoinColumn;
@@ -25,6 +28,7 @@
2528
import lombok.Setter;
2629
import lombok.experimental.SuperBuilder;
2730

31+
@SuppressWarnings("java:S2387")
2832
@SuperBuilder
2933
@AllArgsConstructor
3034
@NoArgsConstructor
@@ -42,9 +46,31 @@ public class DumAemAttributeSpecification extends TurSNAttributeSpec {
4246
@DumUuid
4347
@Column(name = "id", nullable = false)
4448
private String id;
49+
50+
@Column(name = "class_name")
4551
private String className;
52+
4653
private String text;
4754

55+
@Column(name = "name")
56+
private String name;
57+
58+
@Enumerated(EnumType.STRING)
59+
@Column(name = "type")
60+
private TurSEFieldType type;
61+
62+
@Column(name = "mandatory")
63+
private boolean mandatory;
64+
65+
@Column(name = "multi_valued")
66+
private boolean multiValued;
67+
68+
@Column(name = "description")
69+
private String description;
70+
71+
@Column(name = "facet")
72+
private boolean facet;
73+
4874
@Builder.Default
4975
@ElementCollection(fetch = FetchType.EAGER)
5076
@MapKeyColumn(name = "language")

aem/aem-plugin/src/main/java/com/viglet/dumont/connector/plugin/aem/service/DumAemJobService.java

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,14 @@ private void forcingDeIndex(DumAemSession dumAemSession, DumAemObject aemObject)
130130
aemObject.getPath(), PUBLISHING.toString());
131131
DumJobItemWithSession dumJobItemWithSession = new DumJobItemWithSession(
132132
deIndexJobItem, dumAemSession, aemObject.getDependencies(), true);
133-
dumConnectorContext.addJobItem(dumJobItemWithSession);
134-
log.info("Forcing deIndex because {} is not publishing.",
135-
DumAemPluginUtils.getObjectDetailForLogs(dumAemSession, aemObject));
133+
if (dumConnectorContext.addJobItem(dumJobItemWithSession)) {
134+
log.info("Forcing deIndex because {} is not publishing.",
135+
DumAemPluginUtils.getObjectDetailForLogs(dumAemSession, aemObject));
136+
} else {
137+
log.error("Failed to queue deIndex job for {} in session: {}",
138+
DumAemPluginUtils.getObjectDetailForLogs(dumAemSession, aemObject),
139+
dumAemSession.getProviderName());
140+
}
136141
}
137142

138143
private void indexByEnvironment(DumAemSession dumAemSession,
@@ -147,14 +152,22 @@ private void indexByEnvironment(DumAemSession dumAemSession,
147152

148153
private void createIndexJobAndSendToConnectorQueue(DumAemSession dumAemSession,
149154
DumAemObject aemObject, Locale locale) {
155+
log.debug("AemObject {} ", aemObject.toString());
150156
TurSNJobItem turSNJobItem = getTurSNJobItem(dumAemSession, aemObject, locale,
151157
getJobItemAttributes(dumAemSession,
152158
dumAemService.getTargetAttrValueMap(dumAemSession,
153159
aemObject)));
154160
DumJobItemWithSession jobItemWithSession = new DumJobItemWithSession(turSNJobItem,
155161
dumAemSession, aemObject.getDependencies(),
156162
dumAemSession.isStandalone());
157-
dumConnectorContext.addJobItem(jobItemWithSession);
163+
if (dumConnectorContext.addJobItem(jobItemWithSession)) {
164+
log.debug("Index job successfully queued for {}",
165+
DumAemPluginUtils.getObjectDetailForLogs(dumAemSession, aemObject));
166+
} else {
167+
log.error("Failed to queue index job for {} in session: {}",
168+
DumAemPluginUtils.getObjectDetailForLogs(dumAemSession, aemObject),
169+
dumAemSession.getProviderName());
170+
}
158171
}
159172

160173
private static @NotNull Map<String, Object> getJobItemAttributes(
@@ -211,9 +224,13 @@ public void createDeIndexJobAndSendToConnectorQueue(DumAemSession dumAemSession,
211224
deIndexJobItem, dumAemSession,
212225
Collections.emptySet(),
213226
dumAemSession.isStandalone());
214-
dumConnectorContext.addJobItem(dumJobItemWithSession);
215-
log.debug("DeIndex job successfully queued for contentId: {}",
216-
contentId);
227+
if (dumConnectorContext.addJobItem(dumJobItemWithSession)) {
228+
log.debug("DeIndex job successfully queued for contentId: {}",
229+
contentId);
230+
} else {
231+
log.error("Failed to queue deIndex job for contentId: {} in session: {}",
232+
contentId, dumAemSession.getProviderName());
233+
}
217234

218235
} catch (Exception e) {
219236
log.error("Failed to create deIndex job for contentId: {} in session: {}. Error: {}",

connector/connector-app/src/main/java/com/viglet/dumont/connector/impl/DumConnectorContextImpl.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,16 @@ public List<String> getObjectIdByDependency(String source, String provider,
8585
}
8686

8787
@Override
88-
public void addJobItem(DumJobItemWithSession dumJobItemWithSession) {
89-
if (dumJobItemWithSession.turSNJobItem() != null) {
88+
public boolean addJobItem(DumJobItemWithSession dumJobItemWithSession) {
89+
if (dumJobItemWithSession.turSNJobItem() != null &&
90+
dumJobItemWithSession.turSNJobItem().getId() != null) {
9091
log.info("Adding {} object to payload.", dumJobItemWithSession.turSNJobItem().getId());
9192
queueLinks.offer(dumJobItemWithSession);
9293
processRemainingJobs();
94+
return true;
95+
} else {
96+
log.warn("Job item or its ID is null. Skipping addition to payload.");
97+
return false;
9398
}
9499
}
95100

connector/connector-commons/src/main/java/com/viglet/dumont/connector/commons/DumConnectorContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import com.viglet.dumont.connector.commons.domain.DumJobItemWithSession;
2323

2424
public interface DumConnectorContext {
25-
void addJobItem(DumJobItemWithSession dumJobItemWithSession);
25+
boolean addJobItem(DumJobItemWithSession dumJobItemWithSession);
2626

2727
void finishIndexing(DumConnectorSession session, boolean standalone);
2828

0 commit comments

Comments
 (0)