Skip to content

Commit 4f65bac

Browse files
authored
Feat (Core): ImportUtil refactor to improve responses (dotCMS#31407)
This PR represents the final stage of the Import Content response improvements, where the `ImportContentletsProcessor` now leverages the new structured response format while maintaining full backward compatibility with existing Struts implementations. ### Changes Overview * Updated `ImportContentletsProcessor` to use new response format * Added converter to maintain backward compatibility with Struts actions * Improved error handling and validation message organization * Enhanced documentation and code organization ### What's Not Changed We intentionally kept several aspects unchanged to ensure stability: * Core import logic remains untouched * Legacy response format is still fully supported * Existing workflow processing behavior * Current transaction handling * Permission checking mechanisms While working on this code, we identified several potential improvements that were intentionally left for future iterations to keep the scope focused on the immediate needs. This PR is related to: dotCMS#30882 This PR fixes: dotCMS#31339
1 parent 7d4e463 commit 4f65bac

17 files changed

+1089
-1143
lines changed

dotCMS/src/main/java/com/dotcms/jobs/business/processor/impl/ImportContentletsProcessor.java

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.dotmarketing.util.FileUtil;
3030
import com.dotmarketing.util.ImportUtil;
3131
import com.dotmarketing.util.Logger;
32+
import com.dotmarketing.util.importer.model.ImportResult;
3233
import com.google.common.hash.Hashing;
3334
import com.liferay.portal.model.User;
3435
import com.liferay.portal.util.Constants;
@@ -158,7 +159,7 @@ public void process(final Job job) throws JobProcessingException {
158159
// Handle the import operation based on the command, by default any command that is not
159160
// "publish" is considered preview.
160161
final boolean isPublish = CMD_PUBLISH.equals(command);
161-
handleImport(!isPublish, job, fileToImport, user, progressCallback);
162+
handleImport(!isPublish, job, fileToImport, totalLines, user, progressCallback);
162163

163164
if (!cancellationRequested.get()) {
164165
// Ensure the progress is at 100% when the job is done
@@ -325,11 +326,12 @@ public Map<String, Object> getResultMetadata(Job job) {
325326
* @param preview Flag indicating whether the operation is a preview or publish
326327
* @param job The import job configuration
327328
* @param fileToImport The CSV file to be imported
329+
* @param fileTotalLines The total number of lines in the file being processed
328330
* @param user The user performing the import
329331
* @param progressCallback Callback for tracking import progress
330332
*/
331333
private void handleImport(final boolean preview, final Job job, final File fileToImport,
332-
final User user, final LongConsumer progressCallback) {
334+
final long fileTotalLines, final User user, final LongConsumer progressCallback) {
333335

334336
if (!preview) {
335337
AdminLogger.log(
@@ -343,9 +345,10 @@ private void handleImport(final boolean preview, final Job job, final File fileT
343345

344346
CsvReader csvReader = createCsvReader(reader);
345347

346-
final var importResults = processImport(preview, job, user, csvReader,
347-
progressCallback);
348-
resultMetadata = new HashMap<>(importResults);
348+
final var importResults = processImport(
349+
preview, job, user, csvReader, fileTotalLines, progressCallback
350+
);
351+
resultMetadata = JobUtil.transformToMap(importResults);
349352
} catch (Exception e) {
350353

351354
try {
@@ -372,14 +375,16 @@ private void handleImport(final boolean preview, final Job job, final File fileT
372375
* @param job - The {@link Job} being processed.
373376
* @param user - The {@link User} performing this action.
374377
* @param csvReader - The actual data contained in the CSV file.
378+
* @param fileTotalLines - The total number of lines in the file being processed
375379
* @param progressCallback - The callback function to update the progress of the job.
376380
* @return The status of the content import performed by dotCMS. This provides information
377381
* regarding inconsistencies, errors, warnings and/or precautions to the user.
378382
* @throws DotDataException An error occurred when importing the CSV file.
379383
*/
380-
private Map<String, List<String>> processImport(final boolean preview, final Job job,
381-
final User user, final CsvReader csvReader, final LongConsumer progressCallback)
382-
throws DotDataException, IOException, DotSecurityException {
384+
private ImportResult processImport(final boolean preview, final Job job,
385+
final User user, final CsvReader csvReader, final long fileTotalLines,
386+
final LongConsumer progressCallback
387+
) throws DotDataException, IOException, DotSecurityException {
383388

384389
final var currentSiteId = getSiteIdentifier(job);
385390
final var currentSiteName = getSiteName(job);
@@ -397,10 +402,11 @@ private Map<String, List<String>> processImport(final boolean preview, final Job
397402
preview ? "Preview" : "Process"));
398403
Logger.info(this, String.format("-> Content Type: %s", contentType.variable()));
399404

400-
return ImportUtil.importFile(importId, currentSiteId, contentType.id(), fields, preview,
401-
language == null, user, language == null ? -1 : language.getId(),
405+
return ImportUtil.importFileResult(importId, currentSiteId, contentType.id(), fields,
406+
preview, language == null, user, language == null ? -1 : language.getId(),
402407
headerInfo.headers, csvReader, headerInfo.languageCodeColumn,
403-
headerInfo.countryCodeColumn, workflowActionId, httpReq, progressCallback);
408+
headerInfo.countryCodeColumn, workflowActionId, fileTotalLines, httpReq,
409+
progressCallback);
404410
}
405411

406412
/**

dotCMS/src/main/java/com/dotcms/jobs/business/util/JobUtil.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@
1414
import com.dotmarketing.util.Logger;
1515
import com.dotmarketing.util.UtilMethods;
1616
import com.dotmarketing.util.WebKeys;
17+
import com.fasterxml.jackson.core.JsonProcessingException;
18+
import com.fasterxml.jackson.databind.ObjectMapper;
19+
import com.fasterxml.jackson.databind.SerializationFeature;
20+
import com.fasterxml.jackson.datatype.guava.GuavaModule;
21+
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
22+
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
23+
import com.github.jonpeterson.jackson.module.versioning.VersioningModule;
1724
import com.liferay.portal.model.User;
25+
import io.vavr.Lazy;
1826
import io.vavr.control.Try;
1927
import java.math.BigDecimal;
2028
import java.math.RoundingMode;
@@ -30,6 +38,20 @@
3038
*/
3139
public class JobUtil {
3240

41+
/**
42+
* Jackson mapper configuration and lazy initialized instance.
43+
*/
44+
private static final Lazy<ObjectMapper> objectMapper = Lazy.of(() -> {
45+
ObjectMapper mapper = new ObjectMapper();
46+
mapper.enable(SerializationFeature.INDENT_OUTPUT);
47+
mapper.registerModule(new Jdk8Module());
48+
mapper.registerModule(new GuavaModule());
49+
mapper.registerModule(new JavaTimeModule());
50+
mapper.registerModule(new VersioningModule());
51+
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
52+
return mapper;
53+
});
54+
3355
private JobUtil() {
3456
throw new IllegalStateException("Utility class");
3557
}
@@ -160,4 +182,30 @@ public static <T extends JobEvent> void sendEvents(final T event) {
160182
.onFailure(e -> Logger.error(JobUtil.class, e.getMessage()));
161183
}
162184

185+
/**
186+
* Converts the given object into a Map representation. This method uses the configured
187+
* ObjectMapper to transform the provided object into a Map with keys as strings and values as
188+
* objects.
189+
*
190+
* @param toTransform The object to be converted into a Map
191+
* @return A Map containing the key-value pairs representing the structure of the input object
192+
*/
193+
public static Map<String, Object> transformToMap(final Object toTransform) {
194+
return objectMapper.get().convertValue(toTransform, Map.class);
195+
}
196+
197+
/**
198+
* Converts the given object into its JSON string representation using the configured
199+
* ObjectMapper. The ObjectMapper is configured with various modules (JDK8, Guava, JavaTime,
200+
* Versioning) and has pretty printing enabled.
201+
*
202+
* @param toTransform The object to be transformed into a JSON string
203+
* @return A JSON string representation of the input object
204+
* @throws JsonProcessingException If the object cannot be serialized to JSON
205+
*/
206+
public static String transformToString(final Object toTransform)
207+
throws JsonProcessingException {
208+
return objectMapper.get().writeValueAsString(toTransform);
209+
}
210+
163211
}

0 commit comments

Comments
 (0)