You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vk...@apache.org on 2021/10/06 20:03:21 UTC

[ignite-3] 01/02: IGNITE-15686 Fix NPE in examples

This is an automated email from the ASF dual-hosted git repository.

vkulichenko pushed a commit to branch ignite-3.0.0-alpha3
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit 2949b6d307b11213909180eba1d40582b63de865
Author: ibessonov <be...@gmail.com>
AuthorDate: Wed Oct 6 13:04:08 2021 +0200

    IGNITE-15686 Fix NPE in examples
    
    This closes #383
---
 .gitignore                                         |   1 +
 examples/pom.xml                                   |  19 ++++
 .../example/table/KeyValueBinaryViewExample.java   | 112 +++++++++++----------
 .../apache/ignite/example/table/TableExample.java  | 111 ++++++++++----------
 .../org/apache/ignite/sql/jdbc/SqlJdbcExample.java |   2 +-
 .../ignite/example/table/TableExamplesTest.java    |  65 ++++++++++++
 .../internal/configuration/tree/NamedListNode.java |  23 ++++-
 .../configuration/util/ConfigurationUtilTest.java  |   6 +-
 .../configuration/SchemaDescriptorConverter.java   |   3 +-
 9 files changed, 221 insertions(+), 121 deletions(-)

diff --git a/.gitignore b/.gitignore
index 457eacc..0ea62ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 .idea
 *.iml
 target
+work
 .DS_Store
 .flattened-pom.xml
diff --git a/examples/pom.xml b/examples/pom.xml
index f44d425..38f2c00 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -42,5 +42,24 @@
             <groupId>org.apache.ignite</groupId>
             <artifactId>ignite-client</artifactId>
         </dependency>
+
+        <!-- Test dependencies -->
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-params</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/examples/src/main/java/org/apache/ignite/example/table/KeyValueBinaryViewExample.java b/examples/src/main/java/org/apache/ignite/example/table/KeyValueBinaryViewExample.java
index 1827b9a..7ec8492 100644
--- a/examples/src/main/java/org/apache/ignite/example/table/KeyValueBinaryViewExample.java
+++ b/examples/src/main/java/org/apache/ignite/example/table/KeyValueBinaryViewExample.java
@@ -21,6 +21,9 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgnitionManager;
+import org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter;
+import org.apache.ignite.schema.SchemaBuilders;
+import org.apache.ignite.schema.definition.ColumnType;
 import org.apache.ignite.table.KeyValueView;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
