diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 3212a6f387e..3f6911b42cb 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -195,6 +195,8 @@ Bug Fixes * SOLR-11459: In-place update of nonexistent doc following existing doc update fails to create the doc. (Andrey Kudryavtsev via Mikhail Khludnev) +* SOLR-11931: Fix contrib/ltr custom inner class feature/normaliser/model persistence. (Christine Poerschke) + Optimizations ---------------------- diff --git a/solr/contrib/ltr/src/java/org/apache/solr/ltr/store/rest/ManagedFeatureStore.java b/solr/contrib/ltr/src/java/org/apache/solr/ltr/store/rest/ManagedFeatureStore.java index 6b415a66393..9ef36b876de 100644 --- a/solr/contrib/ltr/src/java/org/apache/solr/ltr/store/rest/ManagedFeatureStore.java +++ b/solr/contrib/ltr/src/java/org/apache/solr/ltr/store/rest/ManagedFeatureStore.java @@ -192,7 +192,7 @@ public class ManagedFeatureStore extends ManagedResource implements ManagedResou private static LinkedHashMap toFeatureMap(Feature feat) { final LinkedHashMap o = new LinkedHashMap<>(4, 1.0f); // 1 extra for caller to add store o.put(NAME_KEY, feat.getName()); - o.put(CLASS_KEY, feat.getClass().getCanonicalName()); + o.put(CLASS_KEY, feat.getClass().getName()); o.put(PARAMS_KEY, feat.paramsToMap()); return o; } diff --git a/solr/contrib/ltr/src/java/org/apache/solr/ltr/store/rest/ManagedModelStore.java b/solr/contrib/ltr/src/java/org/apache/solr/ltr/store/rest/ManagedModelStore.java index 342a14067c6..bdc4cfd9df2 100644 --- a/solr/contrib/ltr/src/java/org/apache/solr/ltr/store/rest/ManagedModelStore.java +++ b/solr/contrib/ltr/src/java/org/apache/solr/ltr/store/rest/ManagedModelStore.java @@ -268,7 +268,7 @@ public class ManagedModelStore extends ManagedResource implements ManagedResourc final LinkedHashMap modelMap = new LinkedHashMap<>(5, 1.0f); modelMap.put(NAME_KEY, model.getName()); - modelMap.put(CLASS_KEY, model.getClass().getCanonicalName()); + modelMap.put(CLASS_KEY, model.getClass().getName()); modelMap.put(STORE_KEY, model.getFeatureStoreName()); final List> features = new ArrayList<>(); @@ -321,7 +321,7 @@ public class ManagedModelStore extends ManagedResource implements ManagedResourc private static LinkedHashMap toNormalizerMap(Normalizer norm) { final LinkedHashMap normalizer = new LinkedHashMap<>(2, 1.0f); - normalizer.put(CLASS_KEY, norm.getClass().getCanonicalName()); + normalizer.put(CLASS_KEY, norm.getClass().getName()); final LinkedHashMap params = norm.paramsToMap(); if (params != null) { diff --git a/solr/contrib/ltr/src/test/org/apache/solr/ltr/store/rest/TestModelManagerPersistence.java b/solr/contrib/ltr/src/test/org/apache/solr/ltr/store/rest/TestModelManagerPersistence.java index a056cf7e340..16a202f99d7 100644 --- a/solr/contrib/ltr/src/test/org/apache/solr/ltr/store/rest/TestModelManagerPersistence.java +++ b/solr/contrib/ltr/src/test/org/apache/solr/ltr/store/rest/TestModelManagerPersistence.java @@ -22,14 +22,17 @@ import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.apache.commons.io.FileUtils; import org.apache.solr.ltr.TestRerankBase; +import org.apache.solr.ltr.feature.Feature; import org.apache.solr.ltr.feature.FieldValueFeature; import org.apache.solr.ltr.feature.ValueFeature; import org.apache.solr.ltr.model.DefaultWrapperModel; import org.apache.solr.ltr.model.LinearModel; +import org.apache.solr.ltr.norm.Normalizer; import org.apache.solr.ltr.store.FeatureStore; import org.junit.BeforeClass; import org.junit.Test; @@ -261,4 +264,67 @@ public class TestModelManagerPersistence extends TestRerankBase { // NOTE: we don't test the persistence of the deletion here because it's tested in testFilePersistence } + + public static class DummyCustomFeature extends ValueFeature { + public DummyCustomFeature(String name, Map params) { + super(name, params); + } + } + + public static class DummyCustomModel extends LinearModel { + public DummyCustomModel(String name, List features, List norms, String featureStoreName, + List allFeatures, Map params) { + super(name, features, norms, featureStoreName, allFeatures, params); + } + } + + @Test + public void testInnerCustomClassesPersistence() throws Exception { + + final String featureStoreName = "test42"; + + final String featureName = "feature42"; + final String featureClassName; + if (random().nextBoolean()) { + featureClassName = ValueFeature.class.getName(); + } else { + featureClassName = DummyCustomFeature.class.getName(); + } + + loadFeature(featureName, featureClassName, "test42", + "{\"value\":"+random().nextInt(100)+"}"); + assertJQ(ManagedFeatureStore.REST_END_POINT + "/"+featureStoreName, + "/features/[0]/name=='"+featureName+"'"); + + final String modelName = "model42"; + final String modelClassName; + if (random().nextBoolean()) { + modelClassName = LinearModel.class.getName(); + } else { + modelClassName = DummyCustomModel.class.getName(); + } + + loadModel(modelName, modelClassName, + new String[] { featureName }, featureStoreName, + "{\"weights\":{\""+featureName+"\":1.0}}"); + assertJQ(ManagedModelStore.REST_END_POINT, + "/models/[0]/name=='"+modelName+"'"); + + restTestHarness.reload(); + assertJQ(ManagedFeatureStore.REST_END_POINT + "/"+featureStoreName, + "/features/[0]/name=='"+featureName+"'"); + assertJQ(ManagedModelStore.REST_END_POINT, + "/models/[0]/name=='"+modelName+"'"); + + assertJDelete(ManagedModelStore.REST_END_POINT + "/"+modelName, + "/responseHeader/status==0"); + assertJQ(ManagedModelStore.REST_END_POINT, + "/models/==[]"); + + assertJDelete(ManagedFeatureStore.REST_END_POINT + "/"+featureStoreName, + "/responseHeader/status==0"); + assertJQ(ManagedFeatureStore.REST_END_POINT + "/"+featureStoreName, + "/features/==[]"); + } + }