diff --git a/openmetadata-service/src/main/java/org/openmetadata/csv/CsvUtil.java b/openmetadata-service/src/main/java/org/openmetadata/csv/CsvUtil.java index df63c0372683..8281d1bac89a 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/csv/CsvUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/csv/CsvUtil.java @@ -47,8 +47,8 @@ public static String formatCsv(CsvFile csvFile) throws IOException { List headers = getHeaders(csvFile.getHeaders()); CSVFormat csvFormat = Builder.create(CSVFormat.DEFAULT).setHeader(headers.toArray(new String[0])).build(); try (CSVPrinter printer = new CSVPrinter(writer, csvFormat)) { - for (List record : listOrEmpty(csvFile.getRecords())) { - printer.printRecord(record); + for (List csvRecord : listOrEmpty(csvFile.getRecords())) { + printer.printRecord(csvRecord); } } return writer.toString(); @@ -65,14 +65,14 @@ public static List getHeaders(List csvHeaders) { return headers; } - public static String recordToString(CSVRecord record) { - return recordToString(record.toList()); + public static String recordToString(CSVRecord csvRecord) { + return recordToString(csvRecord.toList()); } public static String recordToString(List fields) { return nullOrEmpty(fields) ? "" - : fields.stream().map(str -> str.contains(SEPARATOR) ? quote(str) : str).collect(Collectors.joining(SEPARATOR)); + : fields.stream().map(CsvUtil::quoteCsvField).collect(Collectors.joining(SEPARATOR)); } public static String recordToString(String[] fields) { @@ -92,47 +92,52 @@ public static String quote(String field) { public static String quoteField(List field) { return nullOrEmpty(field) ? "" - : field.stream() - .map(str -> str.contains(SEPARATOR) || str.contains(FIELD_SEPARATOR) ? quote(str) : str) - .collect(Collectors.joining(FIELD_SEPARATOR)); + : field.stream().map(CsvUtil::quoteCsvField).collect(Collectors.joining(FIELD_SEPARATOR)); } - public static List addField(List record, Boolean field) { - record.add(field == null ? "" : field.toString()); - return record; + public static List addField(List csvRecord, Boolean field) { + csvRecord.add(field == null ? "" : field.toString()); + return csvRecord; } - public static List addField(List record, String field) { - record.add(field); - return record; + public static List addField(List csvRecord, String field) { + csvRecord.add(field); + return csvRecord; } - public static List addFieldList(List record, List field) { - record.add(quoteField(field)); - return record; + public static List addFieldList(List csvRecord, List field) { + csvRecord.add(quoteField(field)); + return csvRecord; } - public static List addEntityReferences(List record, List refs) { - record.add( + public static List addEntityReferences(List csvRecord, List refs) { + csvRecord.add( nullOrEmpty(refs) ? null : refs.stream().map(EntityReference::getFullyQualifiedName).collect(Collectors.joining(FIELD_SEPARATOR))); - return record; + return csvRecord; } - public static List addEntityReference(List record, EntityReference ref) { - record.add(nullOrEmpty(ref) ? null : ref.getFullyQualifiedName()); - return record; + public static List addEntityReference(List csvRecord, EntityReference ref) { + csvRecord.add(nullOrEmpty(ref) ? null : ref.getFullyQualifiedName()); + return csvRecord; } - public static List addTagLabels(List record, List tags) { - record.add( + public static List addTagLabels(List csvRecord, List tags) { + csvRecord.add( nullOrEmpty(tags) ? null : tags.stream().map(TagLabel::getTagFQN).collect(Collectors.joining(FIELD_SEPARATOR))); - return record; + return csvRecord; } - public static List addOwner(List record, EntityReference owner) { - record.add(nullOrEmpty(owner) ? null : owner.getType() + FIELD_SEPARATOR + owner.getName()); - return record; + public static List addOwner(List csvRecord, EntityReference owner) { + csvRecord.add(nullOrEmpty(owner) ? null : owner.getType() + FIELD_SEPARATOR + owner.getName()); + return csvRecord; + } + + private static String quoteCsvField(String str) { + if (str.contains(SEPARATOR) || str.contains(FIELD_SEPARATOR)) { + return quote(str); + } + return str; } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/csv/EntityCsv.java b/openmetadata-service/src/main/java/org/openmetadata/csv/EntityCsv.java index 1e2bdaf8a4fa..fd546c17c078 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/csv/EntityCsv.java +++ b/openmetadata-service/src/main/java/org/openmetadata/csv/EntityCsv.java @@ -60,6 +60,7 @@ */ @Slf4j public abstract class EntityCsv { + public static final String FIELD_ERROR_MSG = "#%s: Field %d error - %s"; public static final String IMPORT_STATUS_HEADER = "status"; public static final String IMPORT_STATUS_DETAILS = "details"; public static final String IMPORT_STATUS_SUCCESS = "success"; @@ -103,8 +104,8 @@ public final CsvImportResult importCsv(String csv, boolean dryRun) throws IOExce // Validate and load each record while (records.hasNext()) { - CSVRecord record = records.next(); - processRecord(resultsPrinter, expectedHeaders, record); + CSVRecord csvRecord = records.next(); + processRecord(resultsPrinter, expectedHeaders, csvRecord); } // Finally, create the entities parsed from the record @@ -114,7 +115,7 @@ public final CsvImportResult importCsv(String csv, boolean dryRun) throws IOExce } /** Implement this method to a CSV record and turn it into an entity */ - protected abstract T toEntity(CSVPrinter resultsPrinter, CSVRecord record) throws IOException; + protected abstract T toEntity(CSVPrinter resultsPrinter, CSVRecord csvRecord) throws IOException; public final String exportCsv(List entities) throws IOException { CsvFile csvFile = new CsvFile().withHeaders(csvHeaders); @@ -143,21 +144,21 @@ public static CsvDocumentation getCsvDocumentation(String entityType) { protected abstract List toRecord(T entity); /** Owner field is in entityType;entityName format */ - public EntityReference getOwner(CSVPrinter printer, CSVRecord record, int fieldNumber) throws IOException { - String owner = record.get(fieldNumber); + public EntityReference getOwner(CSVPrinter printer, CSVRecord csvRecord, int fieldNumber) throws IOException { + String owner = csvRecord.get(fieldNumber); if (nullOrEmpty(owner)) { return null; } List list = CsvUtil.fieldToStrings(owner); if (list.size() != 2) { - importFailure(printer, invalidOwner(fieldNumber), record); + importFailure(printer, invalidOwner(fieldNumber), csvRecord); } - return getEntityReference(printer, record, fieldNumber, list.get(0), list.get(1)); + return getEntityReference(printer, csvRecord, fieldNumber, list.get(0), list.get(1)); } - protected final Boolean getBoolean(CSVPrinter printer, CSVRecord record, int fieldNumber) throws IOException { - String field = record.get(fieldNumber); + protected final Boolean getBoolean(CSVPrinter printer, CSVRecord csvRecord, int fieldNumber) throws IOException { + String field = csvRecord.get(fieldNumber); if (nullOrEmpty(field)) { return null; } @@ -167,15 +168,15 @@ protected final Boolean getBoolean(CSVPrinter printer, CSVRecord record, int fie if (field.equals(Boolean.FALSE.toString())) { return false; } - importFailure(printer, invalidBoolean(fieldNumber, field), record); + importFailure(printer, invalidBoolean(fieldNumber, field), csvRecord); processRecord = false; return false; } protected final EntityReference getEntityReference( - CSVPrinter printer, CSVRecord record, int fieldNumber, String entityType) throws IOException { - String fqn = record.get(fieldNumber); - return getEntityReference(printer, record, fieldNumber, entityType, fqn); + CSVPrinter printer, CSVRecord csvRecord, int fieldNumber, String entityType) throws IOException { + String fqn = csvRecord.get(fieldNumber); + return getEntityReference(printer, csvRecord, fieldNumber, entityType, fqn); } protected EntityInterface getEntityByName(String entityType, String fqn) { @@ -188,13 +189,13 @@ protected EntityInterface getEntityByName(String entityType, String fqn) { } protected final EntityReference getEntityReference( - CSVPrinter printer, CSVRecord record, int fieldNumber, String entityType, String fqn) throws IOException { + CSVPrinter printer, CSVRecord csvRecord, int fieldNumber, String entityType, String fqn) throws IOException { if (nullOrEmpty(fqn)) { return null; } EntityInterface entity = getEntityByName(entityType, fqn); if (entity == null) { - importFailure(printer, entityNotFound(fieldNumber, fqn), record); + importFailure(printer, entityNotFound(fieldNumber, fqn), csvRecord); processRecord = false; return null; } @@ -202,15 +203,15 @@ protected final EntityReference getEntityReference( } protected final List getEntityReferences( - CSVPrinter printer, CSVRecord record, int fieldNumber, String entityType) throws IOException { - String fqns = record.get(fieldNumber); + CSVPrinter printer, CSVRecord csvRecord, int fieldNumber, String entityType) throws IOException { + String fqns = csvRecord.get(fieldNumber); if (nullOrEmpty(fqns)) { return null; } List fqnList = listOrEmpty(CsvUtil.fieldToStrings(fqns)); List refs = new ArrayList<>(); for (String fqn : fqnList) { - EntityReference ref = getEntityReference(printer, record, fieldNumber, entityType, fqn); + EntityReference ref = getEntityReference(printer, csvRecord, fieldNumber, entityType, fqn); if (!processRecord) { return null; } @@ -221,9 +222,9 @@ protected final List getEntityReferences( return refs.isEmpty() ? null : refs; } - protected final List getTagLabels(CSVPrinter printer, CSVRecord record, int fieldNumber) + protected final List getTagLabels(CSVPrinter printer, CSVRecord csvRecord, int fieldNumber) throws IOException { - List refs = getEntityReferences(printer, record, fieldNumber, Entity.TAG); + List refs = getEntityReferences(printer, csvRecord, fieldNumber, Entity.TAG); if (!processRecord || nullOrEmpty(refs)) { return null; } @@ -261,29 +262,29 @@ private Iterator parse(String csv) { return null; } - private boolean validateHeaders(List expectedHeaders, CSVRecord record) { - importResult.withNumberOfRowsProcessed((int) record.getRecordNumber()); - if (expectedHeaders.equals(record.toList())) { + private boolean validateHeaders(List expectedHeaders, CSVRecord csvRecord) { + importResult.withNumberOfRowsProcessed((int) csvRecord.getRecordNumber()); + if (expectedHeaders.equals(csvRecord.toList())) { return true; } importResult.withNumberOfRowsFailed(1); - documentFailure(invalidHeader(recordToString(expectedHeaders), recordToString(record))); + documentFailure(invalidHeader(recordToString(expectedHeaders), recordToString(csvRecord))); return false; } - private void processRecord(CSVPrinter resultsPrinter, List expectedHeader, CSVRecord record) + private void processRecord(CSVPrinter resultsPrinter, List expectedHeader, CSVRecord csvRecord) throws IOException { processRecord = true; // Every row must have total fields corresponding to the number of headers - if (csvHeaders.size() != record.size()) { - importFailure(resultsPrinter, invalidFieldCount(expectedHeader.size(), record.size()), record); + if (csvHeaders.size() != csvRecord.size()) { + importFailure(resultsPrinter, invalidFieldCount(expectedHeader.size(), csvRecord.size()), csvRecord); return; } // Check if required values are present List errors = new ArrayList<>(); for (int i = 0; i < csvHeaders.size(); i++) { - String field = record.get(i); + String field = csvRecord.get(i); boolean fieldRequired = Boolean.TRUE.equals(csvHeaders.get(i).getRequired()); if (fieldRequired && nullOrEmpty(field)) { errors.add(fieldRequired(i)); @@ -291,31 +292,31 @@ private void processRecord(CSVPrinter resultsPrinter, List expectedHeade } if (!errors.isEmpty()) { - importFailure(resultsPrinter, String.join(FIELD_SEPARATOR, errors), record); + importFailure(resultsPrinter, String.join(FIELD_SEPARATOR, errors), csvRecord); return; } // Finally, convert record into entity for importing - T entity = toEntity(resultsPrinter, record); + T entity = toEntity(resultsPrinter, csvRecord); if (entity != null) { // Finally, create entities - createEntity(resultsPrinter, record, entity); + createEntity(resultsPrinter, csvRecord, entity); } } - private void createEntity(CSVPrinter resultsPrinter, CSVRecord record, T entity) throws IOException { + private void createEntity(CSVPrinter resultsPrinter, CSVRecord csvRecord, T entity) throws IOException { entity.setId(UUID.randomUUID()); entity.setUpdatedBy(importedBy); entity.setUpdatedAt(System.currentTimeMillis()); EntityRepository repository = (EntityRepository) Entity.getEntityRepository(entityType); Response.Status responseStatus; - if (!importResult.getDryRun()) { + if (Boolean.FALSE.equals(importResult.getDryRun())) { try { repository.prepareInternal(entity); PutResponse response = repository.createOrUpdate(null, entity); responseStatus = response.getStatus(); } catch (Exception ex) { - importFailure(resultsPrinter, ex.getMessage(), record); + importFailure(resultsPrinter, ex.getMessage(), csvRecord); return; } } else { @@ -329,9 +330,9 @@ private void createEntity(CSVPrinter resultsPrinter, CSVRecord record, T entity) } if (Response.Status.CREATED.equals(responseStatus)) { - importSuccess(resultsPrinter, record, ENTITY_CREATED); + importSuccess(resultsPrinter, csvRecord, ENTITY_CREATED); } else { - importSuccess(resultsPrinter, record, ENTITY_UPDATED); + importSuccess(resultsPrinter, csvRecord, ENTITY_UPDATED); } } @@ -354,22 +355,22 @@ public static String fieldRequired(int field) { } public static String invalidField(int field, String error) { - return String.format("#%s: Field %d error - %s", CsvErrorType.INVALID_FIELD, field + 1, error); + return String.format(FIELD_ERROR_MSG, CsvErrorType.INVALID_FIELD, field + 1, error); } public static String entityNotFound(int field, String fqn) { String error = String.format("Entity %s not found", fqn); - return String.format("#%s: Field %d error - %s", CsvErrorType.INVALID_FIELD, field + 1, error); + return String.format(FIELD_ERROR_MSG, CsvErrorType.INVALID_FIELD, field + 1, error); } public static String invalidOwner(int field) { String error = "Owner should be of format user;userName or team;teamName"; - return String.format("#%s: Field %d error - %s", CsvErrorType.INVALID_FIELD, field + 1, error); + return String.format(FIELD_ERROR_MSG, CsvErrorType.INVALID_FIELD, field + 1, error); } public static String invalidBoolean(int field, String fieldValue) { String error = String.format("Field %s should be either 'true' of 'false'", fieldValue); - return String.format("#%s: Field %d error - %s", CsvErrorType.INVALID_FIELD, field + 1, error); + return String.format(FIELD_ERROR_MSG, CsvErrorType.INVALID_FIELD, field + 1, error); } private void documentFailure(String error) { @@ -378,27 +379,29 @@ private void documentFailure(String error) { } private void importSuccess(CSVPrinter printer, CSVRecord inputRecord, String successDetails) throws IOException { - List record = listOf(IMPORT_STATUS_SUCCESS, successDetails); - record.addAll(inputRecord.toList()); - printer.printRecord(record); + List recordList = listOf(IMPORT_STATUS_SUCCESS, successDetails); + recordList.addAll(inputRecord.toList()); + printer.printRecord(recordList); importResult.withNumberOfRowsProcessed((int) inputRecord.getRecordNumber()); importResult.withNumberOfRowsPassed(importResult.getNumberOfRowsPassed() + 1); } protected void importFailure(CSVPrinter printer, String failedReason, CSVRecord inputRecord) throws IOException { - List record = listOf(IMPORT_STATUS_FAILED, failedReason); - record.addAll(inputRecord.toList()); - printer.printRecord(record); + List recordList = listOf(IMPORT_STATUS_FAILED, failedReason); + recordList.addAll(inputRecord.toList()); + printer.printRecord(recordList); importResult.withNumberOfRowsProcessed((int) inputRecord.getRecordNumber()); importResult.withNumberOfRowsFailed(importResult.getNumberOfRowsFailed() + 1); processRecord = false; } private void setFinalStatus() { - Status status = - importResult.getNumberOfRowsPassed().equals(importResult.getNumberOfRowsProcessed()) - ? Status.SUCCESS - : importResult.getNumberOfRowsPassed() > 1 ? Status.PARTIAL_SUCCESS : Status.FAILURE; + Status status = Status.FAILURE; + if (importResult.getNumberOfRowsPassed().equals(importResult.getNumberOfRowsProcessed())) { + status = Status.SUCCESS; + } else if (importResult.getNumberOfRowsPassed() > 1) { + status = Status.PARTIAL_SUCCESS; + } importResult.setStatus(status); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/clients/pipeline/PipelineServiceClientFactory.java b/openmetadata-service/src/main/java/org/openmetadata/service/clients/pipeline/PipelineServiceClientFactory.java index 35b5a94d24e6..f5192770a5bd 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/clients/pipeline/PipelineServiceClientFactory.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/clients/pipeline/PipelineServiceClientFactory.java @@ -18,9 +18,13 @@ import lombok.extern.slf4j.Slf4j; import org.openmetadata.schema.api.configuration.pipelineServiceClient.PipelineServiceClientConfiguration; import org.openmetadata.sdk.PipelineServiceClient; +import org.openmetadata.sdk.exception.PipelineServiceClientException; @Slf4j -public class PipelineServiceClientFactory { +public final class PipelineServiceClientFactory { + private PipelineServiceClientFactory() { + // Final class + } @Getter private static PipelineServiceClient pipelineServiceClient; @@ -44,7 +48,7 @@ public static PipelineServiceClient createPipelineServiceClient(PipelineServiceC | InvocationTargetException | InstantiationException | IllegalAccessException e) { - throw new RuntimeException( + throw new PipelineServiceClientException( String.format( "Error trying to load PipelineServiceClient %s: %s", pipelineServiceClientClass, e.getMessage())); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/dataInsight/DataInsightAggregatorFactory.java b/openmetadata-service/src/main/java/org/openmetadata/service/dataInsight/DataInsightAggregatorFactory.java index 393b0f511aee..17601d5b9921 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/dataInsight/DataInsightAggregatorFactory.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/dataInsight/DataInsightAggregatorFactory.java @@ -3,9 +3,11 @@ import org.elasticsearch.search.aggregations.Aggregations; import org.openmetadata.schema.dataInsight.DataInsightChartResult; -public class DataInsightAggregatorFactory { +public final class DataInsightAggregatorFactory { - public DataInsightAggregatorFactory() {} + private DataInsightAggregatorFactory() { + /* Factory Class for Creating Data Insight Aggregator */ + } public static DataInsightAggregatorInterface createDataAggregator( Aggregations aggregations, DataInsightChartResult.DataInsightChartType dataInsightChartType) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/dataInsight/TotalEntitiesByTierAggregator.java b/openmetadata-service/src/main/java/org/openmetadata/service/dataInsight/TotalEntitiesByTierAggregator.java index 5d0eb09fc7ad..1116dca57e64 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/dataInsight/TotalEntitiesByTierAggregator.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/dataInsight/TotalEntitiesByTierAggregator.java @@ -45,7 +45,11 @@ List aggregate() throws ParseException { totalEntityCount = totalEntityCount + sumEntityCount.getValue(); } for (TotalEntitiesByTier el : timestampData) { - el.withEntityCountFraction(el.getEntityCount() / totalEntityCount); + if (totalEntityCount != 0.0) { + el.withEntityCountFraction(el.getEntityCount() / totalEntityCount); + } else { + el.withEntityCountFraction(Double.NaN); + } data.add((el)); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/elasticsearch/ElasticSearchEventPublisher.java b/openmetadata-service/src/main/java/org/openmetadata/service/elasticsearch/ElasticSearchEventPublisher.java index 9a92a0b512f9..ad3c174f33da 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/elasticsearch/ElasticSearchEventPublisher.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/elasticsearch/ElasticSearchEventPublisher.java @@ -63,17 +63,10 @@ import org.openmetadata.schema.api.CreateEventPublisherJob; import org.openmetadata.schema.entity.classification.Classification; import org.openmetadata.schema.entity.classification.Tag; -import org.openmetadata.schema.entity.data.Container; -import org.openmetadata.schema.entity.data.Dashboard; import org.openmetadata.schema.entity.data.Database; import org.openmetadata.schema.entity.data.DatabaseSchema; import org.openmetadata.schema.entity.data.Glossary; import org.openmetadata.schema.entity.data.GlossaryTerm; -import org.openmetadata.schema.entity.data.MlModel; -import org.openmetadata.schema.entity.data.Pipeline; -import org.openmetadata.schema.entity.data.Query; -import org.openmetadata.schema.entity.data.Table; -import org.openmetadata.schema.entity.data.Topic; import org.openmetadata.schema.entity.services.DashboardService; import org.openmetadata.schema.entity.services.DatabaseService; import org.openmetadata.schema.entity.services.MessagingService; @@ -135,16 +128,13 @@ public void publish(EventList events) throws EventPublisherException, JsonProces try { switch (entityType) { case Entity.TABLE: - updateTable(event); - break; case Entity.DASHBOARD: - updateDashboard(event); - break; case Entity.TOPIC: - updateTopic(event); - break; case Entity.PIPELINE: - updatePipeline(event); + case Entity.MLMODEL: + case Entity.CONTAINER: + case Entity.QUERY: + updateEntity(event); break; case Entity.USER: updateUser(event); @@ -179,18 +169,9 @@ public void publish(EventList events) throws EventPublisherException, JsonProces case Entity.MLMODEL_SERVICE: updateMlModelService(event); break; - case Entity.MLMODEL: - updateMlModel(event); - break; case Entity.STORAGE_SERVICE: updateStorageService(event); break; - case Entity.CONTAINER: - updateContainer(event); - break; - case Entity.QUERY: - updateQuery(event); - break; case Entity.TAG: updateTag(event); break; @@ -312,122 +293,25 @@ private UpdateRequest applyChangeEvent(ChangeEvent event) { } } - private void updateTable(ChangeEvent event) throws IOException { - UpdateRequest updateRequest = - new UpdateRequest(ElasticSearchIndexType.TABLE_SEARCH_INDEX.indexName, event.getEntityId().toString()); - TableIndex tableIndex; - - switch (event.getEventType()) { - case ENTITY_CREATED: - tableIndex = new TableIndex((Table) event.getEntity()); - updateRequest.doc(JsonUtils.pojoToJson(tableIndex.buildESDoc()), XContentType.JSON); - updateRequest.docAsUpsert(true); - updateElasticSearch(updateRequest); - break; - case ENTITY_UPDATED: - if (Objects.equals(event.getCurrentVersion(), event.getPreviousVersion())) { - updateRequest = applyChangeEvent(event); - } else { - tableIndex = new TableIndex((Table) event.getEntity()); - scriptedUpsert(tableIndex.buildESDoc(), updateRequest); - } - updateElasticSearch(updateRequest); - break; - case ENTITY_SOFT_DELETED: - softDeleteEntity(updateRequest); - updateElasticSearch(updateRequest); - break; - case ENTITY_DELETED: - DeleteRequest deleteRequest = - new DeleteRequest(ElasticSearchIndexType.TABLE_SEARCH_INDEX.indexName, event.getEntityId().toString()); - deleteEntityFromElasticSearch(deleteRequest); - break; - } - } - - private void updateTopic(ChangeEvent event) throws IOException { - UpdateRequest updateRequest = - new UpdateRequest(ElasticSearchIndexType.TOPIC_SEARCH_INDEX.indexName, event.getEntityId().toString()); - TopicIndex topicIndex; - - switch (event.getEventType()) { - case ENTITY_CREATED: - topicIndex = new TopicIndex((Topic) event.getEntity()); - updateRequest.doc(JsonUtils.pojoToJson(topicIndex.buildESDoc()), XContentType.JSON); - updateRequest.docAsUpsert(true); - updateElasticSearch(updateRequest); - break; - case ENTITY_UPDATED: - if (Objects.equals(event.getCurrentVersion(), event.getPreviousVersion())) { - updateRequest = applyChangeEvent(event); - } else { - topicIndex = new TopicIndex((Topic) event.getEntity()); - scriptedUpsert(topicIndex.buildESDoc(), updateRequest); - } - updateElasticSearch(updateRequest); - break; - case ENTITY_SOFT_DELETED: - softDeleteEntity(updateRequest); - updateElasticSearch(updateRequest); - break; - case ENTITY_DELETED: - DeleteRequest deleteRequest = - new DeleteRequest(ElasticSearchIndexType.TOPIC_SEARCH_INDEX.indexName, event.getEntityId().toString()); - deleteEntityFromElasticSearch(deleteRequest); - break; - } - } - - private void updateDashboard(ChangeEvent event) throws IOException { - DashboardIndex dashboardIndex; - UpdateRequest updateRequest = - new UpdateRequest(ElasticSearchIndexType.DASHBOARD_SEARCH_INDEX.indexName, event.getEntityId().toString()); - - switch (event.getEventType()) { - case ENTITY_CREATED: - dashboardIndex = new DashboardIndex((Dashboard) event.getEntity()); - updateRequest.doc(JsonUtils.pojoToJson(dashboardIndex.buildESDoc()), XContentType.JSON); - updateRequest.docAsUpsert(true); - updateElasticSearch(updateRequest); - break; - case ENTITY_UPDATED: - if (Objects.equals(event.getCurrentVersion(), event.getPreviousVersion())) { - updateRequest = applyChangeEvent(event); - } else { - dashboardIndex = new DashboardIndex((Dashboard) event.getEntity()); - scriptedUpsert(dashboardIndex.buildESDoc(), updateRequest); - } - updateElasticSearch(updateRequest); - break; - case ENTITY_SOFT_DELETED: - softDeleteEntity(updateRequest); - updateElasticSearch(updateRequest); - break; - case ENTITY_DELETED: - DeleteRequest deleteRequest = - new DeleteRequest(ElasticSearchIndexType.DASHBOARD_SEARCH_INDEX.indexName, event.getEntityId().toString()); - deleteEntityFromElasticSearch(deleteRequest); - break; - } - } + private void updateEntity(ChangeEvent event) throws IOException { + String entityType = event.getEntityType(); + ElasticSearchIndexType indexType = ElasticSearchIndexDefinition.getIndexMappingByEntityType(entityType); + UpdateRequest updateRequest = new UpdateRequest(indexType.indexName, event.getEntityId().toString()); + ElasticSearchIndex index; - private void updatePipeline(ChangeEvent event) throws IOException { - PipelineIndex pipelineIndex; - UpdateRequest updateRequest = - new UpdateRequest(ElasticSearchIndexType.PIPELINE_SEARCH_INDEX.indexName, event.getEntityId().toString()); switch (event.getEventType()) { case ENTITY_CREATED: - pipelineIndex = new PipelineIndex((Pipeline) event.getEntity()); - updateRequest.doc(JsonUtils.pojoToJson(pipelineIndex.buildESDoc()), XContentType.JSON); + index = ElasticSearchIndexFactory.buildIndex(entityType, event.getEntity()); + updateRequest.doc(JsonUtils.pojoToJson(index.buildESDoc()), XContentType.JSON); updateRequest.docAsUpsert(true); updateElasticSearch(updateRequest); break; case ENTITY_UPDATED: - pipelineIndex = new PipelineIndex((Pipeline) event.getEntity()); if (Objects.equals(event.getCurrentVersion(), event.getPreviousVersion())) { updateRequest = applyChangeEvent(event); } else { - scriptedUpsert(pipelineIndex.buildESDoc(), updateRequest); + index = ElasticSearchIndexFactory.buildIndex(entityType, event.getEntity()); + scriptedUpsert(index.buildESDoc(), updateRequest); } updateElasticSearch(updateRequest); break; @@ -436,8 +320,7 @@ private void updatePipeline(ChangeEvent event) throws IOException { updateElasticSearch(updateRequest); break; case ENTITY_DELETED: - DeleteRequest deleteRequest = - new DeleteRequest(ElasticSearchIndexType.PIPELINE_SEARCH_INDEX.indexName, event.getEntityId().toString()); + DeleteRequest deleteRequest = new DeleteRequest(indexType.indexName, event.getEntityId().toString()); deleteEntityFromElasticSearch(deleteRequest); break; } @@ -544,105 +427,6 @@ private void updateGlossary(ChangeEvent event) throws IOException { } } - private void updateMlModel(ChangeEvent event) throws IOException { - UpdateRequest updateRequest = - new UpdateRequest(ElasticSearchIndexType.MLMODEL_SEARCH_INDEX.indexName, event.getEntityId().toString()); - MlModelIndex mlModelIndex; - - switch (event.getEventType()) { - case ENTITY_CREATED: - mlModelIndex = new MlModelIndex((MlModel) event.getEntity()); - updateRequest.doc(JsonUtils.pojoToJson(mlModelIndex.buildESDoc()), XContentType.JSON); - updateRequest.docAsUpsert(true); - updateElasticSearch(updateRequest); - break; - case ENTITY_UPDATED: - if (Objects.equals(event.getCurrentVersion(), event.getPreviousVersion())) { - updateRequest = applyChangeEvent(event); - } else { - mlModelIndex = new MlModelIndex((MlModel) event.getEntity()); - scriptedUpsert(mlModelIndex.buildESDoc(), updateRequest); - } - updateElasticSearch(updateRequest); - break; - case ENTITY_SOFT_DELETED: - softDeleteEntity(updateRequest); - updateElasticSearch(updateRequest); - break; - case ENTITY_DELETED: - DeleteRequest deleteRequest = - new DeleteRequest(ElasticSearchIndexType.MLMODEL_SEARCH_INDEX.indexName, event.getEntityId().toString()); - deleteEntityFromElasticSearch(deleteRequest); - break; - } - } - - private void updateContainer(ChangeEvent event) throws IOException { - UpdateRequest updateRequest = - new UpdateRequest(ElasticSearchIndexType.CONTAINER_SEARCH_INDEX.indexName, event.getEntityId().toString()); - ContainerIndex containerIndex; - - switch (event.getEventType()) { - case ENTITY_CREATED: - containerIndex = new ContainerIndex((Container) event.getEntity()); - updateRequest.doc(JsonUtils.pojoToJson(containerIndex.buildESDoc()), XContentType.JSON); - updateRequest.docAsUpsert(true); - updateElasticSearch(updateRequest); - break; - case ENTITY_UPDATED: - if (Objects.equals(event.getCurrentVersion(), event.getPreviousVersion())) { - updateRequest = applyChangeEvent(event); - } else { - containerIndex = new ContainerIndex((Container) event.getEntity()); - scriptedUpsert(containerIndex.buildESDoc(), updateRequest); - } - updateElasticSearch(updateRequest); - break; - case ENTITY_SOFT_DELETED: - softDeleteEntity(updateRequest); - updateElasticSearch(updateRequest); - break; - case ENTITY_DELETED: - DeleteRequest deleteRequest = - new DeleteRequest(ElasticSearchIndexType.CONTAINER_SEARCH_INDEX.indexName, event.getEntityId().toString()); - deleteEntityFromElasticSearch(deleteRequest); - break; - } - } - - private void updateQuery(ChangeEvent event) throws IOException { - UpdateRequest updateRequest = - new UpdateRequest(ElasticSearchIndexType.QUERY_SEARCH_INDEX.indexName, event.getEntityId().toString()); - QueryIndex queryIndex; - - switch (event.getEventType()) { - case ENTITY_CREATED: - queryIndex = new QueryIndex((Query) event.getEntity()); - updateRequest.doc(JsonUtils.pojoToJson(queryIndex.buildESDoc()), XContentType.JSON); - updateRequest.docAsUpsert(true); - updateElasticSearch(updateRequest); - break; - case ENTITY_UPDATED: - if (Objects.equals(event.getCurrentVersion(), event.getPreviousVersion())) { - updateRequest = applyChangeEvent(event); - } else { - queryIndex = new QueryIndex((Query) event.getEntity()); - scriptedUpsert(queryIndex.buildESDoc(), updateRequest); - } - updateElasticSearch(updateRequest); - break; - case ENTITY_SOFT_DELETED: - softDeleteEntity(updateRequest); - updateElasticSearch(updateRequest); - break; - case ENTITY_DELETED: - DeleteRequest deleteRequest = - new DeleteRequest(ElasticSearchIndexType.QUERY_SEARCH_INDEX.indexName, event.getEntityId().toString()); - deleteEntityFromElasticSearch(deleteRequest); - break; - } - } - private void updateTag(ChangeEvent event) throws IOException { UpdateRequest updateRequest = new UpdateRequest(ElasticSearchIndexType.TAG_SEARCH_INDEX.indexName, event.getEntityId().toString()); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/elasticsearch/ElasticSearchIndexDefinition.java b/openmetadata-service/src/main/java/org/openmetadata/service/elasticsearch/ElasticSearchIndexDefinition.java index ee5dd851834d..b7eb6b826e95 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/elasticsearch/ElasticSearchIndexDefinition.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/elasticsearch/ElasticSearchIndexDefinition.java @@ -38,6 +38,7 @@ import org.openmetadata.schema.type.IndexMappingLanguage; import org.openmetadata.schema.type.TagLabel; import org.openmetadata.service.Entity; +import org.openmetadata.service.events.errors.EventPublisherException; import org.openmetadata.service.jdbi3.CollectionDAO; import org.openmetadata.service.util.JsonUtils; @@ -55,8 +56,9 @@ public class ElasticSearchIndexDefinition { final EnumMap elasticSearchIndexes = new EnumMap<>(ElasticSearchIndexType.class); - public static final HashMap ENTITY_TYPE_TO_INDEX_MAP; - private static final Map> INDEX_TO_MAPPING_FIELDS_MAP = new HashMap<>(); + protected static final Map ENTITY_TYPE_TO_INDEX_MAP; + private static final Map> INDEX_TO_MAPPING_FIELDS_MAP = + new EnumMap<>(ElasticSearchIndexType.class); private final RestHighLevelClient client; static { @@ -160,7 +162,7 @@ public boolean createIndex(ElasticSearchIndexType elasticSearchIndexType, String } private String getContext(String type, String info) { - return String.format("Failed While : %s \n Additional Info: %s ", type, info); + return String.format("Failed While : %s %n Additional Info: %s ", type, info); } private void updateIndex(ElasticSearchIndexType elasticSearchIndexType, String lang) { @@ -269,7 +271,7 @@ public static ElasticSearchIndexType getIndexMappingByEntityType(String type) { } else if (type.equalsIgnoreCase(Entity.QUERY)) { return ElasticSearchIndexType.QUERY_SEARCH_INDEX; } - throw new RuntimeException("Failed to find index doc for type " + type); + throw new EventPublisherException("Failed to find index doc for type " + type); } public static Set getIndexFields(String entityType, IndexMappingLanguage lang) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/events/ChangeEventHandler.java b/openmetadata-service/src/main/java/org/openmetadata/service/events/ChangeEventHandler.java index acf7f0c2e961..1904f6f5c8b6 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/events/ChangeEventHandler.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/events/ChangeEventHandler.java @@ -168,7 +168,7 @@ public ChangeEvent getChangeEvent(String updateBy, String method, ContainerRespo return (ChangeEvent) responseContext.getEntity(); } - // Entity was hard deleted by DELETE .../entities/{id} + // Entity was hard deleted by DELETE ../entities/{id}?hardDelete=true if (changeType.equals(RestUtil.ENTITY_DELETED)) { EntityInterface entityInterface = (EntityInterface) responseContext.getEntity(); EntityReference entityReference = entityInterface.getEntityReference(); @@ -256,8 +256,8 @@ private List getThreads( ChangeEventParser.getFormattedMessages(PublishTo.FEED, changeDescription, entity); // Create an automated thread - for (EntityLink link : messages.keySet()) { - threads.add(getThread(link.getLinkString(), messages.get(link), loggedInUserName)); + for (Map.Entry entry : messages.entrySet()) { + threads.add(getThread(entry.getKey().getLinkString(), entry.getValue(), loggedInUserName)); } return threads; diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/events/EventFilter.java b/openmetadata-service/src/main/java/org/openmetadata/service/events/EventFilter.java index 87d1005c302f..b881a40cb69f 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/events/EventFilter.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/events/EventFilter.java @@ -67,7 +67,7 @@ public void filter(ContainerRequestContext requestContext, ContainerResponseCont eventHandlers .parallelStream() .forEach( - (eventHandler) -> { + eventHandler -> { UriInfo uriInfo = requestContext.getUriInfo(); if (JwtFilter.EXCLUDED_ENDPOINTS.stream().noneMatch(endpoint -> uriInfo.getPath().contains(endpoint))) { ParallelStreamUtil.runAsync(() -> eventHandler.process(requestContext, responseContext), forkJoinPool); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/events/EventPubSub.java b/openmetadata-service/src/main/java/org/openmetadata/service/events/EventPubSub.java index 342f4cd64100..0d18a762353b 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/events/EventPubSub.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/events/EventPubSub.java @@ -28,6 +28,7 @@ import lombok.extern.slf4j.Slf4j; import org.openmetadata.schema.type.ChangeEvent; import org.openmetadata.service.events.EventPubSub.ChangeEventHolder; +import org.openmetadata.service.events.errors.EventPublisherException; /** Change event PubSub built based on LMAX Disruptor. */ @Slf4j @@ -103,7 +104,8 @@ public static class DefaultExceptionHandler implements ExceptionHandler, LifecycleAware { - void publish(EventList events) throws Exception; + void publish(EventList events) throws EventPublisherException, JsonProcessingException; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/events/scheduled/ReportsHandler.java b/openmetadata-service/src/main/java/org/openmetadata/service/events/scheduled/ReportsHandler.java index be2373937624..9a4dcbf9e256 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/events/scheduled/ReportsHandler.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/events/scheduled/ReportsHandler.java @@ -20,10 +20,12 @@ import java.io.IOException; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.client.RestHighLevelClient; import org.openmetadata.schema.entity.events.EventSubscription; import org.openmetadata.schema.entity.events.TriggerConfig; +import org.openmetadata.service.exception.DataInsightJobException; import org.openmetadata.service.jdbi3.CollectionDAO; import org.openmetadata.service.jdbi3.DataInsightChartRepository; import org.quartz.JobBuilder; @@ -57,10 +59,10 @@ private ReportsHandler(CollectionDAO dao, RestHighLevelClient restHighLevelClien public static ReportsHandler getInstance() { if (INITIALIZED) return INSTANCE; - throw new RuntimeException("Reports Job Handler is not Initialized"); + throw new DataInsightJobException("Reports Job Handler is not Initialized"); } - public ConcurrentHashMap getReportMap() { + public ConcurrentMap getReportMap() { return reportJobKeyMap; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/AlertUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/AlertUtil.java index 71e128a168c6..a0cd51682202 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/AlertUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/AlertUtil.java @@ -53,7 +53,8 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; @Slf4j -public class AlertUtil { +public final class AlertUtil { + private AlertUtil() {} public static SubscriptionPublisher getNotificationsPublisher( EventSubscription subscription, CollectionDAO daoCollection) { @@ -143,6 +144,9 @@ public static Map getAlertFilterFunctions() { List testResultStatus = Stream.of(TestCaseStatus.values()).map(TestCaseStatus::value).collect(Collectors.toList()); func.setParamAdditionalContext(paramAdditionalContext.withData(new HashSet<>(testResultStatus))); + break; + default: + LOG.error("Invalid Function name : {}", type); } alertFunctions.put(func.getName(), func); } @@ -164,7 +168,7 @@ public static Set getEntitiesIndex(List entities) { } public static boolean evaluateAlertConditions(ChangeEvent changeEvent, List alertFilterRules) { - if (alertFilterRules.size() > 0) { + if (!alertFilterRules.isEmpty()) { boolean result; String completeCondition = buildCompleteCondition(alertFilterRules); AlertsRuleEvaluator ruleEvaluator = new AlertsRuleEvaluator(changeEvent); diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/SubscriptionPublisher.java b/openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/SubscriptionPublisher.java index 17f1dd219a10..8b2d97fca057 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/SubscriptionPublisher.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/SubscriptionPublisher.java @@ -124,11 +124,17 @@ public void setProcessor(BatchEventProcessor proc this.processor = processor; } - protected void sendAlert(EventResource.EventList list) throws InterruptedException, JsonProcessingException {} + protected void sendAlert(EventResource.EventList list) throws InterruptedException, JsonProcessingException { + /* This method needs to be over-ridden by specific Publisher for sending Alert */ + } - protected void onStartDelegate() {} + protected void onStartDelegate() { + /* Called on start of Publisher */ + } - protected void onShutdownDelegate() {} + protected void onShutdownDelegate() { + /* Called on shutdown of Publisher */ + } public int getCurrentBackOff() { return currentBackoffTime; diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/exception/DataInsightJobException.java b/openmetadata-service/src/main/java/org/openmetadata/service/exception/DataInsightJobException.java index 3966892349f9..cc31cb87bb07 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/exception/DataInsightJobException.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/exception/DataInsightJobException.java @@ -1,6 +1,10 @@ package org.openmetadata.service.exception; public class DataInsightJobException extends RuntimeException { + public DataInsightJobException(String message) { + super(message); + } + public DataInsightJobException(Throwable throwable) { super(throwable); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/ClassificationRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/ClassificationRepository.java index bfd8e369fe8c..54f66bd6ba83 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/ClassificationRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/ClassificationRepository.java @@ -68,7 +68,9 @@ public void storeEntity(Classification category, boolean update) throws IOExcept } @Override - public void storeRelationships(Classification entity) {} + public void storeRelationships(Classification entity) { + /* No Relationships */ + } private int getTermCount(Classification category) { ListFilter filter = diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java index 2e2e17862261..0cfcde6faa10 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java @@ -58,6 +58,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; @@ -1140,7 +1141,7 @@ public EntityReference getToEntityRef( UUID fromId, Relationship relationship, String toEntityType, boolean mustHaveRelationship) throws IOException { List records = findTo(fromId, entityType, relationship, toEntityType); ensureSingleRelationship(entityType, fromId, records, relationship.value(), mustHaveRelationship); - return records.size() >= 1 + return !records.isEmpty() ? Entity.getEntityReferenceById(records.get(0).getType(), records.get(0).getId(), ALL) : null; } @@ -1148,7 +1149,7 @@ public EntityReference getToEntityRef( public void ensureSingleRelationship( String entityType, UUID id, List relations, String relationshipName, boolean mustHaveRelationship) { // An entity can have only one container - if (mustHaveRelationship && relations.size() == 0) { + if (mustHaveRelationship && relations.isEmpty()) { throw new UnhandledServerException(CatalogExceptionMessage.entityTypeNotFound(entityType)); } if (!mustHaveRelationship && relations.isEmpty()) { @@ -1415,7 +1416,7 @@ private void updateDescription() throws JsonProcessingException { private void updateDeleted() throws JsonProcessingException { if (operation.isPut() || operation.isPatch()) { // Update operation can't set delete attributed to true. This can only be done as part of delete operation - if (updated.getDeleted() != original.getDeleted() && Boolean.TRUE.equals(updated.getDeleted())) { + if (!Objects.equals(updated.getDeleted(), original.getDeleted()) && Boolean.TRUE.equals(updated.getDeleted())) { throw new IllegalArgumentException(CatalogExceptionMessage.readOnlyAttribute(entityType, FIELD_DELETED)); } // PUT or PATCH is restoring the soft-deleted entity diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EventSubscriptionRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EventSubscriptionRepository.java index 85c2d1cd63cd..56f92c5a12b0 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EventSubscriptionRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EventSubscriptionRepository.java @@ -37,6 +37,7 @@ @Slf4j public class EventSubscriptionRepository extends EntityRepository { + private static final String INVALID_ALERT = "Invalid Alert Type"; private static final ConcurrentHashMap subscriptionPublisherMap = new ConcurrentHashMap<>(); static final String ALERT_PATCH_FIELDS = "owner,trigger,enabled,batchSize,timeout"; @@ -120,7 +121,7 @@ public void addSubscriptionPublisher(EventSubscription eventSubscription) { } break; default: - throw new IllegalArgumentException("Invalid Alert Type"); + throw new IllegalArgumentException(INVALID_ALERT); } } @@ -163,7 +164,7 @@ public void updateEventSubscription(EventSubscription eventSubscription) { ReportsHandler.getInstance().updateDataReportConfig(eventSubscription); break; default: - throw new IllegalArgumentException("Invalid Alert Type"); + throw new IllegalArgumentException(INVALID_ALERT); } } @@ -180,7 +181,7 @@ public void removeProcessorForEventSubscription(UUID id, SubscriptionStatus reas } public void deleteEventSubscriptionPublisher(EventSubscription deletedEntity) - throws InterruptedException, IOException, SchedulerException { + throws InterruptedException, SchedulerException { switch (deletedEntity.getAlertType()) { case CHANGE_EVENT: SubscriptionPublisher publisher = subscriptionPublisherMap.remove(deletedEntity.getId()); @@ -195,7 +196,7 @@ public void deleteEventSubscriptionPublisher(EventSubscription deletedEntity) ReportsHandler.getInstance().deleteDataReportConfig(deletedEntity); break; default: - throw new IllegalArgumentException("Invalid Alert Type"); + throw new IllegalArgumentException(INVALID_ALERT); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryRepository.java index 712cb3960b23..2d1c836ff1fd 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/GlossaryRepository.java @@ -154,61 +154,61 @@ public static class GlossaryCsv extends EntityCsv { } @Override - protected GlossaryTerm toEntity(CSVPrinter printer, CSVRecord record) throws IOException { + protected GlossaryTerm toEntity(CSVPrinter printer, CSVRecord csvRecord) throws IOException { GlossaryTerm glossaryTerm = new GlossaryTerm().withGlossary(glossary.getEntityReference()); // Field 1 - parent term - glossaryTerm.withParent(getEntityReference(printer, record, 0, Entity.GLOSSARY_TERM)); + glossaryTerm.withParent(getEntityReference(printer, csvRecord, 0, Entity.GLOSSARY_TERM)); if (!processRecord) { return null; } // Field 2,3,4 - Glossary name, displayName, description - glossaryTerm.withName(record.get(1)).withDisplayName(record.get(2)).withDescription(record.get(3)); + glossaryTerm.withName(csvRecord.get(1)).withDisplayName(csvRecord.get(2)).withDescription(csvRecord.get(3)); // Field 5 - Synonym list - glossaryTerm.withSynonyms(CsvUtil.fieldToStrings(record.get(4))); + glossaryTerm.withSynonyms(CsvUtil.fieldToStrings(csvRecord.get(4))); // Field 6 - Related terms - glossaryTerm.withRelatedTerms(getEntityReferences(printer, record, 5, Entity.GLOSSARY_TERM)); + glossaryTerm.withRelatedTerms(getEntityReferences(printer, csvRecord, 5, Entity.GLOSSARY_TERM)); if (!processRecord) { return null; } // Field 7 - TermReferences - glossaryTerm.withReferences(getTermReferences(printer, record)); + glossaryTerm.withReferences(getTermReferences(printer, csvRecord)); if (!processRecord) { return null; } // Field 8 - tags - glossaryTerm.withTags(getTagLabels(printer, record, 7)); + glossaryTerm.withTags(getTagLabels(printer, csvRecord, 7)); if (!processRecord) { return null; } // Field 9 - reviewers - glossaryTerm.withReviewers(getEntityReferences(printer, record, 8, Entity.USER)); + glossaryTerm.withReviewers(getEntityReferences(printer, csvRecord, 8, Entity.USER)); if (!processRecord) { return null; } // Field 10 - owner - glossaryTerm.withOwner(getOwner(printer, record, 9)); + glossaryTerm.withOwner(getOwner(printer, csvRecord, 9)); // Field 11 - status - glossaryTerm.withStatus(getTermStatus(printer, record)); + glossaryTerm.withStatus(getTermStatus(printer, csvRecord)); return glossaryTerm; } - private List getTermReferences(CSVPrinter printer, CSVRecord record) throws IOException { - String termRefs = record.get(6); + private List getTermReferences(CSVPrinter printer, CSVRecord csvRecord) throws IOException { + String termRefs = csvRecord.get(6); if (nullOrEmpty(termRefs)) { return null; } List termRefList = CsvUtil.fieldToStrings(termRefs); if (termRefList.size() % 2 != 0) { // List should have even numbered terms - termName and endPoint - importFailure(printer, invalidField(6, "Term references should termName;endpoint"), record); + importFailure(printer, invalidField(6, "Term references should termName;endpoint"), csvRecord); processRecord = false; return null; } @@ -219,14 +219,14 @@ private List getTermReferences(CSVPrinter printer, CSVRecord reco return list; } - private Status getTermStatus(CSVPrinter printer, CSVRecord record) throws IOException { - String termStatus = record.get(10); + private Status getTermStatus(CSVPrinter printer, CSVRecord csvRecord) throws IOException { + String termStatus = csvRecord.get(10); try { return nullOrEmpty(termStatus) ? Status.DRAFT : Status.fromValue(termStatus); } catch (Exception ex) { // List should have even numbered terms - termName and endPoint importFailure( - printer, invalidField(10, String.format("Glossary term status %s is invalid", termStatus)), record); + printer, invalidField(10, String.format("Glossary term status %s is invalid", termStatus)), csvRecord); processRecord = false; return null; } @@ -234,19 +234,19 @@ private Status getTermStatus(CSVPrinter printer, CSVRecord record) throws IOExce @Override protected List toRecord(GlossaryTerm entity) { - List record = new ArrayList<>(); - addEntityReference(record, entity.getParent()); - addField(record, entity.getName()); - addField(record, entity.getDisplayName()); - addField(record, entity.getDescription()); - CsvUtil.addFieldList(record, entity.getSynonyms()); - addEntityReferences(record, entity.getRelatedTerms()); - addField(record, termReferencesToRecord(entity.getReferences())); - addTagLabels(record, entity.getTags()); - addEntityReferences(record, entity.getReviewers()); - addOwner(record, entity.getOwner()); - addField(record, entity.getStatus().value()); - return record; + List recordList = new ArrayList<>(); + addEntityReference(recordList, entity.getParent()); + addField(recordList, entity.getName()); + addField(recordList, entity.getDisplayName()); + addField(recordList, entity.getDescription()); + CsvUtil.addFieldList(recordList, entity.getSynonyms()); + addEntityReferences(recordList, entity.getRelatedTerms()); + addField(recordList, termReferencesToRecord(entity.getReferences())); + addTagLabels(recordList, entity.getTags()); + addEntityReferences(recordList, entity.getReviewers()); + addOwner(recordList, entity.getOwner()); + addField(recordList, entity.getStatus().value()); + return recordList; } private String termReferencesToRecord(List list) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/IngestionPipelineRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/IngestionPipelineRepository.java index 66f7af62968b..5473a58c8b3f 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/IngestionPipelineRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/IngestionPipelineRepository.java @@ -53,7 +53,7 @@ public class IngestionPipelineRepository extends EntityRepository { + private static final String KPI_RESULT_FIELD = "kpiResult"; public static final String COLLECTION_PATH = "/v1/kpi"; private static final String UPDATE_FIELDS = "owner,targetDefinition,dataInsightChart,startDate,endDate,metricType"; private static final String PATCH_FIELDS = @@ -48,7 +49,7 @@ public KpiRepository(CollectionDAO dao) { @Override public Kpi setFields(Kpi kpi, EntityUtil.Fields fields) throws IOException { kpi.setDataInsightChart(fields.contains("dataInsightChart") ? getDataInsightChart(kpi) : null); - return kpi.withKpiResult(fields.contains("kpiResult") ? getKpiResult(kpi.getFullyQualifiedName()) : null); + return kpi.withKpiResult(fields.contains(KPI_RESULT_FIELD) ? getKpiResult(kpi.getFullyQualifiedName()) : null); } @Override @@ -119,7 +120,7 @@ public RestUtil.PutResponse addKpiResult(UriInfo uriInfo, String fqn, KpiResu } else { daoCollection .entityExtensionTimeSeriesDao() - .insert(kpi.getFullyQualifiedName(), KPI_RESULT_EXTENSION, "kpiResult", JsonUtils.pojoToJson(kpiResult)); + .insert(kpi.getFullyQualifiedName(), KPI_RESULT_EXTENSION, KPI_RESULT_FIELD, JsonUtils.pojoToJson(kpiResult)); } ChangeDescription change = addKpiResultChangeDescription(kpi.getVersion(), kpiResult, storedKpiResult); ChangeEvent changeEvent = getChangeEvent(withHref(uriInfo, kpi), change, entityType, kpi.getVersion()); @@ -147,14 +148,15 @@ public RestUtil.PutResponse deleteKpiResult(String fqn, Long timestamp) throw } private ChangeDescription addKpiResultChangeDescription(Double version, Object newValue, Object oldValue) { - FieldChange fieldChange = new FieldChange().withName("kpiResult").withNewValue(newValue).withOldValue(oldValue); + FieldChange fieldChange = + new FieldChange().withName(KPI_RESULT_FIELD).withNewValue(newValue).withOldValue(oldValue); ChangeDescription change = new ChangeDescription().withPreviousVersion(version); change.getFieldsUpdated().add(fieldChange); return change; } private ChangeDescription deleteKpiChangeDescription(Double version, Object oldValue) { - FieldChange fieldChange = new FieldChange().withName("kpiResult").withOldValue(oldValue); + FieldChange fieldChange = new FieldChange().withName(KPI_RESULT_FIELD).withOldValue(oldValue); ChangeDescription change = new ChangeDescription().withPreviousVersion(version); change.getFieldsDeleted().add(fieldChange); return change; @@ -166,8 +168,8 @@ private EntityReference getDataInsightChart(Kpi kpi) throws IOException { public void validateDataInsightChartOneToOneMapping(UUID chartId) { // Each Chart has one unique Kpi mapping - List record = findTo(chartId, DATA_INSIGHT_CHART, Relationship.USES, KPI); - if (record.size() > 0 && !chartId.equals(record.get(0).getId())) { + List recordList = findTo(chartId, DATA_INSIGHT_CHART, Relationship.USES, KPI); + if (!recordList.isEmpty() && !chartId.equals(recordList.get(0).getId())) { throw new CustomExceptionMessage(Response.Status.BAD_REQUEST, "Chart Already has a mapped Kpi."); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/PipelineRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/PipelineRepository.java index ba4c7b7850f5..f635dede5665 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/PipelineRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/PipelineRepository.java @@ -46,6 +46,7 @@ import org.openmetadata.service.util.ResultList; public class PipelineRepository extends EntityRepository { + private static final String TASK_FIELD = "tasks"; private static final String PIPELINE_UPDATE_FIELDS = "owner,tags,tasks,extension,followers"; private static final String PIPELINE_PATCH_FIELDS = "owner,tags,tasks,extension,followers"; public static final String PIPELINE_STATUS_EXTENSION = "pipeline.pipelineStatus"; @@ -73,7 +74,7 @@ public Pipeline setFields(Pipeline pipeline, Fields fields) throws IOException { pipeline.setService(getContainer(pipeline.getId())); pipeline.setFollowers(fields.contains(FIELD_FOLLOWERS) ? getFollowers(pipeline) : null); getTaskTags(fields.contains(FIELD_TAGS), pipeline.getTasks()); - if (!fields.contains("tasks")) { + if (!fields.contains(TASK_FIELD)) { pipeline.withTasks(null); } return pipeline.withPipelineStatus(fields.contains("pipelineStatus") ? getPipelineStatus(pipeline) : null); @@ -323,7 +324,7 @@ private void updateTasks(Pipeline original, Pipeline updated) throws IOException updateTaskDescription(storedTask, updatedTask); updateTags( storedTask.getFullyQualifiedName(), - EntityUtil.getFieldName("tasks", updatedTask.getName(), FIELD_TAGS), + EntityUtil.getFieldName(TASK_FIELD, updatedTask.getName(), FIELD_TAGS), storedTask.getTags(), updatedTask.getTags()); } @@ -333,7 +334,7 @@ private void updateTasks(Pipeline original, Pipeline updated) throws IOException if (newTasks || removedTasks) { List added = new ArrayList<>(); List deleted = new ArrayList<>(); - recordListChange("tasks", origTasks, updatedTasks, added, deleted, taskMatch); + recordListChange(TASK_FIELD, origTasks, updatedTasks, added, deleted, taskMatch); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/QueryRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/QueryRepository.java index 3ec2f57eb317..d61daaf95dc2 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/QueryRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/QueryRepository.java @@ -26,6 +26,7 @@ import org.openmetadata.service.util.RestUtil; public class QueryRepository extends EntityRepository { + private static final String QUERY_USED_IN_FIELD = "queryUsedIn"; private static final String QUERY_PATCH_FIELDS = "owner,tags,users,followers,query"; private static final String QUERY_UPDATE_FIELDS = "owner,tags,users,votes,followers"; @@ -45,7 +46,7 @@ public QueryRepository(CollectionDAO dao) { public Query setFields(Query entity, EntityUtil.Fields fields) throws IOException { entity.setFollowers(fields.contains(FIELD_FOLLOWERS) ? getFollowers(entity) : null); entity.setVotes(fields.contains("votes") ? this.getVotes(entity) : null); - entity.setQueryUsedIn(fields.contains("queryUsedIn") ? this.getQueryUsage(entity) : null); + entity.setQueryUsedIn(fields.contains(QUERY_USED_IN_FIELD) ? this.getQueryUsage(entity) : null); entity.setUsers(fields.contains("users") ? this.getQueryUsers(entity) : null); return entity; } @@ -124,24 +125,24 @@ public EntityUpdater getUpdater(Query original, Query updated, Operation operati public RestUtil.PutResponse addQueryUsage( UriInfo uriInfo, String updatedBy, UUID queryId, List entityIds) throws IOException { - Query query = Entity.getEntity(Entity.QUERY, queryId, "queryUsedIn", Include.NON_DELETED); + Query query = Entity.getEntity(Entity.QUERY, queryId, QUERY_USED_IN_FIELD, Include.NON_DELETED); List oldValue = query.getQueryUsedIn(); // Create Relationships entityIds.forEach( - (entityRef) -> + entityRef -> addRelationship(entityRef.getId(), queryId, entityRef.getType(), Entity.QUERY, Relationship.MENTIONED_IN)); // Populate Fields - setFieldsInternal(query, new EntityUtil.Fields(allowedFields, "queryUsedIn")); + setFieldsInternal(query, new EntityUtil.Fields(allowedFields, QUERY_USED_IN_FIELD)); Entity.withHref(uriInfo, query.getQueryUsedIn()); ChangeEvent changeEvent = - getQueryChangeEvent(updatedBy, "queryUsedIn", oldValue, query.getQueryUsedIn(), withHref(uriInfo, query)); + getQueryChangeEvent(updatedBy, QUERY_USED_IN_FIELD, oldValue, query.getQueryUsedIn(), withHref(uriInfo, query)); return new RestUtil.PutResponse<>(Response.Status.CREATED, changeEvent, RestUtil.ENTITY_FIELDS_CHANGED); } public RestUtil.PutResponse removeQueryUsedIn( UriInfo uriInfo, String updatedBy, UUID queryId, List entityIds) throws IOException { - Query query = Entity.getEntity(Entity.QUERY, queryId, "queryUsedIn", Include.NON_DELETED); + Query query = Entity.getEntity(Entity.QUERY, queryId, QUERY_USED_IN_FIELD, Include.NON_DELETED); List oldValue = query.getQueryUsedIn(); for (EntityReference ref : entityIds) { @@ -149,10 +150,10 @@ public RestUtil.PutResponse removeQueryUsedIn( } // Populate Fields - setFieldsInternal(query, new EntityUtil.Fields(allowedFields, "queryUsedIn")); + setFieldsInternal(query, new EntityUtil.Fields(allowedFields, QUERY_USED_IN_FIELD)); Entity.withHref(uriInfo, query.getQueryUsedIn()); ChangeEvent changeEvent = - getQueryChangeEvent(updatedBy, "queryUsedIn", oldValue, query.getQueryUsedIn(), withHref(uriInfo, query)); + getQueryChangeEvent(updatedBy, QUERY_USED_IN_FIELD, oldValue, query.getQueryUsedIn(), withHref(uriInfo, query)); return new RestUtil.PutResponse<>(Response.Status.CREATED, changeEvent, RestUtil.ENTITY_FIELDS_CHANGED); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/SystemRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/SystemRepository.java index c0afafa22a30..4ce2d6bec5b6 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/SystemRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/SystemRepository.java @@ -10,6 +10,7 @@ import org.openmetadata.schema.settings.SettingsType; import org.openmetadata.schema.util.EntitiesCount; import org.openmetadata.schema.util.ServicesCount; +import org.openmetadata.service.exception.CustomExceptionMessage; import org.openmetadata.service.fernet.Fernet; import org.openmetadata.service.jdbi3.CollectionDAO.SystemDAO; import org.openmetadata.service.resources.settings.SettingsCache; @@ -129,7 +130,8 @@ public void updateSetting(Settings setting) { } dao.insertSettings(setting.getConfigType().toString(), JsonUtils.pojoToJson(setting.getConfigValue())); } catch (Exception ex) { - throw new RuntimeException(ex); + LOG.error("Failing in Updating Setting.", ex); + throw new CustomExceptionMessage(Response.Status.INTERNAL_SERVER_ERROR, ex.getMessage()); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java index b348eb88b0c8..8fa28b63e6ac 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TeamRepository.java @@ -78,6 +78,7 @@ @Slf4j public class TeamRepository extends EntityRepository { + static final String PARENTS_FIELD = "parents"; static final String TEAM_UPDATE_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies,teamType,email"; static final String TEAM_PATCH_FIELDS = "owner,profile,users,defaultRoles,parents,children,policies,teamType,email"; private static final String DEFAULT_ROLES = "defaultRoles"; @@ -105,7 +106,7 @@ public Team setFields(Team team, Fields fields) throws IOException { team.setDefaultRoles(fields.contains(DEFAULT_ROLES) ? getDefaultRoles(team) : null); team.setInheritedRoles(fields.contains(DEFAULT_ROLES) ? getInheritedRoles(team) : null); team.setOwner(fields.contains(FIELD_OWNER) ? getOwner(team) : null); - team.setParents(fields.contains("parents") ? getParents(team) : null); + team.setParents(fields.contains(PARENTS_FIELD) ? getParents(team) : null); team.setChildren(fields.contains("children") ? getChildren(team.getId()) : null); team.setPolicies(fields.contains("policies") ? getPolicies(team) : null); team.setChildrenCount(fields.contains("childrenCount") ? getChildrenCount(team) : null); @@ -278,7 +279,7 @@ private TeamHierarchy mergeTrees(TeamHierarchy team1, TeamHierarchy team2) { } public List listHierarchy(ListFilter filter, int limit, Boolean isJoinable) throws IOException { - Fields fields = getFields("parents"); + Fields fields = getFields(PARENTS_FIELD); Map map = new HashMap<>(); ResultList resultList = listAfter(null, fields, filter, limit, null); List allTeams = resultList.getData(); @@ -293,7 +294,7 @@ public List listHierarchy(ListFilter filter, int limit, Boolean i Team currentTeam = team; TeamHierarchy currentHierarchy = getTeamHierarchy(team); while (currentTeam != null - && currentTeam.getParents().size() > 0 + && !currentTeam.getParents().isEmpty() && !currentTeam.getParents().get(0).getName().equals(ORGANIZATION_NAME)) { EntityReference parentRef = currentTeam.getParents().get(0); Team parent = @@ -550,36 +551,36 @@ public static class TeamCsv extends EntityCsv { } @Override - protected Team toEntity(CSVPrinter printer, CSVRecord record) throws IOException { + protected Team toEntity(CSVPrinter printer, CSVRecord csvRecord) throws IOException { // Field 1, 2, 3, 4, 7 - name, displayName, description, teamType, isJoinable Team importedTeam = new Team() - .withName(record.get(0)) - .withDisplayName(record.get(1)) - .withDescription(record.get(2)) - .withTeamType(TeamType.fromValue(record.get(3))) - .withIsJoinable(getBoolean(printer, record, 6)); + .withName(csvRecord.get(0)) + .withDisplayName(csvRecord.get(1)) + .withDescription(csvRecord.get(2)) + .withTeamType(TeamType.fromValue(csvRecord.get(3))) + .withIsJoinable(getBoolean(printer, csvRecord, 6)); // Field 5 - parent teams - getParents(printer, record, importedTeam); + getParents(printer, csvRecord, importedTeam); if (!processRecord) { return null; } // Field 6 - Owner - importedTeam.setOwner(getEntityReference(printer, record, 5, Entity.USER)); + importedTeam.setOwner(getEntityReference(printer, csvRecord, 5, Entity.USER)); if (!processRecord) { return null; } // Field 8 - defaultRoles - importedTeam.setDefaultRoles(getEntityReferences(printer, record, 7, ROLE)); + importedTeam.setDefaultRoles(getEntityReferences(printer, csvRecord, 7, ROLE)); if (!processRecord) { return null; } // Field 9 - policies - importedTeam.setPolicies(getEntityReferences(printer, record, 8, POLICY)); + importedTeam.setPolicies(getEntityReferences(printer, csvRecord, 8, POLICY)); if (!processRecord) { return null; } @@ -588,21 +589,21 @@ protected Team toEntity(CSVPrinter printer, CSVRecord record) throws IOException @Override protected List toRecord(Team entity) { - List record = new ArrayList<>(); - addField(record, entity.getName()); - addField(record, entity.getDisplayName()); - addField(record, entity.getDescription()); - addField(record, entity.getTeamType().value()); - addEntityReferences(record, entity.getParents()); - CsvUtil.addEntityReference(record, entity.getOwner()); - addField(record, entity.getIsJoinable()); - addEntityReferences(record, entity.getDefaultRoles()); - addEntityReferences(record, entity.getPolicies()); - return record; - } - - private void getParents(CSVPrinter printer, CSVRecord record, Team importedTeam) throws IOException { - List parentRefs = getEntityReferences(printer, record, 4, Entity.TEAM); + List recordList = new ArrayList<>(); + addField(recordList, entity.getName()); + addField(recordList, entity.getDisplayName()); + addField(recordList, entity.getDescription()); + addField(recordList, entity.getTeamType().value()); + addEntityReferences(recordList, entity.getParents()); + CsvUtil.addEntityReference(recordList, entity.getOwner()); + addField(recordList, entity.getIsJoinable()); + addEntityReferences(recordList, entity.getDefaultRoles()); + addEntityReferences(recordList, entity.getPolicies()); + return recordList; + } + + private void getParents(CSVPrinter printer, CSVRecord csvRecord, Team importedTeam) throws IOException { + List parentRefs = getEntityReferences(printer, csvRecord, 4, Entity.TEAM); // Validate team being created is under the hierarchy of the team for which CSV is being imported to for (EntityReference parentRef : listOrEmpty(parentRefs)) { @@ -614,7 +615,8 @@ private void getParents(CSVPrinter printer, CSVRecord record, Team importedTeam) } // Else the parent should already exist if (!SubjectCache.getInstance().isInTeam(team.getName(), parentRef)) { - importFailure(printer, invalidTeam(4, team.getName(), importedTeam.getName(), parentRef.getName()), record); + importFailure( + printer, invalidTeam(4, team.getName(), importedTeam.getName(), parentRef.getName()), csvRecord); processRecord = false; } } @@ -636,8 +638,8 @@ private List listTeams(TeamRepository repository, String parentTeam, List< return teams; } teams.addAll(list); - for (Team team : list) { - listTeams(repository, team.getName(), teams, fields); + for (Team teamEntry : list) { + listTeams(repository, teamEntry.getName(), teams, fields); } return teams; } @@ -663,7 +665,7 @@ public void entitySpecificUpdate() throws IOException { throw new IllegalArgumentException(INVALID_GROUP_TEAM_UPDATE); } // A team containing children cannot be updated to Group - if (original.getChildren().size() > 0 && GROUP.equals(updated.getTeamType())) { + if (!original.getChildren().isEmpty() && GROUP.equals(updated.getTeamType())) { throw new IllegalArgumentException(INVALID_GROUP_TEAM_CHILDREN_UPDATE); } } @@ -703,7 +705,7 @@ private void updateParents(Team original, Team updated) throws JsonProcessingExc List origParents = listOrEmpty(original.getParents()); List updatedParents = listOrEmpty(updated.getParents()); updateFromRelationships( - "parents", TEAM, origParents, updatedParents, Relationship.PARENT_OF, TEAM, original.getId()); + PARENTS_FIELD, TEAM, origParents, updatedParents, Relationship.PARENT_OF, TEAM, original.getId()); } private void updateChildren(Team original, Team updated) throws JsonProcessingException { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestCaseRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestCaseRepository.java index 5382f5b8a2e1..c25c3152444b 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestCaseRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TestCaseRepository.java @@ -35,6 +35,8 @@ import org.openmetadata.service.util.ResultList; public class TestCaseRepository extends EntityRepository { + private static final String TEST_SUITE_FIELD = "testSuite"; + private static final String TEST_CASE_RESULT_FIELD = "testCaseResult"; public static final String COLLECTION_PATH = "/v1/dataQuality/testCases"; private static final String UPDATE_FIELDS = "owner,entityLink,testSuite,testDefinition"; private static final String PATCH_FIELDS = "owner,entityLink,testSuite,testDefinition"; @@ -46,9 +48,9 @@ public TestCaseRepository(CollectionDAO dao) { @Override public TestCase setFields(TestCase test, EntityUtil.Fields fields) throws IOException { - test.setTestSuite(fields.contains("testSuite") ? getTestSuite(test) : null); + test.setTestSuite(fields.contains(TEST_SUITE_FIELD) ? getTestSuite(test) : null); test.setTestDefinition(fields.contains("testDefinition") ? getTestDefinition(test) : null); - return test.withTestCaseResult(fields.contains("testCaseResult") ? getTestCaseResult(test) : null); + return test.withTestCaseResult(fields.contains(TEST_CASE_RESULT_FIELD) ? getTestCaseResult(test) : null); } @Override @@ -158,10 +160,10 @@ public RestUtil.PutResponse addTestCaseResult( .insert( testCase.getFullyQualifiedName(), TESTCASE_RESULT_EXTENSION, - "testCaseResult", + TEST_CASE_RESULT_FIELD, JsonUtils.pojoToJson(testCaseResult)); } - setFieldsInternal(testCase, new EntityUtil.Fields(allowedFields, "testSuite")); + setFieldsInternal(testCase, new EntityUtil.Fields(allowedFields, TEST_SUITE_FIELD)); ChangeDescription change = addTestCaseChangeDescription(testCase.getVersion(), testCaseResult, storedTestCaseResult); ChangeEvent changeEvent = @@ -193,14 +195,14 @@ public RestUtil.PutResponse deleteTestCaseResult(String updatedBy, String fqn private ChangeDescription addTestCaseChangeDescription(Double version, Object newValue, Object oldValue) { FieldChange fieldChange = - new FieldChange().withName("testCaseResult").withNewValue(newValue).withOldValue(oldValue); + new FieldChange().withName(TEST_CASE_RESULT_FIELD).withNewValue(newValue).withOldValue(oldValue); ChangeDescription change = new ChangeDescription().withPreviousVersion(version); change.getFieldsUpdated().add(fieldChange); return change; } private ChangeDescription deleteTestCaseChangeDescription(Double version, Object oldValue) { - FieldChange fieldChange = new FieldChange().withName("testCaseResult").withOldValue(oldValue); + FieldChange fieldChange = new FieldChange().withName(TEST_CASE_RESULT_FIELD).withOldValue(oldValue); ChangeDescription change = new ChangeDescription().withPreviousVersion(version); change.getFieldsDeleted().add(fieldChange); return change; @@ -268,7 +270,7 @@ public void entitySpecificUpdate() throws IOException { TEST_CASE, updated.getId()); updateFromRelationship( - "testSuite", + TEST_SUITE_FIELD, TEST_SUITE, original.getTestSuite(), updated.getTestSuite(), diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TokenRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TokenRepository.java index ecd12f3bb045..72a9bd5ce083 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TokenRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TokenRepository.java @@ -9,6 +9,7 @@ @Slf4j public class TokenRepository { + static final String TOKEN_NOT_PRESENT_MSG = "Token not present for the user"; private final CollectionDAO dao; public TokenRepository(CollectionDAO dao) { @@ -39,7 +40,7 @@ public void deleteToken(String token) { try { dao.getTokenDAO().delete(token); } catch (Exception ex) { - LOG.info("Token not present for the user"); + LOG.info(TOKEN_NOT_PRESENT_MSG); } } @@ -47,7 +48,7 @@ public void deleteAllToken(List tokens) { try { dao.getTokenDAO().deleteAll(tokens); } catch (Exception ex) { - LOG.info("Token not present for the user"); + LOG.info(TOKEN_NOT_PRESENT_MSG); } } @@ -55,7 +56,7 @@ public void deleteTokenByUserAndType(String userId, String type) { try { dao.getTokenDAO().deleteTokenByUserAndType(userId, type); } catch (Exception ex) { - LOG.info("Token not present for the user"); + LOG.info(TOKEN_NOT_PRESENT_MSG); } } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java index 7c09cb39b0db..2ec961e1d13d 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/UserRepository.java @@ -63,6 +63,8 @@ @Slf4j public class UserRepository extends EntityRepository { + static final String ROLES_FIELD = "roles"; + public static final String AUTH_MECHANISM_FIELD = "authenticationMechanism"; static final String USER_PATCH_FIELDS = "profile,roles,teams,authenticationMechanism,isEmailVerified"; static final String USER_UPDATE_FIELDS = "profile,roles,teams,authenticationMechanism,isEmailVerified"; private final EntityReference organization; @@ -83,7 +85,7 @@ public UserRepository(CollectionDAO dao) { public final Fields getFieldsWithUserAuth(String fields) { List tempFields = getAllowedFieldsCopy(); if (fields != null && fields.equals("*")) { - tempFields.add("authenticationMechanism"); + tempFields.add(AUTH_MECHANISM_FIELD); return new Fields(tempFields, String.join(",", tempFields)); } return new Fields(tempFields, fields); @@ -166,11 +168,10 @@ public User setFields(User user, Fields fields) throws IOException { user.setTeams(fields.contains("teams") ? getTeams(user) : null); user.setOwns(fields.contains("owns") ? getOwns(user) : null); user.setFollows(fields.contains("follows") ? getFollows(user) : null); - user.setRoles(fields.contains("roles") ? getRoles(user) : null); - user.setAuthenticationMechanism( - fields.contains("authenticationMechanism") ? user.getAuthenticationMechanism() : null); + user.setRoles(fields.contains(ROLES_FIELD) ? getRoles(user) : null); + user.setAuthenticationMechanism(fields.contains(AUTH_MECHANISM_FIELD) ? user.getAuthenticationMechanism() : null); user.setIsEmailVerified(fields.contains("isEmailVerified") ? user.getIsEmailVerified() : null); - return user.withInheritedRoles(fields.contains("roles") ? getInheritedRoles(user) : null); + return user.withInheritedRoles(fields.contains(ROLES_FIELD) ? getInheritedRoles(user) : null); } @Override @@ -334,25 +335,25 @@ public static class UserCsv extends EntityCsv { } @Override - protected User toEntity(CSVPrinter printer, CSVRecord record) throws IOException { + protected User toEntity(CSVPrinter printer, CSVRecord csvRecord) throws IOException { // Field 1, 2, 3, 4, 5, 6 - name, displayName, description, email, timezone, isAdmin User user = new User() - .withName(record.get(0)) - .withDisplayName(record.get(1)) - .withDescription(record.get(2)) - .withEmail(record.get(3)) - .withTimezone(record.get(4)) - .withIsAdmin(getBoolean(printer, record, 5)); + .withName(csvRecord.get(0)) + .withDisplayName(csvRecord.get(1)) + .withDescription(csvRecord.get(2)) + .withEmail(csvRecord.get(3)) + .withTimezone(csvRecord.get(4)) + .withIsAdmin(getBoolean(printer, csvRecord, 5)); // Field 7 - team - user.setTeams(getTeams(printer, record, user.getName())); + user.setTeams(getTeams(printer, csvRecord, user.getName())); if (!processRecord) { return null; } // Field 8 - roles - user.setRoles(getEntityReferences(printer, record, 7, ROLE)); + user.setRoles(getEntityReferences(printer, csvRecord, 7, ROLE)); if (!processRecord) { return null; } @@ -364,16 +365,16 @@ protected User toEntity(CSVPrinter printer, CSVRecord record) throws IOException @Override protected List toRecord(User entity) { // Headers - name,displayName,description,email,timezone,isAdmin,team,roles - List record = new ArrayList<>(); - addField(record, entity.getName()); - addField(record, entity.getDisplayName()); - addField(record, entity.getDescription()); - addField(record, entity.getEmail()); - addField(record, entity.getTimezone()); - addField(record, entity.getIsAdmin()); - addField(record, entity.getTeams().get(0).getFullyQualifiedName()); - addEntityReferences(record, entity.getRoles()); - return record; + List recordList = new ArrayList<>(); + addField(recordList, entity.getName()); + addField(recordList, entity.getDisplayName()); + addField(recordList, entity.getDescription()); + addField(recordList, entity.getEmail()); + addField(recordList, entity.getTimezone()); + addField(recordList, entity.getIsAdmin()); + addField(recordList, entity.getTeams().get(0).getFullyQualifiedName()); + addEntityReferences(recordList, entity.getRoles()); + return recordList; } private List listUsers( @@ -394,8 +395,8 @@ private List listUsers( filter = new ListFilter(Include.NON_DELETED).addQueryParam("parentTeam", parentTeam); List teamList = teamRepository.listAll(Fields.EMPTY_FIELDS, filter); - for (Team team : teamList) { - listUsers(teamRepository, userRepository, team.getName(), users, fields); + for (Team teamEntry : teamList) { + listUsers(teamRepository, userRepository, teamEntry.getName(), users, fields); } return users; } @@ -407,8 +408,8 @@ public String exportCsv() throws IOException { return exportCsv(listUsers(teamRepository, userRepository, team.getName(), new ArrayList<>(), fields)); } - private List getTeams(CSVPrinter printer, CSVRecord record, String user) throws IOException { - List teams = getEntityReferences(printer, record, 6, Entity.TEAM); + private List getTeams(CSVPrinter printer, CSVRecord csvRecord, String user) throws IOException { + List teams = getEntityReferences(printer, csvRecord, 6, Entity.TEAM); // Validate team being created is under the hierarchy of the team for which CSV is being imported to for (EntityReference teamRef : listOrEmpty(teams)) { @@ -417,7 +418,7 @@ private List getTeams(CSVPrinter printer, CSVRecord record, Str } // Else the parent should already exist if (!SubjectCache.getInstance().isInTeam(team.getName(), teamRef)) { - importFailure(printer, invalidTeam(6, team.getName(), user, teamRef.getName()), record); + importFailure(printer, invalidTeam(6, team.getName(), user, teamRef.getName()), csvRecord); processRecord = false; } } @@ -462,7 +463,7 @@ private void updateRoles(User original, User updated) throws IOException { List added = new ArrayList<>(); List deleted = new ArrayList<>(); - recordListChange("roles", origRoles, updatedRoles, added, deleted, EntityUtil.entityReferenceMatch); + recordListChange(ROLES_FIELD, origRoles, updatedRoles, added, deleted, EntityUtil.entityReferenceMatch); } private void updateTeams(User original, User updated) throws IOException { @@ -485,11 +486,11 @@ private void updateAuthenticationMechanism(User original, User updated) throws I AuthenticationMechanism origAuthMechanism = original.getAuthenticationMechanism(); AuthenticationMechanism updatedAuthMechanism = updated.getAuthenticationMechanism(); if (origAuthMechanism == null && updatedAuthMechanism != null) { - recordChange("authenticationMechanism", original.getAuthenticationMechanism(), "new-encrypted-value"); + recordChange(AUTH_MECHANISM_FIELD, original.getAuthenticationMechanism(), "new-encrypted-value"); } else if (origAuthMechanism != null && updatedAuthMechanism != null && !JsonUtils.areEquals(origAuthMechanism, updatedAuthMechanism)) { - recordChange("authenticationMechanism", "old-encrypted-value", "new-encrypted-value"); + recordChange(AUTH_MECHANISM_FIELD, "old-encrypted-value", "new-encrypted-value"); } } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/monitoring/EventMonitorFactory.java b/openmetadata-service/src/main/java/org/openmetadata/service/monitoring/EventMonitorFactory.java index 43d7b1782899..b62e2ca1509f 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/monitoring/EventMonitorFactory.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/monitoring/EventMonitorFactory.java @@ -14,7 +14,11 @@ import org.openmetadata.schema.monitoring.EventMonitorProvider; -public class EventMonitorFactory { +public final class EventMonitorFactory { + + private EventMonitorFactory() { + /* Cannot be constructed. */ + } public static EventMonitor createEventMonitor(EventMonitorConfiguration config, String clusterName) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/monitoring/PrometheusEventMonitor.java b/openmetadata-service/src/main/java/org/openmetadata/service/monitoring/PrometheusEventMonitor.java index b955bb03ad33..2fe2adec1c76 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/monitoring/PrometheusEventMonitor.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/monitoring/PrometheusEventMonitor.java @@ -64,7 +64,7 @@ protected void pushMetric(ChangeEvent event) { incrementIngestionPipelineCounter(fqn, pipelineType, pipelineStatus.getPipelineState().value()); } }); - + break; default: throw new IllegalArgumentException("Invalid EventType " + event.getEventType()); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/dataInsight/DataInsightChartResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/dataInsight/DataInsightChartResource.java index d814ed27372e..842042cd8a6e 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/dataInsight/DataInsightChartResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/dataInsight/DataInsightChartResource.java @@ -109,6 +109,7 @@ public DataInsightChartResultList( } } + @Override public void initialize(OpenMetadataApplicationConfig config) throws IOException { // instantiate an elasticsearch client if (config.getElasticSearchConfiguration() != null) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/databases/DatabaseUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/databases/DatabaseUtil.java index 33726d2f42db..e39cac430e10 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/databases/DatabaseUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/databases/DatabaseUtil.java @@ -140,10 +140,8 @@ public static void validateArrayColumn(Column column) { column.setArrayDataType(null); } - if (dataType == ColumnDataType.ARRAY) { - if (column.getArrayDataType() == null) { - throw new IllegalArgumentException("For column data type array, arrayDataType " + "must not be null"); - } + if (dataType == ColumnDataType.ARRAY && (column.getArrayDataType() == null)) { + throw new IllegalArgumentException("For column data type array, arrayDataType " + "must not be null"); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/events/EventResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/events/EventResource.java index eb48b2a7182c..a0cdaf1839ff 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/events/EventResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/events/EventResource.java @@ -50,9 +50,7 @@ @Consumes(MediaType.APPLICATION_JSON) @Collection(name = "events") public class EventResource { - @Getter private final ChangeEventRepository dao; - private final Authorizer authorizer; public static class EventList extends ResultList { @@ -67,7 +65,6 @@ public EventList(List data, String beforeCursor, String afterCursor public EventResource(CollectionDAO dao, Authorizer authorizer) { Objects.requireNonNull(dao, "ChangeEventRepository must not be null"); this.dao = new ChangeEventRepository(dao); - this.authorizer = authorizer; } @GET @@ -121,6 +118,6 @@ public ResultList get( List entityDeletedList = EntityList.getEntityList("entityDeleted", entityDeleted); List events = dao.list(timestamp, entityCreatedList, entityUpdatedList, entityDeletedList); events.sort(EntityUtil.compareChangeEvent); // Sort change events based on time - return new EventList(events, null, null, events.size()); // TODO + return new EventList(events, null, null, events.size()); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/events/subscription/EventSubscriptionResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/events/subscription/EventSubscriptionResource.java index 818eb7c788bd..fda1e4ca1be5 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/events/subscription/EventSubscriptionResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/events/subscription/EventSubscriptionResource.java @@ -107,7 +107,9 @@ public EventSubscriptionResource(CollectionDAO dao, Authorizer authorizer) { public static class EventSubscriptionList extends ResultList { @SuppressWarnings("unused") /* Required for tests */ - public EventSubscriptionList() {} + public EventSubscriptionList() { + /* unused */ + } } public static class EventSubResourceDescriptorList extends ResultList { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/lineage/LineageResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/lineage/LineageResource.java index 150efb71272b..7c67b9bbde40 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/lineage/LineageResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/lineage/LineageResource.java @@ -67,6 +67,7 @@ @Consumes(MediaType.APPLICATION_JSON) @Collection(name = "lineage") public class LineageResource { + static final String LINEAGE_FIELD = "lineage"; private final LineageRepository dao; private final Authorizer authorizer; @@ -172,7 +173,9 @@ public Response addLineage( @Context UriInfo uriInfo, @Context SecurityContext securityContext, @Valid AddLineage addLineage) throws IOException { authorizer.authorize( - securityContext, new OperationContext("lineage", MetadataOperation.EDIT_LINEAGE), new LineageResourceContext()); + securityContext, + new OperationContext(LINEAGE_FIELD, MetadataOperation.EDIT_LINEAGE), + new LineageResourceContext()); dao.addLineage(addLineage); return Response.status(Status.OK).build(); } @@ -208,7 +211,9 @@ public Response deleteLineage( String toId) throws IOException { authorizer.authorize( - securityContext, new OperationContext("lineage", MetadataOperation.EDIT_LINEAGE), new LineageResourceContext()); + securityContext, + new OperationContext(LINEAGE_FIELD, MetadataOperation.EDIT_LINEAGE), + new LineageResourceContext()); boolean deleted = dao.deleteLineage(fromEntity, fromId, toEntity, toId); if (!deleted) { @@ -229,7 +234,7 @@ static class LineageResourceContext implements ResourceContextInterface { @Override public String getResource() { - return "lineage"; + return LINEAGE_FIELD; } @Override diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/search/SearchResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/search/SearchResource.java index 1c66d144b2b9..eb6b4216abea 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/search/SearchResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/search/SearchResource.java @@ -97,6 +97,10 @@ @Produces(MediaType.APPLICATION_JSON) @Collection(name = "search") public class SearchResource { + static final String ES_MESSAGE_SCHEMA_FIELD = "messageSchema.schemaFields.name"; + static final String ES_TAG_FQN_FIELD = "tags.tagFQN"; + static final String PRE_TAG = ""; + static final String POST_TAG = ""; private RestHighLevelClient client; private static final Integer MAX_AGGREGATE_SIZE = 50; private static final Integer MAX_RESULT_HITS = 10000; @@ -237,10 +241,10 @@ public Response search( searchSourceBuilder = buildTableSearchBuilder(query, from, size); break; case "user_search_index": - searchSourceBuilder = buildUserSearchBuilder(query, from, size); + searchSourceBuilder = buildUserOrTeamSearchBuilder(query, from, size); break; case "team_search_index": - searchSourceBuilder = buildTeamSearchBuilder(query, from, size); + searchSourceBuilder = buildUserOrTeamSearchBuilder(query, from, size); break; case "glossary_search_index": searchSourceBuilder = buildGlossaryTermSearchBuilder(query, from, size); @@ -453,12 +457,14 @@ public Response reindexAllJobLastStatus(@Context UriInfo uriInfo, @Context Secur // Only admins can issue a reindex request authorizer.authorizeAdmin(securityContext); // Check if there is a running job for reindex for requested entity - String record; - record = + String jobRecord; + jobRecord = dao.entityExtensionTimeSeriesDao() .getLatestExtension(ELASTIC_SEARCH_ENTITY_FQN_STREAM, ELASTIC_SEARCH_EXTENSION); - if (record != null) { - return Response.status(Response.Status.OK).entity(JsonUtils.readValue(record, EventPublisherJob.class)).build(); + if (jobRecord != null) { + return Response.status(Response.Status.OK) + .entity(JsonUtils.readValue(jobRecord, EventPublisherJob.class)) + .build(); } return Response.status(Response.Status.NOT_FOUND).entity("No Last Run.").build(); } @@ -592,8 +598,8 @@ private SearchSourceBuilder buildTableSearchBuilder(String query, int from, int hb.field(highlightColumns); hb.field(highlightColumnDescriptions); hb.field(highlightColumnChildren); - hb.preTags(""); - hb.postTags(""); + hb.preTags(PRE_TAG); + hb.postTags(POST_TAG); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(queryBuilder).highlighter(hb).from(from).size(size); searchSourceBuilder.aggregation(AggregationBuilders.terms("database.name.keyword").field("database.name.keyword")); @@ -614,7 +620,7 @@ private SearchSourceBuilder buildTopicSearchBuilder(String query, int from, int .field(DISPLAY_NAME_KEYWORD, 25.0f) .field(NAME_KEYWORD, 25.0f) .field(FIELD_DESCRIPTION, 1.0f) - .field("messageSchema.schemaFields.name", 2.0f) + .field(ES_MESSAGE_SCHEMA_FIELD, 2.0f) .field("messageSchema.schemaFields.description", 1.0f) .field("messageSchema.schemaFields.children.name", 2.0f) .defaultOperator(Operator.AND) @@ -629,8 +635,7 @@ private SearchSourceBuilder buildTopicSearchBuilder(String query, int from, int hb.field(new HighlightBuilder.Field("messageSchema.schemaFields.description").highlighterType(UNIFIED)); hb.field(new HighlightBuilder.Field("messageSchema.schemaFields.children.name").highlighterType(UNIFIED)); SearchSourceBuilder searchSourceBuilder = searchBuilder(queryBuilder, hb, from, size); - searchSourceBuilder.aggregation( - AggregationBuilders.terms("messageSchema.schemaFields.name").field("messageSchema.schemaFields.name")); + searchSourceBuilder.aggregation(AggregationBuilders.terms(ES_MESSAGE_SCHEMA_FIELD).field(ES_MESSAGE_SCHEMA_FIELD)); return addAggregation(searchSourceBuilder); } @@ -765,8 +770,8 @@ private SearchSourceBuilder buildContainerSearchBuilder(String query, int from, hb.field(highlightColumns); hb.field(highlightColumnDescriptions); hb.field(highlightColumnChildren); - hb.preTags(""); - hb.postTags(""); + hb.preTags(PRE_TAG); + hb.postTags(POST_TAG); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(queryBuilder).highlighter(hb).from(from).size(size); return addAggregation(searchSourceBuilder); @@ -794,8 +799,8 @@ private SearchSourceBuilder buildQuerySearchBuilder(String query, int from, int hb.field(highlightDescription); hb.field(highlightGlossaryName); hb.field(highlightQuery); - hb.preTags(""); - hb.postTags(""); + hb.preTags(PRE_TAG); + hb.postTags(POST_TAG); return searchBuilder(queryBuilder, hb, from, size); } @@ -803,8 +808,8 @@ private SearchSourceBuilder buildQuerySearchBuilder(String query, int from, int private SearchSourceBuilder searchBuilder(QueryBuilder queryBuilder, HighlightBuilder hb, int from, int size) { SearchSourceBuilder builder = new SearchSourceBuilder().query(queryBuilder).from(from).size(size); if (hb != null) { - hb.preTags(""); - hb.postTags(""); + hb.preTags(PRE_TAG); + hb.postTags(POST_TAG); builder.highlighter(hb); } return builder; @@ -817,25 +822,12 @@ private SearchSourceBuilder addAggregation(SearchSourceBuilder builder) { AggregationBuilders.terms("service.name.keyword").field("service.name.keyword").size(MAX_AGGREGATE_SIZE)) .aggregation(AggregationBuilders.terms("entityType").field("entityType").size(MAX_AGGREGATE_SIZE)) .aggregation(AggregationBuilders.terms("tier.tagFQN").field("tier.tagFQN")) - .aggregation(AggregationBuilders.terms("tags.tagFQN").field("tags.tagFQN").size(MAX_AGGREGATE_SIZE)); + .aggregation(AggregationBuilders.terms(ES_TAG_FQN_FIELD).field(ES_TAG_FQN_FIELD).size(MAX_AGGREGATE_SIZE)); return builder; } - private SearchSourceBuilder buildUserSearchBuilder(String query, int from, int size) { - QueryStringQueryBuilder queryBuilder = - QueryBuilders.queryStringQuery(query) - .field(DISPLAY_NAME, 3.0f) - .field(DISPLAY_NAME_KEYWORD, 5.0f) - .field(FIELD_DISPLAY_NAME_NGRAM) - .field(FIELD_NAME, 2.0f) - .field(NAME_KEYWORD, 3.0f) - .defaultOperator(Operator.AND) - .fuzziness(Fuzziness.AUTO); - return searchBuilder(queryBuilder, null, from, size); - } - - private SearchSourceBuilder buildTeamSearchBuilder(String query, int from, int size) { + private SearchSourceBuilder buildUserOrTeamSearchBuilder(String query, int from, int size) { QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery(query) .field(DISPLAY_NAME, 3.0f) @@ -881,12 +873,12 @@ private SearchSourceBuilder buildGlossaryTermSearchBuilder(String query, int fro hb.field(highlightGlossaryDisplayName); hb.field(highlightSynonym); - hb.preTags(""); - hb.postTags(""); + hb.preTags(PRE_TAG); + hb.postTags(POST_TAG); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(queryBuilder).highlighter(hb).from(from).size(size); searchSourceBuilder - .aggregation(AggregationBuilders.terms("tags.tagFQN").field("tags.tagFQN").size(MAX_AGGREGATE_SIZE)) + .aggregation(AggregationBuilders.terms(ES_TAG_FQN_FIELD).field(ES_TAG_FQN_FIELD).size(MAX_AGGREGATE_SIZE)) .aggregation(AggregationBuilders.terms("glossary.name.keyword").field("glossary.name.keyword")); return searchSourceBuilder; } @@ -911,8 +903,8 @@ private SearchSourceBuilder buildTagSearchBuilder(String query, int from, int si hb.field(highlightTagDisplayName); hb.field(highlightDescription); hb.field(highlightTagName); - hb.preTags(""); - hb.postTags(""); + hb.preTags(PRE_TAG); + hb.postTags(POST_TAG); return searchBuilder(queryBuilder, hb, from, size); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/dashboard/DashboardServiceResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/dashboard/DashboardServiceResource.java index bafe0ab00b4a..1fe45586a1fb 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/dashboard/DashboardServiceResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/dashboard/DashboardServiceResource.java @@ -94,7 +94,9 @@ public DashboardServiceResource(CollectionDAO dao, Authorizer authorizer) { public static class DashboardServiceList extends ResultList { @SuppressWarnings("unused") /* Required for tests */ - public DashboardServiceList() {} + public DashboardServiceList() { + /* unused */ + } } @GET diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/database/DatabaseServiceResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/database/DatabaseServiceResource.java index d2c6c3014d7b..e152d9ac2393 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/database/DatabaseServiceResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/database/DatabaseServiceResource.java @@ -98,7 +98,9 @@ public DatabaseServiceResource(CollectionDAO dao, Authorizer authorizer) { public static class DatabaseServiceList extends ResultList { @SuppressWarnings("unused") /* Required for tests */ - public DatabaseServiceList() {} + public DatabaseServiceList() { + /* unused */ + } } @GET diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/ingestionpipelines/IngestionPipelineResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/ingestionpipelines/IngestionPipelineResource.java index 9cc0258be61e..ce85e70dc8fa 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/ingestionpipelines/IngestionPipelineResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/ingestionpipelines/IngestionPipelineResource.java @@ -16,6 +16,7 @@ import static org.openmetadata.common.utils.CommonUtil.listOrEmpty; import static org.openmetadata.service.Entity.FIELD_OWNER; import static org.openmetadata.service.Entity.FIELD_PIPELINE_STATUS; +import static org.openmetadata.service.jdbi3.IngestionPipelineRepository.validateProfileSample; import static org.openmetadata.service.resources.services.metadata.MetadataServiceResource.OPENMETADATA_SERVICE; import io.swagger.v3.oas.annotations.ExternalDocumentation; @@ -408,7 +409,7 @@ public Response create( throws IOException { IngestionPipeline ingestionPipeline = getIngestionPipeline(create, securityContext.getUserPrincipal().getName()); Response response = create(uriInfo, securityContext, ingestionPipeline); - dao.validateProfileSample(ingestionPipeline); + validateProfileSample(ingestionPipeline); decryptOrNullify(securityContext, (IngestionPipeline) response.getEntity(), false); return response; } @@ -460,7 +461,7 @@ public Response createOrUpdate( IngestionPipeline ingestionPipeline = getIngestionPipeline(update, securityContext.getUserPrincipal().getName()); unmask(ingestionPipeline); Response response = createOrUpdate(uriInfo, securityContext, ingestionPipeline); - dao.validateProfileSample(ingestionPipeline); + validateProfileSample(ingestionPipeline); decryptOrNullify(securityContext, (IngestionPipeline) response.getEntity(), false); return response; } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/messaging/MessagingServiceResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/messaging/MessagingServiceResource.java index 204793e321b0..d638d4c92d9f 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/messaging/MessagingServiceResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/messaging/MessagingServiceResource.java @@ -94,7 +94,9 @@ public MessagingServiceResource(CollectionDAO dao, Authorizer authorizer) { public static class MessagingServiceList extends ResultList { @SuppressWarnings("unused") /* Required for tests */ - public MessagingServiceList() {} + public MessagingServiceList() { + /* unused */ + } } @GET diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/metadata/MetadataServiceResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/metadata/MetadataServiceResource.java index 60f40456eac4..adb19ec77807 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/metadata/MetadataServiceResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/metadata/MetadataServiceResource.java @@ -81,6 +81,7 @@ public class MetadataServiceResource public static final String COLLECTION_PATH = "v1/services/metadataServices/"; public static final String FIELDS = "pipelines,owner,tags"; + @Override public void initialize(OpenMetadataApplicationConfig config) { registerMetadataServices(config); } @@ -100,7 +101,7 @@ private void registerMetadataServices(OpenMetadataApplicationConfig config) { dao.setFullyQualifiedName(service); dao.initializeEntity(service); } else { - throw new RuntimeException("Only one Openmetadata Service can be initialized from the Data."); + throw new IOException("Only one Openmetadata Service can be initialized from the Data."); } } else { LOG.error("[MetadataService] Missing Elastic Search Config."); @@ -124,7 +125,9 @@ public MetadataServiceResource(CollectionDAO dao, Authorizer authorizer) { public static class MetadataServiceList extends ResultList { @SuppressWarnings("unused") /* Required for tests */ - public MetadataServiceList() {} + public MetadataServiceList() { + /* unused */ + } } @GET @@ -296,8 +299,8 @@ public EntityHistory listVersions( .map( json -> { try { - MetadataService MetadataService = JsonUtils.readValue((String) json, MetadataService.class); - return JsonUtils.pojoToJson(decryptOrNullify(securityContext, MetadataService)); + MetadataService metadataService = JsonUtils.readValue((String) json, MetadataService.class); + return JsonUtils.pojoToJson(decryptOrNullify(securityContext, metadataService)); } catch (IOException e) { return json; } @@ -492,7 +495,7 @@ protected String extractServiceType(MetadataService service) { return service.getServiceType().value(); } - private ElasticsSearch getElasticSearchConnectionSink(ElasticSearchConfiguration esConfig) { + private ElasticsSearch getElasticSearchConnectionSink(ElasticSearchConfiguration esConfig) throws IOException { if (Objects.nonNull(esConfig)) { ElasticsSearch sink = new ElasticsSearch(); ComponentConfig componentConfig = new ComponentConfig(); @@ -506,7 +509,7 @@ private ElasticsSearch getElasticSearchConnectionSink(ElasticSearchConfiguration .withAdditionalProperty("scheme", esConfig.getScheme())); return sink; } else { - throw new RuntimeException("Elastic Search Configuration Missing"); + throw new IOException("Elastic Search Configuration Missing"); } } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/mlmodel/MlModelServiceResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/mlmodel/MlModelServiceResource.java index 790640059285..1302efc64f2e 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/mlmodel/MlModelServiceResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/mlmodel/MlModelServiceResource.java @@ -93,7 +93,9 @@ public MlModelServiceResource(CollectionDAO dao, Authorizer authorizer) { public static class MlModelServiceList extends ResultList { @SuppressWarnings("unused") /* Required for tests */ - public MlModelServiceList() {} + public MlModelServiceList() { + /* unused */ + } } @GET diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/pipeline/PipelineServiceResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/pipeline/PipelineServiceResource.java index fb1ec854845d..16d8e049ad5b 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/pipeline/PipelineServiceResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/pipeline/PipelineServiceResource.java @@ -92,7 +92,9 @@ public PipelineServiceResource(CollectionDAO dao, Authorizer authorizer) { public static class PipelineServiceList extends ResultList { @SuppressWarnings("unused") /* Required for tests */ - public PipelineServiceList() {} + public PipelineServiceList() { + /* unused */ + } } @GET diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/storage/StorageServiceResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/storage/StorageServiceResource.java index f64b96e5d5e0..6b2f993afe28 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/storage/StorageServiceResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/storage/StorageServiceResource.java @@ -85,7 +85,9 @@ public StorageServiceResource(CollectionDAO dao, Authorizer authorizer) { public static class StorageServiceList extends ResultList { @SuppressWarnings("unused") /* Required for tests */ - public StorageServiceList() {} + public StorageServiceList() { + /* unused */ + } } @GET diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/settings/SettingsCache.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/settings/SettingsCache.java index f6e2229cf115..d8975cb9a9b7 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/settings/SettingsCache.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/settings/SettingsCache.java @@ -25,6 +25,7 @@ import org.openmetadata.schema.settings.Settings; import org.openmetadata.schema.settings.SettingsType; import org.openmetadata.service.OpenMetadataApplicationConfig; +import org.openmetadata.service.exception.EntityNotFoundException; import org.openmetadata.service.jdbi3.CollectionDAO; import org.openmetadata.service.jdbi3.SystemRepository; import org.openmetadata.service.util.JsonUtils; @@ -61,12 +62,13 @@ public static SettingsCache getInstance() { return INSTANCE; } - public T getSetting(SettingsType settingName, Class clazz) throws RuntimeException { + public T getSetting(SettingsType settingName, Class clazz) { try { String json = JsonUtils.pojoToJson(SETTINGS_CACHE.get(settingName.toString()).getConfigValue()); return JsonUtils.readValue(json, clazz); } catch (Exception ex) { - throw new RuntimeException(ex); + LOG.error("Failed to fetch Settings . Setting {}", settingName, ex); + throw new EntityNotFoundException("Setting not found"); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/UserResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/UserResource.java index 687c71d1e73f..ce4232898946 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/UserResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/teams/UserResource.java @@ -21,6 +21,7 @@ import static org.openmetadata.schema.entity.teams.AuthenticationMechanism.AuthType.BASIC; import static org.openmetadata.schema.entity.teams.AuthenticationMechanism.AuthType.JWT; import static org.openmetadata.service.exception.CatalogExceptionMessage.EMAIL_SENDING_ISSUE; +import static org.openmetadata.service.jdbi3.UserRepository.AUTH_MECHANISM_FIELD; import static org.openmetadata.service.security.jwt.JWTTokenGenerator.getExpiryDate; import at.favre.lib.crypto.bcrypt.BCrypt; @@ -188,12 +189,16 @@ public void initialize(OpenMetadataApplicationConfig config) { public static class UserList extends ResultList { @SuppressWarnings("unused") // Used for deserialization - public UserList() {} + public UserList() { + /* unused */ + } } public static class PersonalAccessTokenList extends ResultList { @SuppressWarnings("unused") // Used for deserialization - public PersonalAccessTokenList() {} + public PersonalAccessTokenList() { + /* unused */ + } } static final String FIELDS = "profile,roles,teams,follows,owns"; @@ -616,7 +621,7 @@ public Response revokeToken( throws IOException { authorizer.authorizeAdmin(securityContext); User user = dao.get(uriInfo, revokeTokenRequest.getId(), dao.getFieldsWithUserAuth("*")); - if (!user.getIsBot()) { + if (Boolean.FALSE.equals(user.getIsBot())) { throw new IllegalStateException(CatalogExceptionMessage.INVALID_BOT_USER); } JWTAuthMechanism jwtAuthMechanism = new JWTAuthMechanism().withJWTToken(StringUtils.EMPTY); @@ -650,7 +655,7 @@ public JWTAuthMechanism getToken( @Parameter(description = "Id of the user", schema = @Schema(type = "UUID")) @PathParam("id") UUID id) throws IOException { - User user = dao.get(uriInfo, id, new Fields(List.of("authenticationMechanism"))); + User user = dao.get(uriInfo, id, new Fields(List.of(AUTH_MECHANISM_FIELD))); if (!Boolean.TRUE.equals(user.getIsBot())) { throw new IllegalArgumentException("JWT token is only supported for bot users"); } @@ -687,7 +692,7 @@ public AuthenticationMechanism getAuthenticationMechanism( @Parameter(description = "Id of the user", schema = @Schema(type = "UUID")) @PathParam("id") UUID id) throws IOException { - User user = dao.get(uriInfo, id, new Fields(List.of("authenticationMechanism"))); + User user = dao.get(uriInfo, id, new Fields(List.of(AUTH_MECHANISM_FIELD))); if (!Boolean.TRUE.equals(user.getIsBot())) { throw new IllegalArgumentException("JWT token is only supported for bot users"); } @@ -1133,7 +1138,7 @@ public Response createAccessToken( throws IOException { String userName = securityContext.getUserPrincipal().getName(); User user = dao.getByName(null, userName, getFields("email,isBot"), Include.NON_DELETED); - if (!user.getIsBot()) { + if (Boolean.FALSE.equals(user.getIsBot())) { // Create Personal Access Token JWTAuthMechanism authMechanism = JWTTokenGenerator.getInstance() @@ -1239,7 +1244,7 @@ private User getUser(SecurityContext securityContext, CreateUser create) { public void validateEmailAlreadyExists(String email) { if (dao.checkEmailAlreadyExists(email)) { - throw new RuntimeException("User with Email Already Exists"); + throw new CustomExceptionMessage(BAD_REQUEST, "User with Email Already Exists"); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/types/TypeResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/types/TypeResource.java index bdf9eae50675..c7bf6a79a56e 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/types/TypeResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/types/TypeResource.java @@ -103,7 +103,7 @@ public void initialize(OpenMetadataApplicationConfig config) throws IOException type.withId(UUID.randomUUID()).withUpdatedBy(ADMIN_USER_NAME).withUpdatedAt(now); LOG.info("Loading type {}", type.getName()); try { - Fields fields = getFields("customProperties"); + Fields fields = getFields(PROPERTIES_FIELD); try { Type storedType = dao.getByName(null, type.getName(), fields); type.setId(storedType.getId()); @@ -130,6 +130,7 @@ public static class TypeList extends ResultList { } public static final String PROPERTIES = "customProperties"; + public static final String PROPERTIES_FIELD = "customProperties"; @GET @Valid diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/sandbox/SandboxConfiguration.java b/openmetadata-service/src/main/java/org/openmetadata/service/sandbox/SandboxConfiguration.java deleted file mode 100644 index 8082a7eecafb..000000000000 --- a/openmetadata-service/src/main/java/org/openmetadata/service/sandbox/SandboxConfiguration.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openmetadata.service.sandbox; - -public class SandboxConfiguration { - private boolean isSandboxModeEnabled; - - public boolean isSandboxModeEnabled() { - return isSandboxModeEnabled; - } - - public void setSandboxModeEnabled(boolean sandboxModeEnabled) { - isSandboxModeEnabled = sandboxModeEnabled; - } -} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/secrets/SecretsManagerUpdateService.java b/openmetadata-service/src/main/java/org/openmetadata/service/secrets/SecretsManagerUpdateService.java index 84e17042b96b..ba20298d002f 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/secrets/SecretsManagerUpdateService.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/secrets/SecretsManagerUpdateService.java @@ -167,17 +167,16 @@ private List retrieveServices(ServiceEntityRepository, ServiceEntityRepository> retrieveConnectionTypeRepositoriesMap() { - Map, ServiceEntityRepository> - connectionTypeRepositoriesMap = - CollectionRegistry.getInstance().getCollectionMap().values().stream() - .map(this::retrieveServiceRepository) - .filter(Optional::isPresent) - .map(Optional::get) - .collect(Collectors.toMap(ServiceEntityRepository::getServiceConnectionClass, Function.identity())); - if (connectionTypeRepositoriesMap.isEmpty()) { + Map, ServiceEntityRepository> connTypeRepositoriesMap = + CollectionRegistry.getInstance().getCollectionMap().values().stream() + .map(this::retrieveServiceRepository) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toMap(ServiceEntityRepository::getServiceConnectionClass, Function.identity())); + if (connTypeRepositoriesMap.isEmpty()) { throw new SecretsManagerUpdateException("Unexpected error: ServiceRepository not found."); } - return connectionTypeRepositoriesMap; + return connTypeRepositoriesMap; } private Optional> retrieveServiceRepository(CollectionDetails collectionDetails) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/secrets/SecretsUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/secrets/SecretsUtil.java index 17920ca0258e..7c47a1b26d81 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/secrets/SecretsUtil.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/secrets/SecretsUtil.java @@ -16,7 +16,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class SecretsUtil { +public final class SecretsUtil { + + private SecretsUtil() { + /* Final Class */ + } /** * Returns an error message when it is related to an Unrecognized field diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/secrets/converter/ClassConverter.java b/openmetadata-service/src/main/java/org/openmetadata/service/secrets/converter/ClassConverter.java index 5a80a8d90bb7..9f8210661892 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/secrets/converter/ClassConverter.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/secrets/converter/ClassConverter.java @@ -29,7 +29,7 @@ public abstract class ClassConverter { protected final Class clazz; - public ClassConverter(Class clazz) { + protected ClassConverter(Class clazz) { this.clazz = clazz; } @@ -51,7 +51,7 @@ protected Optional tryToConvertOrFail(Object object, List> cand if (object != null) { Object converted = candidateClasses.stream() - .map(clazz -> convert(object, clazz)) + .map(candidateClazz -> convert(object, candidateClazz)) .filter(Objects::nonNull) .findFirst() .orElseThrow( @@ -69,7 +69,10 @@ protected Optional tryToConvertOrFail(Object object, List> cand protected Optional tryToConvert(Object object, List> candidateClasses) { if (object != null) { Optional converted = - candidateClasses.stream().map(clazz -> convert(object, clazz)).filter(Objects::nonNull).findFirst(); + candidateClasses.stream() + .map(candidateClazz -> convert(object, candidateClazz)) + .filter(Objects::nonNull) + .findFirst(); if (converted.isPresent()) { return Optional.of(ClassConverterFactory.getConverter(converted.get().getClass()).convert(converted.get())); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/secrets/converter/ClassConverterFactory.java b/openmetadata-service/src/main/java/org/openmetadata/service/secrets/converter/ClassConverterFactory.java index c4468f447380..08eb44a43a8b 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/secrets/converter/ClassConverterFactory.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/secrets/converter/ClassConverterFactory.java @@ -13,8 +13,6 @@ package org.openmetadata.service.secrets.converter; -import java.util.Collections; -import java.util.HashMap; import java.util.Map; import lombok.Getter; import org.openmetadata.schema.auth.SSOAuthMechanism; @@ -33,31 +31,30 @@ import org.openmetadata.schema.services.connections.storage.GcsConnection; /** Factory class to get a `ClassConverter` based on the service class. */ -public class ClassConverterFactory { +public final class ClassConverterFactory { + private ClassConverterFactory() { + /* Final Class */ + } @Getter private static final Map, ClassConverter> converterMap; static { converterMap = - Collections.unmodifiableMap( - new HashMap<>() { - { - put(AirflowConnection.class, new AirflowConnectionClassConverter()); - put(BigQueryConnection.class, new BigQueryConnectionClassConverter()); - put(DatalakeConnection.class, new DatalakeConnectionClassConverter()); - put(DbtGCSConfig.class, new DbtGCSConfigClassConverter()); - put(DbtPipeline.class, new DbtPipelineClassConverter()); - put(GCSConfig.class, new GCSConfigClassConverter()); - put(GCSCredentials.class, new GcsCredentialsClassConverter()); - put(GcsConnection.class, new GcsConnectionClassConverter()); - put(OpenMetadataConnection.class, new OpenMetadataConnectionClassConverter()); - put(SSOAuthMechanism.class, new SSOAuthMechanismClassConverter()); - put(SupersetConnection.class, new SupersetConnectionClassConverter()); - put(TableauConnection.class, new TableauConnectionClassConverter()); - put(TestServiceConnectionRequest.class, new TestServiceConnectionRequestClassConverter()); - put(Workflow.class, new WorkflowClassConverter()); - } - }); + Map.ofEntries( + Map.entry(AirflowConnection.class, new AirflowConnectionClassConverter()), + Map.entry(BigQueryConnection.class, new BigQueryConnectionClassConverter()), + Map.entry(DatalakeConnection.class, new DatalakeConnectionClassConverter()), + Map.entry(DbtGCSConfig.class, new DbtGCSConfigClassConverter()), + Map.entry(DbtPipeline.class, new DbtPipelineClassConverter()), + Map.entry(GCSConfig.class, new GCSConfigClassConverter()), + Map.entry(GCSCredentials.class, new GcsCredentialsClassConverter()), + Map.entry(GcsConnection.class, new GcsConnectionClassConverter()), + Map.entry(OpenMetadataConnection.class, new OpenMetadataConnectionClassConverter()), + Map.entry(SSOAuthMechanism.class, new SSOAuthMechanismClassConverter()), + Map.entry(SupersetConnection.class, new SupersetConnectionClassConverter()), + Map.entry(TableauConnection.class, new TableauConnectionClassConverter()), + Map.entry(TestServiceConnectionRequest.class, new TestServiceConnectionRequestClassConverter()), + Map.entry(Workflow.class, new WorkflowClassConverter())); } public static ClassConverter getConverter(Class clazz) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/AuthenticationException.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/AuthenticationException.java index 2d8c3fca609f..50c077ef0d23 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/AuthenticationException.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/AuthenticationException.java @@ -38,6 +38,16 @@ public AuthenticationException(String msg, Throwable cause) { .build(); } + public static AuthenticationException getTokenNotPresentException() { + String msg = "Not Authorized! Token not present"; + return new AuthenticationException(msg); + } + + public static AuthenticationException getInvalidTokenException() { + String msg = "Not Authorized! Invalid Token"; + return new AuthenticationException(msg); + } + private static ErrorResponse convertToErrorResponseMessage(String msg) { return new ErrorResponse(msg); } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/CatalogOpenIdAuthorizationRequestFilter.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/CatalogOpenIdAuthorizationRequestFilter.java index ee0ded51ea7a..95c4c497c8a0 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/CatalogOpenIdAuthorizationRequestFilter.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/CatalogOpenIdAuthorizationRequestFilter.java @@ -34,7 +34,9 @@ public class CatalogOpenIdAuthorizationRequestFilter implements ContainerRequest @SuppressWarnings("unused") private CatalogOpenIdAuthorizationRequestFilter() {} - public CatalogOpenIdAuthorizationRequestFilter(AuthenticationConfiguration config, AuthorizerConfiguration conf) {} + public CatalogOpenIdAuthorizationRequestFilter(AuthenticationConfiguration config, AuthorizerConfiguration conf) { + /* Used in test */ + } public void filter(ContainerRequestContext containerRequestContext) { if (isHealthEndpoint(containerRequestContext)) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/JwtFilter.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/JwtFilter.java index 9b9992b41ab4..fda189762c53 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/JwtFilter.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/JwtFilter.java @@ -216,39 +216,39 @@ protected static String extractToken(MultivaluedMap headers) { LOG.debug("Request Headers:{}", headers); String source = headers.getFirst(AUTHORIZATION_HEADER); if (nullOrEmpty(source)) { - throw new AuthenticationException("Not Authorized! Token not present"); + throw AuthenticationException.getTokenNotPresentException(); } // Extract the bearer token if (source.startsWith(TOKEN_PREFIX)) { return source.substring(TOKEN_PREFIX.length() + 1); } - throw new AuthenticationException("Not Authorized! Token not present"); + throw AuthenticationException.getTokenNotPresentException(); } public static String extractToken(String tokenFromHeader) { LOG.debug("Request Token:{}", tokenFromHeader); if (nullOrEmpty(tokenFromHeader)) { - throw new AuthenticationException("Not Authorized! Token not present"); + throw AuthenticationException.getTokenNotPresentException(); } // Extract the bearer token if (tokenFromHeader.startsWith(TOKEN_PREFIX)) { return tokenFromHeader.substring(TOKEN_PREFIX.length() + 1); } - throw new AuthenticationException("Not Authorized! Token not present"); + throw AuthenticationException.getTokenNotPresentException(); } private void validateBotToken(String tokenFromHeader, String userName) { if (tokenFromHeader.equals(BotTokenCache.getInstance().getToken(userName))) { return; } - throw new AuthenticationException("Not Authorized! Invalid Token"); + throw AuthenticationException.getInvalidTokenException(); } private void validatePersonalAccessToken(String tokenFromHeader, String userName) { if (UserTokenCache.getInstance().getToken(userName).contains(tokenFromHeader)) { return; } - throw new AuthenticationException("Not Authorized! Invalid Token"); + throw AuthenticationException.getInvalidTokenException(); } private void validateTokenIsNotUsedAfterLogout(String authToken) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/BasicAuthenticator.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/BasicAuthenticator.java index c761e380792c..02e9547f4050 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/BasicAuthenticator.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/BasicAuthenticator.java @@ -215,7 +215,7 @@ public void resetUserPasswordWithToken(UriInfo uriInfo, PasswordResetRequest req uriInfo, request.getUsername(), new EntityUtil.Fields(fields, String.join(",", fields))); // token validity if (!passwordResetToken.getUserId().equals(storedUser.getId())) { - throw new RuntimeException("Token does not belong to the user."); + throw new CustomExceptionMessage(BAD_REQUEST, "Token does not belong to the user."); } verifyPasswordResetTokenExpiry(passwordResetToken); // passwords validity @@ -292,6 +292,7 @@ public void changeUserPwdWithOldPwd(UriInfo uriInfo, String userName, ChangePass } } + @Override public void sendInviteMailToUser( UriInfo uriInfo, User user, String subject, CreateUser.CreatePasswordType requestType, String pwd) throws IOException { @@ -378,7 +379,8 @@ public RefreshToken validateAndReturnNewRefresh(UUID currentUserId, TokenRefresh String requestRefreshToken = tokenRefreshRequest.getRefreshToken(); RefreshToken storedRefreshToken = (RefreshToken) tokenRepository.findByToken(requestRefreshToken); if (storedRefreshToken.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) { - throw new RuntimeException("Expired token. Please login again : " + storedRefreshToken.getToken().toString()); + throw new CustomExceptionMessage( + BAD_REQUEST, "Expired token. Please login again : " + storedRefreshToken.getToken().toString()); } // TODO: currently allow single login from a place, later multiple login can be added // just delete the existing token @@ -414,7 +416,7 @@ private User getUserFromRegistrationRequest(RegistrationRequest create) { public void validateEmailAlreadyExists(String email) { if (userRepository.checkEmailAlreadyExists(email)) { - throw new RuntimeException("User with Email Already Exists"); + throw new CustomExceptionMessage(BAD_REQUEST, "User with Email Already Exists"); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/CatalogSecurityContextRequestFilter.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/CatalogSecurityContextRequestFilter.java index 5adf4bfd681d..ee1ab0087b12 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/CatalogSecurityContextRequestFilter.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/CatalogSecurityContextRequestFilter.java @@ -33,7 +33,9 @@ public class CatalogSecurityContextRequestFilter implements ContainerRequestFilt @SuppressWarnings("unused") private CatalogSecurityContextRequestFilter() {} - public CatalogSecurityContextRequestFilter(AuthenticationConfiguration authenticationConfiguration) {} + public CatalogSecurityContextRequestFilter(AuthenticationConfiguration authenticationConfiguration) { + /* used for testing */ + } @Override public void filter(ContainerRequestContext requestContext) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/LdapAuthenticator.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/LdapAuthenticator.java index 82684cd28ba4..6761cec107af 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/LdapAuthenticator.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/LdapAuthenticator.java @@ -50,6 +50,7 @@ @Slf4j public class LdapAuthenticator implements AuthenticatorHandler { + static final String LDAP_ERR_MSG = "[LDAP] Issue in creating a LookUp Connection SSL"; private UserRepository userRepository; private TokenRepository tokenRepository; private LoginAttemptCache loginAttemptCache; @@ -90,8 +91,8 @@ private LDAPConnectionPool getLdapConnectionPool(LdapConfiguration ldapConfigura // Use the connection here. return new LDAPConnectionPool(connection, ldapConfiguration.getMaxPoolSize()); } catch (GeneralSecurityException e) { - LOG.error("[LDAP] Issue in creating a LookUp Connection SSL", e); - throw new IllegalStateException("[LDAP] Issue in creating a LookUp Connection SSL", e); + LOG.error(LDAP_ERR_MSG, e); + throw new IllegalStateException(LDAP_ERR_MSG, e); } } else { try (LDAPConnection conn = @@ -107,7 +108,7 @@ private LDAPConnectionPool getLdapConnectionPool(LdapConfiguration ldapConfigura } } } catch (LDAPException e) { - throw new IllegalStateException("[LDAP] Issue in creating a LookUp Connection SSL", e); + throw new IllegalStateException(LDAP_ERR_MSG, e); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/NoopAuthenticator.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/NoopAuthenticator.java index 34d0b0ba2e81..f772e8e07375 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/NoopAuthenticator.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/NoopAuthenticator.java @@ -12,7 +12,9 @@ public class NoopAuthenticator implements AuthenticatorHandler { @Override - public void init(OpenMetadataApplicationConfig config, Jdbi jdbi) {} + public void init(OpenMetadataApplicationConfig config, Jdbi jdbi) { + /* deprecated unused */ + } @Override public JwtResponse loginUser(LoginRequest loginRequest) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/UserTokenCache.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/UserTokenCache.java index 1e86bd0b351f..ae50bf8b6682 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/UserTokenCache.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/auth/UserTokenCache.java @@ -51,6 +51,7 @@ public HashSet getToken(String userName) { try { return USER_TOKEN_CACHE.get(userName); } catch (ExecutionException | UncheckedExecutionException ex) { + LOG.error("Token not found", ex); return null; } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/CompiledRule.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/CompiledRule.java index 01e5dcb45676..5fd336372fba 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/CompiledRule.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/CompiledRule.java @@ -202,13 +202,13 @@ private boolean matchOperation(MetadataOperation operation) { private boolean matchExpression( PolicyContext policyContext, SubjectContext subjectContext, ResourceContextInterface resourceContext) { - Expression expression = getExpression(); - if (expression == null) { + Expression expr = getExpression(); + if (expr == null) { return true; } RuleEvaluator ruleEvaluator = new RuleEvaluator(policyContext, subjectContext, resourceContext); StandardEvaluationContext evaluationContext = new StandardEvaluationContext(ruleEvaluator); - return Boolean.TRUE.equals(expression.getValue(evaluationContext, Boolean.class)); + return Boolean.TRUE.equals(expr.getValue(evaluationContext, Boolean.class)); } public static boolean overrideAccess(Access newAccess, Access currentAccess) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/saml/OMMicrometerHttpFilter.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/saml/OMMicrometerHttpFilter.java index 8e44662d6915..408a4b9a3e54 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/saml/OMMicrometerHttpFilter.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/saml/OMMicrometerHttpFilter.java @@ -26,21 +26,27 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import org.openmetadata.common.utils.CommonUtil; /** * This is OMMicrometerHttpFilter is similar to MicrometerHttpFilter with support to handle OM Servlets, and provide * metric information for them. */ +@Slf4j public class OMMicrometerHttpFilter implements Filter { protected FilterConfig filterConfig; - public OMMicrometerHttpFilter() {} + public OMMicrometerHttpFilter() { + /* default */ + } + @Override public void init(FilterConfig filterConfig) { this.filterConfig = filterConfig; } + @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { Timer.Sample timer = Timer.start(prometheusMeterRegistry); @@ -57,5 +63,8 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha timer.stop(webAnalyticEvents); } - public void destroy() {} + @Override + public void destroy() { + LOG.info("OMMicrometerHttpFilter destroyed."); + } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/socket/FeedServlet.java b/openmetadata-service/src/main/java/org/openmetadata/service/socket/FeedServlet.java index a4c002f13b2f..05d556c44155 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/socket/FeedServlet.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/socket/FeedServlet.java @@ -24,8 +24,6 @@ @Slf4j @WebServlet("/api/v1/push/feed/*") public class FeedServlet extends HttpServlet { - public FeedServlet() {} - @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException { try { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/AuthenticationMechanismBuilder.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/AuthenticationMechanismBuilder.java index f6bc9297a4dc..d09148ff0947 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/AuthenticationMechanismBuilder.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/AuthenticationMechanismBuilder.java @@ -21,7 +21,10 @@ import org.openmetadata.schema.entity.teams.AuthenticationMechanism; import org.openmetadata.service.secrets.converter.ClassConverterFactory; -public class AuthenticationMechanismBuilder { +public final class AuthenticationMechanismBuilder { + private AuthenticationMechanismBuilder() { + // Final Class + } /** Build `AuthenticationMechanism` object with concrete class for the config which by definition it is a `Object`. */ public static AuthenticationMechanism addDefinedConfig(AuthenticationMechanism authMechanism) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/ElasticSearchClientUtils.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/ElasticSearchClientUtils.java index 929a36272d48..bf8150a973af 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/ElasticSearchClientUtils.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/ElasticSearchClientUtils.java @@ -22,6 +22,7 @@ import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.impl.client.BasicCredentialsProvider; +import org.elasticsearch.ElasticsearchException; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; @@ -57,7 +58,7 @@ public static RestHighLevelClient createElasticSearchClient(ElasticSearchConfigu .setSocketTimeout(esConfig.getSocketTimeoutSecs() * 1000)); return new RestHighLevelClient(restClientBuilder); } catch (Exception e) { - throw new RuntimeException("Failed to create elastic search client ", e); + throw new ElasticsearchException("Failed to create elastic search client ", e); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/IngestionPipelineBuilder.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/IngestionPipelineBuilder.java index ef9780f3d43a..4861ac4066aa 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/IngestionPipelineBuilder.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/IngestionPipelineBuilder.java @@ -20,7 +20,11 @@ import org.openmetadata.schema.services.connections.metadata.OpenMetadataConnection; import org.openmetadata.service.secrets.converter.ClassConverterFactory; -public class IngestionPipelineBuilder { +public final class IngestionPipelineBuilder { + + private IngestionPipelineBuilder() { + // Final + } /** Build `IngestionPipeline` object with concrete class for the config which by definition it is a `Object`. */ public static IngestionPipeline addDefinedConfig(IngestionPipeline ingestionPipeline) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/IngestionPipelineUtils.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/IngestionPipelineUtils.java index 8c19076ad82f..6075adbbbfc9 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/IngestionPipelineUtils.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/IngestionPipelineUtils.java @@ -15,7 +15,11 @@ import org.openmetadata.schema.entity.services.ingestionPipelines.AirflowConfig; -public class IngestionPipelineUtils { +public final class IngestionPipelineUtils { + private IngestionPipelineUtils() { + // Final + } + public static AirflowConfig getDefaultAirflowConfig() { return new AirflowConfig() .withPausePipeline(false) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/util/NotificationHandler.java b/openmetadata-service/src/main/java/org/openmetadata/service/util/NotificationHandler.java index 0fa02d566393..5ec49b1e7cef 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/util/NotificationHandler.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/util/NotificationHandler.java @@ -100,7 +100,7 @@ private void handleTaskNotification(Thread thread) throws JsonProcessingExceptio // fetch all that are there in the team List records = dao.relationshipDAO().findTo(e.getId().toString(), TEAM, Relationship.HAS.ordinal(), Entity.USER); - records.forEach((eRecord) -> receiversList.add(eRecord.getId())); + records.forEach(eRecord -> receiversList.add(eRecord.getId())); } }); @@ -155,7 +155,7 @@ private void handleEmailNotifications(HashSet userList, Thread thread) { UserRepository repository = (UserRepository) Entity.getEntityRepository(USER); URI urlInstance = thread.getHref(); userList.forEach( - (id) -> { + id -> { try { User user = repository.get(null, id, repository.getFields("name,email,href")); EmailUtil.getInstance()