@@ -43,72 +46,71 @@ import org.apache.ignite.table.Tuple;
  */
 public class KeyValueBinaryViewExample {
     public static void main(String[] args) throws Exception {
-        Ignite ignite = IgnitionManager.start(
+        try (Ignite ignite = IgnitionManager.start(
             "node-0",
-            Files.readString(Path.of("config", "ignite-config.json").toAbsolutePath()),
+            Files.readString(Path.of("config", "ignite-config.json")),
             Path.of("work")
-        );
+        )) {
 
-        //---------------------------------------------------------------------------------
-        //
-        // Creating a table. The API call below is the equivalent of the following DDL:
-        //
-        //     CREATE TABLE accounts (
-        //         accountNumber INT PRIMARY KEY,
-        //         firstName     VARCHAR,
-        //         lastName      VARCHAR,
-        //         balance       DOUBLE
-        //     )
-        //
-        //---------------------------------------------------------------------------------
+            //---------------------------------------------------------------------------------
+            //
+            // Creating a table. The API call below is the equivalent of the following DDL:
+            //
+            //     CREATE TABLE accounts (
+            //         accountNumber INT PRIMARY KEY,
+            //         firstName     VARCHAR,
+            //         lastName      VARCHAR,
+            //         balance       DOUBLE
+            //     )
+            //
+            //---------------------------------------------------------------------------------
 
-        Table accounts = ignite.tables().createTable("PUBLIC.accounts", tbl -> tbl
-            .changeName("PUBLIC.accounts")
-            .changeColumns(cols -> cols
-                .create("0", c -> c.changeName("accountNumber").changeType(t -> t.changeType("int32")).changeNullable(false))
-                .create("1", c -> c.changeName("firstName").changeType(t -> t.changeType("string")).changeNullable(true))
-                .create("2", c -> c.changeName("lastName").changeType(t -> t.changeType("string")).changeNullable(true))
-                .create("3", c -> c.changeName("balance").changeType(t -> t.changeType("double")).changeNullable(true))
-            )
-            .changeIndices(idxs -> idxs
-                .create("PK", idx -> idx
-                    .changeName("PK")
-                    .changeType("PK")
-                    .changeColumns(cols -> cols.create("0", c -> c.changeName("accountNumber").changeAsc(true)))
-                )
-            )
-        );
+            Table accounts = ignite.tables().createTable("PUBLIC.accounts", tbl ->
+                SchemaConfigurationConverter.convert(
+                    SchemaBuilders.tableBuilder("PUBLIC", "accounts")
+                        .columns(
+                            SchemaBuilders.column("accountNumber", ColumnType.INT32).asNonNull().build(),
+                            SchemaBuilders.column("firstName", ColumnType.string()).asNullable().build(),
+                            SchemaBuilders.column("lastName", ColumnType.string()).asNullable().build(),
+                            SchemaBuilders.column("balance", ColumnType.DOUBLE).asNullable().build()
+                        )
+                        .withPrimaryKey("accountNumber")
+                        .build(), tbl)
+                    .changeReplicas(1)
+                    .changePartitions(10)
+            );
 
-        KeyValueView<Tuple, Tuple> kvView = accounts.keyValueView();
+            KeyValueView<Tuple, Tuple> kvView = accounts.keyValueView();
 
-        //---------------------------------------------------------------------------------
-        //
-        // Tuple API: insert operation.
-        //
-        //---------------------------------------------------------------------------------
+            //---------------------------------------------------------------------------------
+            //
+            // Tuple API: insert operation.
+            //
+            //---------------------------------------------------------------------------------
 
-        Tuple key = Tuple.create()
-            .set("accountNumber", 123456);
+            Tuple key = Tuple.create()
+                .set("accountNumber", 123456);
 
-        Tuple value = Tuple.create()
-            .set("firstName", "Val")
-            .set("lastName", "Kulichenko")
-            .set("balance", 100.00d);
+            Tuple value = Tuple.create()
+                .set("firstName", "Val")
+                .set("lastName", "Kulichenko")
+                .set("balance", 100.00d);
 
-        kvView.put(key, value);
+            kvView.put(key, value);
 
-        //---------------------------------------------------------------------------------
-        //
-        // Tuple API: get operation.
-        //
-        //---------------------------------------------------------------------------------
+            //---------------------------------------------------------------------------------
+            //
+            // Tuple API: get operation.
+            //
+            //---------------------------------------------------------------------------------
 
-        value = accounts.recordView().get(key);
+            value = accounts.recordView().get(key);
 
-        System.out.println(
-            "Retrieved using Key-Value API\n" +
-            "    Account Number: " + key.intValue("accountNumber") + '\n' +
-            "    Owner: " + value.stringValue("firstName") + " " + value.stringValue("lastName") + '\n' +
-            "    Balance: $" + value.doubleValue("balance"));
+            System.out.println(
+                "Retrieved using Key-Value API\n" +
+                    "    Account Number: " + key.intValue("accountNumber") + '\n' +
+                    "    Owner: " + value.stringValue("firstName") + " " + value.stringValue("lastName") + '\n' +
+                    "    Balance: $" + value.doubleValue("balance"));
+        }
     }
 }
diff --git a/examples/src/main/java/org/apache/ignite/example/table/TableExample.java b/examples/src/main/java/org/apache/ignite/example/table/TableExample.java
index 5a04db2..ba2ea58 100644
--- a/examples/src/main/java/org/apache/ignite/example/table/TableExample.java
+++ b/examples/src/main/java/org/apache/ignite/example/table/TableExample.java
@@ -21,6 +21,9 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgnitionManager;
+import org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter;
+import org.apache.ignite.schema.SchemaBuilders;
+import org.apache.ignite.schema.definition.ColumnType;
 import org.apache.ignite.table.RecordView;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.table.Tuple;
