From 4c0ebf75c68a9393bc30f6e298becc33d0db9513 Mon Sep 17 00:00:00 2001 From: Fabio Buso Date: Tue, 26 Dec 2023 23:35:10 +0100 Subject: [PATCH] [FSTORE-1139] Get feature store requests can throw NullPointerException is the project is not properly initialized (#1646) --- .../featurestore/FeaturestoreController.java | 13 ++-- .../TestFeaturestoreController.java | 66 +++++++++++++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 hopsworks-common/src/test/io/hops/hopsworks/common/featurestore/TestFeaturestoreController.java diff --git a/hopsworks-common/src/main/java/io/hops/hopsworks/common/featurestore/FeaturestoreController.java b/hopsworks-common/src/main/java/io/hops/hopsworks/common/featurestore/FeaturestoreController.java index 80f36bf3a3..3eb31aaf48 100644 --- a/hopsworks-common/src/main/java/io/hops/hopsworks/common/featurestore/FeaturestoreController.java +++ b/hopsworks-common/src/main/java/io/hops/hopsworks/common/featurestore/FeaturestoreController.java @@ -43,7 +43,6 @@ import io.hops.hopsworks.exceptions.UserException; import io.hops.hopsworks.persistence.entity.dataset.Dataset; import io.hops.hopsworks.persistence.entity.dataset.DatasetSharedWith; -import io.hops.hopsworks.persistence.entity.dataset.DatasetType; import io.hops.hopsworks.persistence.entity.featurestore.Featurestore; import io.hops.hopsworks.persistence.entity.featurestore.storageconnector.FeaturestoreConnectorType; import io.hops.hopsworks.persistence.entity.project.Project; @@ -64,6 +63,7 @@ import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.Objects; import java.util.logging.Level; import java.util.stream.Collectors; @@ -136,7 +136,7 @@ public List getFeaturestoresForProject(Project project) throws */ public Dataset getProjectFeaturestoreDataset(Project project) throws FeaturestoreException { return project.getDatasetCollection().stream() - .filter(ds -> ds.getDsType() == DatasetType.FEATURESTORE) + .filter(ds -> ds.getFeatureStore() != null) .findFirst() .orElseThrow(() -> new FeaturestoreException(RESTCodes.FeaturestoreErrorCode.FEATURESTORE_NOT_FOUND, Level.INFO, "Could not find feature store for project: " + project.getName())); @@ -150,8 +150,8 @@ public Dataset getProjectFeaturestoreDataset(Project project) throws Featurestor public Featurestore getProjectFeaturestore(Project project) throws FeaturestoreException { Collection dsInProject = project.getDatasetCollection(); return dsInProject.stream() - .filter(ds -> ds.getDsType() == DatasetType.FEATURESTORE) .map(Dataset::getFeatureStore) + .filter(Objects::nonNull) .findFirst() .orElseThrow(() -> new FeaturestoreException(RESTCodes.FeaturestoreErrorCode.FEATURESTORE_NOT_FOUND, Level.INFO, "Could not find feature store for project: " + project.getName())); @@ -163,7 +163,7 @@ public Featurestore getProjectFeaturestore(Project project) throws FeaturestoreE * @param project the project to list featurestores for * @return a list of featurestore entities */ - private List getProjectFeaturestores(Project project) { + public List getProjectFeaturestores(Project project) { Collection dsInProject = project.getDatasetCollection(); // Add all datasets shared with the project dsInProject.addAll(project.getDatasetSharedWithCollection().stream() @@ -171,8 +171,9 @@ private List getProjectFeaturestores(Project project) { .filter(DatasetSharedWith::getAccepted) .map(DatasetSharedWith::getDataset).collect(Collectors.toList())); return dsInProject.stream() - .filter(ds -> ds.getDsType() == DatasetType.FEATURESTORE) - .map(Dataset::getFeatureStore).collect(Collectors.toList()); + .map(Dataset::getFeatureStore) + .filter(Objects::nonNull) + .collect(Collectors.toList()); } /** diff --git a/hopsworks-common/src/test/io/hops/hopsworks/common/featurestore/TestFeaturestoreController.java b/hopsworks-common/src/test/io/hops/hopsworks/common/featurestore/TestFeaturestoreController.java new file mode 100644 index 0000000000..2ab9011519 --- /dev/null +++ b/hopsworks-common/src/test/io/hops/hopsworks/common/featurestore/TestFeaturestoreController.java @@ -0,0 +1,66 @@ +/* + * This file is part of Hopsworks + * Copyright (C) 2023, Hopsworks AB. All rights reserved + * + * Hopsworks is free software: you can redistribute it and/or modify it under the terms of + * the GNU Affero General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * + * Hopsworks is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License along with this program. + * If not, see . + */ + +package io.hops.hopsworks.common.featurestore; + +import io.hops.hopsworks.persistence.entity.dataset.Dataset; +import io.hops.hopsworks.persistence.entity.dataset.DatasetType; +import io.hops.hopsworks.persistence.entity.featurestore.Featurestore; +import io.hops.hopsworks.persistence.entity.project.Project; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class TestFeaturestoreController { + + @Test + public void testGetProjectFeaturestores() { + FeaturestoreController featurestoreController = new FeaturestoreController(); + Featurestore featurestore = new Featurestore(); + featurestore.setId(1); + + Dataset fsDataset = new Dataset(); + fsDataset.setDsType(DatasetType.FEATURESTORE); + fsDataset.setFeatureStore(featurestore); + + Project project = new Project(); + project.setDatasetCollection(Arrays.asList(fsDataset)); + project.setDatasetSharedWithCollection(new ArrayList<>()); + + List projectFeaturestores = featurestoreController.getProjectFeaturestores(project); + Assert.assertEquals(featurestore.getId(), projectFeaturestores.get(0).getId()); + } + + @Test + public void testGetProjectFeaturestores_notInitialized() { + FeaturestoreController featurestoreController = new FeaturestoreController(); + + Dataset fsDataset = new Dataset(); + fsDataset.setDsType(DatasetType.FEATURESTORE); + fsDataset.setFeatureStore(null); + + Project project = new Project(); + project.setDatasetCollection(Arrays.asList(fsDataset)); + project.setDatasetSharedWithCollection(new ArrayList<>()); + + List projectFeaturestores = featurestoreController.getProjectFeaturestores(project); + Assert.assertEquals(0, projectFeaturestores.size()); + } + +}