GEODE-7208: FlatFormatSerializer should index on inherited fields (#4058)
(cherry picked from commit 4ec87419d456748a7d853e979c90ad4e301b2405)
diff --git a/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/Customer.java b/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/Customer.java
index c405f87..d213c06 100644
--- a/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/Customer.java
+++ b/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/Customer.java
@@ -18,10 +18,10 @@
import java.util.Collection;
public class Customer implements Serializable {
- private String name;
- private Collection<String> phoneNumbers;
- private Collection<Person> contacts;
- private Page[] myHomePages;
+ protected String name;
+ protected Collection<String> phoneNumbers;
+ protected Collection<Person> contacts;
+ protected Page[] myHomePages;
public Customer(String name, Collection<String> phoneNumbers, Collection<Person> contacts,
Page[] myHomePages) {
@@ -37,7 +37,8 @@
@Override
public String toString() {
- return "Customer[name=" + name + ",phoneNumbers=" + phoneNumbers + ",contacts=" + contacts
+ return this.getClass() + "[name=" + name + ",phoneNumbers=" + phoneNumbers + ",contacts="
+ + contacts
+ ",homepage=" + myHomePages + "]";
}
}
diff --git a/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/GrandSubCustomer.java b/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/GrandSubCustomer.java
new file mode 100644
index 0000000..8870385
--- /dev/null
+++ b/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/GrandSubCustomer.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.cache.lucene.test;
+
+import java.util.Collection;
+
+public class GrandSubCustomer extends SubCustomer {
+ public GrandSubCustomer(String name,
+ Collection<String> phoneNumbers,
+ Collection<Person> contacts,
+ Page[] myHomePages) {
+ super(name, phoneNumbers, contacts, myHomePages);
+ }
+}
diff --git a/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/SubCustomer.java b/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/SubCustomer.java
new file mode 100644
index 0000000..35b166a
--- /dev/null
+++ b/geode-lucene/geode-lucene-test/src/main/java/org/apache/geode/cache/lucene/test/SubCustomer.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.cache.lucene.test;
+
+import java.util.Collection;
+
+public class SubCustomer extends Customer {
+ public SubCustomer(String name,
+ Collection<String> phoneNumbers,
+ Collection<Person> contacts,
+ Page[] myHomePages) {
+ super(name, phoneNumbers, contacts, myHomePages);
+ }
+}
diff --git a/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSeralizerIntegrationTest.java b/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSeralizerIntegrationTest.java
index 8696560..cf256b8 100644
--- a/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSeralizerIntegrationTest.java
+++ b/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSeralizerIntegrationTest.java
@@ -20,6 +20,7 @@
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
@@ -44,12 +45,22 @@
@Category({LuceneTest.class})
public class NestedObjectSeralizerIntegrationTest extends LuceneIntegrationTest {
- private static int WAIT_FOR_FLUSH_TIME = 10000;
- private static final Logger logger = LogService.getLogger();
+ protected static int WAIT_FOR_FLUSH_TIME = 10000;
+ protected static final Logger logger = LogService.getLogger();
LuceneQuery<Integer, Object> query;
PageableLuceneQueryResults<Integer, Object> results;
- private Region createRegionAndIndex() {
+ protected CustomerFactory getCustomerFactory() {
+ return Customer::new;
+ }
+
+ protected static interface CustomerFactory {
+ public Customer create(String name, Collection<String> phoneNumbers,
+ Collection<Person> contacts,
+ Page[] myHomePages);
+ }
+
+ protected Region createRegionAndIndex() {
luceneService.createIndexFactory().setLuceneSerializer(new FlatFormatSerializer())
.addField("name").addField("phoneNumbers").addField("myHomePages.content")
.addField("contacts.name").addField("contacts.email", new KeywordAnalyzer())
@@ -61,7 +72,7 @@
return region;
}
- private Region createRegionAndIndexOnInvalidFields() {
+ protected Region createRegionAndIndexOnInvalidFields() {
luceneService.createIndexFactory().setLuceneSerializer(new FlatFormatSerializer())
.addField("name").addField("contacts").addField("contacts.page")
.addField("contacts.missing").addField("missing2").create(INDEX_NAME, REGION_NAME);
@@ -70,7 +81,7 @@
return region;
}
- private void feedSomeNestedObjects(Region region) throws InterruptedException {
+ protected void feedSomeNestedObjects(Region region) throws InterruptedException {
Person contact1 = new Person("Tommi Jackson", new String[] {"5036330001", "5036330002"}, 1);
Person contact2 = new Person("Tommi2 Skywalker", new String[] {"5036330003", "5036330004"}, 2);
HashSet<Person> contacts1 = new HashSet();
@@ -80,7 +91,8 @@
ArrayList<String> phoneNumbers = new ArrayList();
phoneNumbers.add("5035330001");
phoneNumbers.add("5035330002");
- Customer customer13 = new Customer("Tommy Jackson", phoneNumbers, contacts1, myHomePages1);
+ Customer customer13 =
+ getCustomerFactory().create("Tommy Jackson", phoneNumbers, contacts1, myHomePages1);
region.put("object-13", customer13);
Person contact3 = new Person("Johnni Jackson", new String[] {"5036330005", "5036330006"}, 3);
@@ -92,7 +104,9 @@
phoneNumbers.add("5035330003");
phoneNumbers.add("5035330004");
Page[] myHomePages2 = new Page[] {new Page(14), new Page(141)};
- Customer customer14 = new Customer("Johnny Jackson", phoneNumbers, contacts2, myHomePages2);
+
+ Customer customer14 =
+ getCustomerFactory().create("Johnny Jackson", phoneNumbers, contacts2, myHomePages2);
region.put("object-14", customer14);
Person contact5 = new Person("Johnni Jackson2", new String[] {"5036330009", "5036330010"}, 5);
@@ -105,7 +119,9 @@
phoneNumbers.add("5035330005");
phoneNumbers.add("5035330006");
Page[] myHomePages3 = new Page[] {new Page(15), new Page(151)};
- Customer customer15 = new Customer("Johnny Jackson2", phoneNumbers, contacts3, myHomePages3);
+
+ Customer customer15 =
+ getCustomerFactory().create("Johnny Jackson2", phoneNumbers, contacts3, myHomePages3);
region.put("object-15", customer15);
Person contact7 = new Person("Johnni Jackson21", new String[] {"5036330013", "5036330014"}, 7);
@@ -118,7 +134,9 @@
phoneNumbers.add("5035330007");
phoneNumbers.add("5035330008");
Page[] myHomePages4 = new Page[] {new Page(16), new Page(161)};
- Customer customer16 = new Customer("Johnny Jackson21", phoneNumbers, contacts4, myHomePages4);
+
+ Customer customer16 =
+ getCustomerFactory().create("Johnny Jackson21", phoneNumbers, contacts4, myHomePages4);
region.put("object-16", customer16);
region.put("key-1", "region value 1");
@@ -432,7 +450,7 @@
assertEquals(0, results.size());
}
- private void printResults(PageableLuceneQueryResults<Integer, Object> results) {
+ protected void printResults(PageableLuceneQueryResults<Integer, Object> results) {
if (results.size() > 0) {
while (results.hasNext()) {
results.next().stream().forEach(struct -> {
@@ -444,7 +462,7 @@
}
}
- private Region createRegionAndIndexForPdxObject() {
+ protected Region createRegionAndIndexForPdxObject() {
luceneService.createIndexFactory().setLuceneSerializer(new FlatFormatSerializer())
.addField("ID").addField("description").addField("status").addField("names")
.addField("position1.country").addField("position1.secId").addField("positions.secId")
@@ -454,7 +472,7 @@
return region;
}
- private void feedSomePdxObjects(Region region) throws InterruptedException {
+ protected void feedSomePdxObjects(Region region) throws InterruptedException {
SimplePortfolioPdx.resetCounter();
SimplePositionPdx.resetCounter();
for (int i = 1; i < 10; i++) {
diff --git a/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSerializerOnGrandSubclassIntegrationTest.java b/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSerializerOnGrandSubclassIntegrationTest.java
new file mode 100644
index 0000000..8c0cfb9
--- /dev/null
+++ b/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSerializerOnGrandSubclassIntegrationTest.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.cache.lucene;
+
+import org.apache.geode.cache.lucene.test.GrandSubCustomer;
+
+
+public class NestedObjectSerializerOnGrandSubclassIntegrationTest
+ extends NestedObjectSeralizerIntegrationTest {
+
+ protected CustomerFactory getCustomerFactory() {
+ return GrandSubCustomer::new;
+ }
+}
diff --git a/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSerializerOnSubclassIntegrationTest.java b/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSerializerOnSubclassIntegrationTest.java
new file mode 100644
index 0000000..af2ce5c
--- /dev/null
+++ b/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/NestedObjectSerializerOnSubclassIntegrationTest.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.cache.lucene;
+
+import org.apache.geode.cache.lucene.test.SubCustomer;
+
+public class NestedObjectSerializerOnSubclassIntegrationTest
+ extends NestedObjectSeralizerIntegrationTest {
+
+ protected CustomerFactory getCustomerFactory() {
+ return SubCustomer::new;
+ }
+
+}
diff --git a/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/ToplevelObjectSerializerOnGrandSubclassIntegrationTest.java b/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/ToplevelObjectSerializerOnGrandSubclassIntegrationTest.java
new file mode 100644
index 0000000..f0c86c3
--- /dev/null
+++ b/geode-lucene/src/integrationTest/java/org/apache/geode/cache/lucene/ToplevelObjectSerializerOnGrandSubclassIntegrationTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.cache.lucene;
+
+import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.INDEX_NAME;
+import static org.apache.geode.cache.lucene.test.LuceneTestUtilities.REGION_NAME;
+import static org.apache.geode.internal.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.logging.log4j.Logger;
+import org.junit.Test;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.lucene.test.GrandSubCustomer;
+import org.apache.geode.internal.logging.LogService;
+
+public class ToplevelObjectSerializerOnGrandSubclassIntegrationTest extends LuceneIntegrationTest {
+ protected static int WAIT_FOR_FLUSH_TIME = 10000;
+ protected static final Logger logger = LogService.getLogger();
+ LuceneQuery<Integer, Object> query;
+ PageableLuceneQueryResults<Integer, Object> results;
+
+ protected Region createRegionAndIndex() {
+ luceneService.createIndexFactory().addField("name").create(INDEX_NAME, REGION_NAME);
+
+ Region region = createRegion(REGION_NAME, RegionShortcut.PARTITION);
+ return region;
+ }
+
+ @Test
+ public void shouldIndexOnToplevelFieldUsingDefaultSerializer()
+ throws InterruptedException, LuceneQueryException {
+ Region region = createRegionAndIndex();
+ GrandSubCustomer grandSubCustomer = new GrandSubCustomer("Tommy Jackson", null, null, null);
+ region.put("key-1", grandSubCustomer);
+ luceneService.waitUntilFlushed(INDEX_NAME, REGION_NAME, WAIT_FOR_FLUSH_TIME,
+ TimeUnit.MILLISECONDS);
+
+ query = luceneService.createLuceneQueryFactory().create(INDEX_NAME, REGION_NAME, "Tommy*",
+ "name");
+ results = query.findPages();
+ assertEquals(1, results.size());
+
+ results.next().stream().forEach(struct -> {
+ assertTrue(struct.getValue() instanceof GrandSubCustomer);
+ });
+
+ }
+}
diff --git a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/FlatFormatSerializer.java b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/FlatFormatSerializer.java
index 62006db..a56b1a0 100644
--- a/geode-lucene/src/main/java/org/apache/geode/cache/lucene/FlatFormatSerializer.java
+++ b/geode-lucene/src/main/java/org/apache/geode/cache/lucene/FlatFormatSerializer.java
@@ -140,13 +140,17 @@
&& SerializerUtil.supportedPrimitiveTypes().contains(clazz)) {
return value;
}
- try {
- Field field = clazz.getDeclaredField(fieldName);
- field.setAccessible(true);
- return field.get(value);
- } catch (Exception e) {
- return null;
- }
+
+ do {
+ try {
+ Field field = clazz.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return field.get(value);
+ } catch (Exception e) {
+ clazz = clazz.getSuperclass();
+ }
+ } while (clazz != null && !clazz.equals(Object.class));
+ return null;
}
}
}
diff --git a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/FlatFormatSerializerJUnitTest.java b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/FlatFormatSerializerJUnitTest.java
index 89e7e16..a03f6c1 100644
--- a/geode-lucene/src/test/java/org/apache/geode/cache/lucene/FlatFormatSerializerJUnitTest.java
+++ b/geode-lucene/src/test/java/org/apache/geode/cache/lucene/FlatFormatSerializerJUnitTest.java
@@ -29,6 +29,7 @@
import org.apache.geode.cache.lucene.internal.repository.serializer.SerializerTestHelper;
import org.apache.geode.cache.lucene.test.Customer;
+import org.apache.geode.cache.lucene.test.GrandSubCustomer;
import org.apache.geode.cache.lucene.test.Page;
import org.apache.geode.cache.lucene.test.Person;
import org.apache.geode.test.junit.categories.LuceneTest;
@@ -87,6 +88,24 @@
}
@Test
+ public void shouldIndexOnInheritedFields() {
+ String[] fields = new String[] {"myHomePages.content"};
+
+ FlatFormatSerializer serializer = new FlatFormatSerializer();
+
+ Page[] myHomePages1 = new Page[] {new Page(131), new Page(132)};
+ GrandSubCustomer customer = new GrandSubCustomer("Tommy Jackson", null, null, myHomePages1);
+ Document doc1 = SerializerTestHelper.invokeSerializer(serializer, customer, fields);
+
+ IndexableField[] fieldsInDoc = doc1.getFields("myHomePages.content");
+ Collection<Object> results = getResultCollection(fieldsInDoc, false);
+ assertEquals(2, results.size());
+ Object value = results.iterator().next();
+ assertTrue(results.contains("Hello world no 131"));
+ assertTrue(results.contains("Hello world no 132"));
+ }
+
+ @Test
public void shouldQueryOnFieldInCollectionObject() {
String[] fields = new String[] {"contacts.name"};