@@ -43,70 +46,70 @@ import org.apache.ignite.table.Tuple;
  */
 public class TableExample {
     public static void main(String[] args) throws Exception {
-        Ignite ignite = IgnitionManager.start(
+        try (Ignite ignite = IgnitionManager.start(
             "node-0",
             Files.readString(Path.of("config", "ignite-config.json")),
-            Path.of("work")
-        );
+            Path.of("work"))
+        ) {
 
-        //---------------------------------------------------------------------------------
-        //
-        // Creating a table. The API call below is the equivalent of the following DDL:
-        //
-        //     CREATE TABLE accounts (
-        //         accountNumber INT PRIMARY KEY,
-        //         firstName     VARCHAR,
-        //         lastName      VARCHAR,
-        //         balance       DOUBLE
-        //     )
-        //
-        //---------------------------------------------------------------------------------
+            //---------------------------------------------------------------------------------
+            //
+            // Creating a table. The API call below is the equivalent of the following DDL:
+            //
+            //     CREATE TABLE accounts (
+            //         accountNumber INT PRIMARY KEY,
+            //         firstName     VARCHAR,
+            //         lastName      VARCHAR,
+            //         balance       DOUBLE
+            //     )
+            //
+            //---------------------------------------------------------------------------------
 
-        RecordView<Tuple> accounts = ignite.tables().createTable("PUBLIC.accounts", tbl -> tbl
-            .changeName("PUBLIC.accounts")
-            .changeColumns(cols -> cols
-                .create("0", c -> c.changeName("accountNumber").changeType(t -> t.changeType("int32")).changeNullable(false))
-                .create("1", c -> c.changeName("firstName").changeType(t -> t.changeType("string")).changeNullable(true))
-                .create("2", c -> c.changeName("lastName").changeType(t -> t.changeType("string")).changeNullable(true))
-                .create("3", c -> c.changeName("balance").changeType(t -> t.changeType("double")).changeNullable(true))
-            )
-            .changeIndices(idxs -> idxs
-                .create("PK", idx -> idx
-                    .changeName("PK")
-                    .changeType("PK")
-                    .changeColumns(cols -> cols.create("0", c -> c.changeName("accountNumber").changeAsc(true)))
-                )
-            )
-        ).recordView();
+            RecordView<Tuple> accounts = ignite.tables().createTable("PUBLIC.accounts", tbl ->
+                SchemaConfigurationConverter.convert(
+                    SchemaBuilders.tableBuilder("PUBLIC", "accounts")
+                        .columns(
+                            SchemaBuilders.column("accountNumber", ColumnType.INT32).asNonNull().build(),
+                            SchemaBuilders.column("firstName", ColumnType.string()).asNullable().build(),
+                            SchemaBuilders.column("lastName", ColumnType.string()).asNullable().build(),
+                            SchemaBuilders.column("balance", ColumnType.DOUBLE).asNullable().build()
+                        )
+                        .withPrimaryKey("accountNumber")
+                        .build(), tbl)
+                    .changeReplicas(1)
+                    .changePartitions(10)
+            ).recordView();
 
-        //---------------------------------------------------------------------------------
-        //
-        // Tuple API: insert operation.
-        //
-        //---------------------------------------------------------------------------------
+            //---------------------------------------------------------------------------------
+            //
+            // Tuple API: insert operation.
+            //
+            //---------------------------------------------------------------------------------
 
-        Tuple newAccountTuple = Tuple.create()
-            .set("accountNumber", 123456)
-            .set("firstName", "Val")
-            .set("lastName", "Kulichenko")
-            .set("balance", 100.00d);
+            Tuple newAccountTuple = Tuple.create()
+                .set("accountNumber", 123456)
+                .set("firstName", "Val")
+                .set("lastName", "Kulichenko")
+                .set("balance", 100.00d);
 
-        accounts.insert(newAccountTuple);
+            accounts.insert(newAccountTuple);
 
-        //---------------------------------------------------------------------------------
-        //
-        // Tuple API: get operation.
-        //
-        //---------------------------------------------------------------------------------
+            //---------------------------------------------------------------------------------
+            //
+            // Tuple API: get operation.
+            //
+            //---------------------------------------------------------------------------------
 
-        Tuple accountNumberTuple = Tuple.create().set("accountNumber", 123456);
+            Tuple accountNumberTuple = Tuple.create().set("accountNumber", 123456);
 
-        Tuple accountTuple = accounts.get(accountNumberTuple);
+            Tuple accountTuple = accounts.get(accountNumberTuple);
 
-        System.out.println(
-            "Retrieved using Tuple API\n" +
-            "    Account Number: " + accountTuple.intValue("accountNumber") + '\n' +
-            "    Owner: " + accountTuple.stringValue("firstName") + " " + accountTuple.stringValue("lastName") + '\n' +
-            "    Balance: $" + accountTuple.doubleValue("balance"));
+            System.out.println(
+                "Retrieved using Tuple API\n" +
+                    "    Account Number: " + accountTuple.intValue("accountNumber") + '\n' +
+                    "    Owner: " + accountTuple.stringValue("firstName") + " " + accountTuple.stringValue("lastName") + '\n' +
+                    "    Balance: $" + accountTuple.doubleValue("balance"));
+
+        }
     }
 }
