diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java index 2c786b16f9..2956bec77e 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java @@ -1300,7 +1300,8 @@ public class GmsGraphQLEngine { "createApplication", new CreateApplicationResolver(this.applicationService, this.entityService)) .dataFetcher( - "deleteApplication", new DeleteApplicationResolver(this.applicationService)) + "deleteApplication", + new DeleteApplicationResolver(this.entityClient, this.applicationService)) .dataFetcher( "batchSetApplication", new BatchSetApplicationResolver(this.applicationService)) .dataFetcher( diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/application/DeleteApplicationResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/application/DeleteApplicationResolver.java index d608e2f351..20f3d2d65b 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/application/DeleteApplicationResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/application/DeleteApplicationResolver.java @@ -11,6 +11,7 @@ import com.linkedin.datahub.graphql.QueryContext; import com.linkedin.datahub.graphql.authorization.AuthorizationUtils; import com.linkedin.datahub.graphql.concurrency.GraphQLConcurrencyUtils; import com.linkedin.datahub.graphql.exception.AuthorizationException; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.authorization.PoliciesConfig; import com.linkedin.metadata.service.ApplicationService; import graphql.schema.DataFetcher; @@ -23,6 +24,7 @@ import lombok.extern.slf4j.Slf4j; @RequiredArgsConstructor public class DeleteApplicationResolver implements DataFetcher> { + private final EntityClient entityClient; private final ApplicationService applicationService; private static final ConjunctivePrivilegeGroup ALL_PRIVILEGES_GROUP = @@ -52,6 +54,19 @@ public class DeleteApplicationResolver implements DataFetcher { + try { + this.entityClient.deleteEntityReferences( + context.getOperationContext(), applicationUrn); + } catch (Exception e) { + log.error( + String.format( + "Caught exception while attempting to clear all entity references for Application with urn %s", + applicationUrn), + e); + } + }); return true; } catch (Exception e) { throw new RuntimeException("Failed to delete Application", e); diff --git a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/application/DeleteApplicationResolverTest.java b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/application/DeleteApplicationResolverTest.java index cea65788c1..256bfb8e76 100644 --- a/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/application/DeleteApplicationResolverTest.java +++ b/datahub-graphql-core/src/test/java/com/linkedin/datahub/graphql/resolvers/application/DeleteApplicationResolverTest.java @@ -8,6 +8,7 @@ import static org.testng.Assert.*; import com.linkedin.common.urn.Urn; import com.linkedin.common.urn.UrnUtils; import com.linkedin.datahub.graphql.QueryContext; +import com.linkedin.entity.client.EntityClient; import com.linkedin.metadata.service.ApplicationService; import graphql.schema.DataFetchingEnvironment; import java.util.concurrent.CompletionException; @@ -25,11 +26,13 @@ public class DeleteApplicationResolverTest { private DeleteApplicationResolver resolver; private QueryContext mockContext; private DataFetchingEnvironment mockEnv; + private EntityClient mockEntityClient; @BeforeMethod public void setupTest() { mockApplicationService = Mockito.mock(ApplicationService.class); - resolver = new DeleteApplicationResolver(mockApplicationService); + mockEntityClient = Mockito.mock(EntityClient.class); + resolver = new DeleteApplicationResolver(mockEntityClient, mockApplicationService); mockContext = getMockAllowContext(TEST_ACTOR_URN.toString()); mockEnv = Mockito.mock(DataFetchingEnvironment.class); Mockito.when(mockEnv.getContext()).thenReturn(mockContext); diff --git a/datahub-web-react/src/app/entityV2/application/ApplicationEntity.tsx b/datahub-web-react/src/app/entityV2/application/ApplicationEntity.tsx index 4e26a4f432..eb298e07db 100644 --- a/datahub-web-react/src/app/entityV2/application/ApplicationEntity.tsx +++ b/datahub-web-react/src/app/entityV2/application/ApplicationEntity.tsx @@ -35,6 +35,12 @@ import { Application, EntityType, SearchResult } from '@types'; const headerDropdownItems = new Set([EntityMenuItems.SHARE, EntityMenuItems.DELETE, EntityMenuItems.EDIT]); +type ApplicationWithChildren = Application & { + children?: { + total: number; + } | null; +}; + /** * Definition of the DataHub Application entity. */ @@ -181,8 +187,7 @@ export class ApplicationEntity implements Entity { globalTags={data.tags} glossaryTerms={data.glossaryTerms} domain={data.domain?.domain} - // @ts-ignore - entityCount={data?.children?.total || undefined} + entityCount={(data as ApplicationWithChildren)?.children?.total || undefined} externalUrl={data.properties?.externalUrl} headerDropdownItems={headerDropdownItems} previewType={previewType} @@ -204,8 +209,7 @@ export class ApplicationEntity implements Entity { globalTags={data.tags} glossaryTerms={data.glossaryTerms} domain={data.domain?.domain} - // @ts-ignore - entityCount={data?.children?.total || undefined} + entityCount={(data as ApplicationWithChildren)?.children?.total || undefined} externalUrl={data.properties?.externalUrl} degree={(result as any).degree} paths={(result as any).paths} @@ -221,8 +225,7 @@ export class ApplicationEntity implements Entity { getOverridePropertiesFromEntity = (data: Application) => { const name = data?.properties?.name; const externalUrl = data?.properties?.externalUrl; - // @ts-ignore - const entityCount = data?.children?.total || undefined; + const entityCount = (data as ApplicationWithChildren)?.children?.total || undefined; const parentDomains = { domains: (data?.domain && [data?.domain?.domain]) || [], count: (data?.domain && 1) || 0, diff --git a/datahub-web-react/src/graphql/application.graphql b/datahub-web-react/src/graphql/application.graphql index 374d3070b8..6b9920890d 100644 --- a/datahub-web-react/src/graphql/application.graphql +++ b/datahub-web-react/src/graphql/application.graphql @@ -92,4 +92,4 @@ mutation deleteApplication($urn: String!) { mutation batchSetApplication($input: BatchSetApplicationInput!) { batchSetApplication(input: $input) -} \ No newline at end of file +} diff --git a/datahub-web-react/src/graphql/search.graphql b/datahub-web-react/src/graphql/search.graphql index be74cb1f04..7ec633ea8e 100644 --- a/datahub-web-react/src/graphql/search.graphql +++ b/datahub-web-react/src/graphql/search.graphql @@ -1494,4 +1494,4 @@ query scrollAcrossEntities($input: ScrollAcrossEntitiesInput!) { scrollAcrossEntities(input: $input) { ...scrollResults } -} \ No newline at end of file +}