diff --git a/examples/src/main/java/org/apache/ignite/sql/jdbc/SqlJdbcExample.java b/examples/src/main/java/org/apache/ignite/sql/jdbc/SqlJdbcExample.java
index b3b3187..ecd97e9 100644
--- a/examples/src/main/java/org/apache/ignite/sql/jdbc/SqlJdbcExample.java
+++ b/examples/src/main/java/org/apache/ignite/sql/jdbc/SqlJdbcExample.java
@@ -51,7 +51,7 @@ public class SqlJdbcExample {
     public static void main(String[] args) throws Exception {
         Ignite ignite = IgnitionManager.start(
             "node-0",
-            Files.readString(Path.of( "examples/config/ignite-config.json").toAbsolutePath()),
+            Files.readString(Path.of( "config", "ignite-config.json")),
             Path.of("work")
         );
 
diff --git a/examples/src/test/java/org/apache/ignite/example/table/TableExamplesTest.java b/examples/src/test/java/org/apache/ignite/example/table/TableExamplesTest.java
new file mode 100644
index 0000000..ba88683
--- /dev/null
+++ b/examples/src/test/java/org/apache/ignite/example/table/TableExamplesTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.ignite.example.table;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+/**
+ * These tests check that all table examples pass correctly.
+ */
+public class TableExamplesTest {
+    /** Empty argument to invoke an example. */
+    protected static final String[] EMPTY_ARGS = new String[0];
+
+    /**
+     * Runs TableExample.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testTableExample() throws Exception {
+        TableExample.main(EMPTY_ARGS);
+    }
+
+    /**
+     * Runs KeyValueBinaryViewExample.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testKeyValueBinaryViewExample() throws Exception {
+        KeyValueBinaryViewExample.main(EMPTY_ARGS);
+    }
+
+    /**
+     * Removes a previously created work directory.
+     */
+    @BeforeEach
+    @AfterEach
+    private void removeWorkDir() {
+        Path workDir = Path.of("work");
+
+        if (Files.exists(workDir))
+            IgniteUtils.deleteIfExists(workDir);
+    }
+}
diff --git a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/tree/NamedListNode.java b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/tree/NamedListNode.java
index 85453bc..2bec423 100644
--- a/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/tree/NamedListNode.java
+++ b/modules/configuration/src/main/java/org/apache/ignite/internal/configuration/tree/NamedListNode.java
@@ -30,6 +30,8 @@ import org.apache.ignite.configuration.NamedListChange;
 import org.apache.ignite.configuration.annotation.NamedConfigValue;
 import org.apache.ignite.internal.configuration.util.ConfigurationUtil;
 
+import static org.apache.ignite.internal.configuration.util.ConfigurationUtil.addDefaults;
+
 /**
  * Configuration node implementation for the collection of named {@link InnerNode}s. Unlike implementations of
  * {@link InnerNode}, this class is used for every named list in configuration.
@@ -122,7 +124,7 @@ public final class NamedListNode<N extends InnerNode> implements NamedListChange
 
         checkNewKey(key);
 
-        ElementDescriptor<N> element = new ElementDescriptor<>(valSupplier.get());
+        ElementDescriptor<N> element = newElementDescriptor();
 
         map.put(key, element);
 
@@ -143,7 +145,7 @@ public final class NamedListNode<N extends InnerNode> implements NamedListChange
 
         checkNewKey(key);
 
-        ElementDescriptor<N> element = new ElementDescriptor<>(valSupplier.get());
+        ElementDescriptor<N> element = newElementDescriptor();
 
         map.putByIndex(index, key, element);
 
@@ -165,7 +167,7 @@ public final class NamedListNode<N extends InnerNode> implements NamedListChange
 
         checkNewKey(key);
 
-        ElementDescriptor<N> element = new ElementDescriptor<>(valSupplier.get());
+        ElementDescriptor<N> element = newElementDescriptor();
 
         map.putAfter(precedingKey, key, element);
 
@@ -187,7 +189,7 @@ public final class NamedListNode<N extends InnerNode> implements NamedListChange
         ElementDescriptor<N> element = map.get(key);
 
         if (element == null) {
-            element = new ElementDescriptor<>(valSupplier.get());
+            element = newElementDescriptor();
 
             reverseIdMap.put(element.internalId, key);
         }
@@ -349,6 +351,19 @@ public final class NamedListNode<N extends InnerNode> implements NamedListChange
     }
 
     /**
+     * Creates new element instance with initialized defaults.
+     *
+     * @return New element instance with initialized defaults.
+     */
+    private NamedListNode.ElementDescriptor<N> newElementDescriptor() {
+        N newElement = valSupplier.get();
+
+        addDefaults(newElement);
+
+        return new ElementDescriptor<>(newElement);
+    }
+
+    /**
      * Descriptor for internal named list element representation. Has node itself and its internal id.
      *
      * @param <N> Type of the node.
diff --git a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/util/ConfigurationUtilTest.java b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/util/ConfigurationUtilTest.java
index 9df981b..cc7cd68 100644
--- a/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/util/ConfigurationUtilTest.java
+++ b/modules/configuration/src/test/java/org/apache/ignite/internal/configuration/util/ConfigurationUtilTest.java
@@ -208,10 +208,6 @@ public class ConfigurationUtilTest {
 
         parent.changeElements(elements -> elements.createOrUpdate("name", element -> {}));
 
-        assertNull(ConfigurationUtil.find(List.of("elements", "name", "child"), parent, true));
-
-        ((NamedElementChange)parent.elements().get("name")).changeChild(child -> {});
-
         assertNull(ConfigurationUtil.find(List.of("elements", "name", "child", "str"), parent, true));
     }
 
@@ -232,7 +228,7 @@ public class ConfigurationUtilTest {
 
         assertThrows(
             KeyNotFoundException.class,
-            () -> ConfigurationUtil.find(List.of("elements", "name", "child", "str"), parent, true)
+            () -> ConfigurationUtil.find(List.of("elements", "name", "child", "str0"), parent, true)
         );
 
         ((NamedElementChange)parent.elements().get("name")).changeChild(child -> child.changeStr("value"));
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverter.java
index 5c09ade..b343a6f 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverter.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaDescriptorConverter.java
@@ -32,7 +32,6 @@ import org.apache.ignite.internal.schema.Column;
 import org.apache.ignite.internal.schema.DecimalNativeType;
 import org.apache.ignite.internal.schema.InvalidTypeException;
 import org.apache.ignite.internal.schema.NativeType;
-import org.apache.ignite.internal.schema.NativeTypeSpec;
 import org.apache.ignite.internal.schema.NativeTypes;
 import org.apache.ignite.internal.schema.SchemaDescriptor;
 import org.apache.ignite.internal.schema.SchemaException;
@@ -163,7 +162,7 @@ public class SchemaDescriptorConverter {
      * @return Parsed object.
      */
     private static Serializable convertDefault(NativeType type, String dflt) {
-        if (dflt == null || dflt.isEmpty() && type.spec() != NativeTypeSpec.STRING)
+        if (dflt == null || dflt.isEmpty())
             return null;
 
         assert dflt instanceof String;