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

pdallig pushed a commit to branch branch-0.12
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/branch-0.12 by this push:
     new bd270bd857 [ZEPPELIN-6131] Update Interpreter to Store Values as 
Integers When Applicable
bd270bd857 is described below

commit bd270bd8579313fa42a03e0c021f709ccd15f446
Author: Gyeongtae Park <67095975+parkgyeong...@users.noreply.github.com>
AuthorDate: Tue Nov 12 19:09:42 2024 +0900

    [ZEPPELIN-6131] Update Interpreter to Store Values as Integers When 
Applicable
    
    ### What is this PR for?
    There was an issue where the port was treated as a string and included `.0` 
when modifying the port of the Elasticsearch interpreter.
    
    ### What type of PR is it?
    Bug Fix
    
    ### Todos
    * [x] - Modified HttpBasedClient.java file
    
    ### What is the Jira issue?
    * https://issues.apache.org/jira/projects/ZEPPELIN/issues/ZEPPELIN-6131
    
    ### How should this be tested?
    * Zeppelin project build and run
    ```bash
    ./mvnw clean package -DskipTests
    ```
    
    * Add a test index and test data to Elasticsearch
    ```bash
    # Create an index
    curl -X PUT "http://localhost:9200/customer?pretty";
    
    # Create a document
    curl -X \
    PUT "localhost:9200/customer/_doc/1" \
    -H 'Content-Type: application/json' \
    -d'
    {
      "field_1": "value_1"
    }'
    ```
    
    * Modify the Elasticsearch interpreter type and port
    elasticsearch.client.type: transport -> http
    elasticsearch.port: 9300 -> 9200
    
    * Previous configuration
    <img width="1228" alt="image" 
src="https://github.com/user-attachments/assets/aab69016-b982-4817-8d72-68186fdd45b8";>
    
    * New configuration
    <img width="1219" alt="image" 
src="https://github.com/user-attachments/assets/a9c44503-1ed1-43c0-89f9-19b92a1ac1e0";>
    
    * Create a Zeppelin notebook and execute a paragraph
    ```bash
    %elasticsearch
    get /customer/_doc/1
    ```
    
    * Result before modification - Error occurred
    <img width="942" alt="image" 
src="https://github.com/user-attachments/assets/00d5db2f-e1dd-46bf-96d9-eb2eb1d88072";>
    
    ```bash
    org.apache.zeppelin.interpreter.InterpreterException: 
java.lang.NumberFormatException: For input string: "9200.0"
            at 
org.apache.zeppelin.interpreter.LazyOpenInterpreter.open(LazyOpenInterpreter.java:77)
            at 
org.apache.zeppelin.interpreter.remote.RemoteInterpreterServer$InterpretJob.jobRun(RemoteInterpreterServer.java:808)
            at 
org.apache.zeppelin.interpreter.remote.RemoteInterpreterServer$InterpretJob.jobRun(RemoteInterpreterServer.java:716)
            at org.apache.zeppelin.scheduler.Job.run(Job.java:187)
            at 
org.apache.zeppelin.scheduler.AbstractScheduler.runJob(AbstractScheduler.java:136)
            at 
org.apache.zeppelin.scheduler.FIFOScheduler.lambda$runJobInScheduler$0(FIFOScheduler.java:42)
            at 
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
            at 
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
            at java.base/java.lang.Thread.run(Thread.java:829)
    Caused by: java.lang.NumberFormatException: For input string: "9200.0"
            at 
java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
            at java.base/java.lang.Integer.parseInt(Integer.java:652)
            at java.base/java.lang.Integer.parseInt(Integer.java:770)
            at 
org.apache.zeppelin.elasticsearch.client.HttpBasedClient.<init>(HttpBasedClient.java:67)
            at 
org.apache.zeppelin.elasticsearch.ElasticsearchInterpreter.open(ElasticsearchInterpreter.java:136)
            at 
org.apache.zeppelin.interpreter.LazyOpenInterpreter.open(LazyOpenInterpreter.java:71)
            ... 8 more
    ```
    
    * Result after modification
    <img width="500" alt="image" 
src="https://github.com/user-attachments/assets/2634216c-ed42-4a1e-8c6d-d3bb378365fa";>
    
    ### Screenshots (if appropriate)
    * Refer to the above content
    
    ### Questions:
    * Does the license files need to update? No.
    * Is there breaking changes for older versions? No.
    * Does this needs documentation? No.
    
    
    Closes #4878 from ParkGyeongTae/fix-elasticsearch-port-string-handling.
    
    Signed-off-by: Philipp Dallig <philipp.dal...@gmail.com>
---
 .../message/UpdateInterpreterSettingRequest.java   |  45 ++++++++
 .../UpdateInterpreterSettingRequestTest.java       | 115 +++++++++++++++++++++
 2 files changed, 160 insertions(+)

diff --git 
a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/UpdateInterpreterSettingRequest.java
 
b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/UpdateInterpreterSettingRequest.java
index 79cc1e19b5..ca7e76a0b9 100644
--- 
a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/UpdateInterpreterSettingRequest.java
+++ 
b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/message/UpdateInterpreterSettingRequest.java
@@ -39,10 +39,55 @@ public class UpdateInterpreterSettingRequest {
     this.option = option;
   }
 
+  /**
+   * Retrieves the properties of the interpreter and, if the property type is 
"number"
+   * and its value is a double that represents a whole number, converts that 
value to an integer.
+   *
+   * @return A map of the interpreter's properties with possible modifications 
to the numeric properties.
+   */
   public Map<String, InterpreterProperty> getProperties() {
+    properties.forEach((key, property) -> {
+      if (isNumberType(property) && isWholeNumberDouble(property.getValue())) {
+        convertDoubleToInt(property);
+      }
+    });
     return properties;
   }
 
+  /**
+   * Checks if the property type is "number".
+   *
+   * @param property The InterpreterProperty to check.
+   * @return true if the property type is "number", false otherwise.
+   */
+  private boolean isNumberType(InterpreterProperty property) {
+    return "number".equals(property.getType());
+  }
+
+  /**
+   * Checks if the given value is a Double and represents a whole number.
+   *
+   * @param value The object to check.
+   * @return true if the value is a Double and a whole number, false otherwise.
+   */
+  private boolean isWholeNumberDouble(Object value) {
+    if (value instanceof Double) {
+      Double doubleValue = (Double) value;
+      return doubleValue == Math.floor(doubleValue);
+    }
+    return false;
+  }
+
+  /**
+   * Converts the value of the given property from a Double to an Integer if 
the Double represents a whole number.
+   *
+   * @param property The InterpreterProperty whose value will be converted.
+   */
+  private void convertDoubleToInt(InterpreterProperty property) {
+    Double doubleValue = (Double) property.getValue();
+    property.setValue(doubleValue.intValue());
+  }
+
   public List<Dependency> getDependencies() {
     return dependencies;
   }
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/message/UpdateInterpreterSettingRequestTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/message/UpdateInterpreterSettingRequestTest.java
new file mode 100644
index 0000000000..1ecf555ad7
--- /dev/null
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/message/UpdateInterpreterSettingRequestTest.java
@@ -0,0 +1,115 @@
+/*
+ * 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.zeppelin.rest.message;
+
+import org.apache.zeppelin.dep.Dependency;
+import org.apache.zeppelin.interpreter.InterpreterOption;
+import org.apache.zeppelin.interpreter.InterpreterProperty;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * Unit test class for the UpdateInterpreterSettingRequest.
+ * This class tests the behavior of UpdateInterpreterSettingRequest methods,
+ * especially focusing on property type handling and value conversions.
+ */
+class UpdateInterpreterSettingRequestTest {
+
+  private Map<String, InterpreterProperty> properties;
+  private List<Dependency> dependencies;
+  private InterpreterOption option;
+  private UpdateInterpreterSettingRequest request;
+
+  /**
+   * Setup method that initializes test fixtures before each test.
+   * Mocks dependencies and option objects to isolate 
UpdateInterpreterSettingRequest behavior.
+   */
+  @BeforeEach
+  void setUp() {
+    properties = new HashMap<>();
+    dependencies = Collections.emptyList();
+    option = mock(InterpreterOption.class);
+    request = new UpdateInterpreterSettingRequest(properties, dependencies, 
option);
+  }
+
+  /**
+   * Tests getProperties method to verify that properties with "number" type
+   * and whole-number Double values are correctly converted to Integer.
+   * Verifies that only whole-number Doubles are converted and non-integer 
Doubles remain unchanged.
+   */
+  @Test
+  void testGetPropertiesWithWholeNumberDoubleConversion() {
+    InterpreterProperty property1 = mock(InterpreterProperty.class);
+    when(property1.getType()).thenReturn("number");
+    when(property1.getValue()).thenReturn(5.0);
+
+    InterpreterProperty property2 = mock(InterpreterProperty.class);
+    when(property2.getType()).thenReturn("number");
+    when(property2.getValue()).thenReturn(5.5);
+
+    properties.put("property1", property1);
+    properties.put("property2", property2);
+
+    Map<String, InterpreterProperty> resultProperties = 
request.getProperties();
+
+    verify(property1).setValue(5);
+    verify(property2, never()).setValue(any());
+    assertEquals(properties, resultProperties);
+  }
+
+  /**
+   * Tests getProperties method when the property type is not "number".
+   * Verifies that no conversion is performed on non-number types.
+   */
+  @Test
+  void testGetPropertiesWithoutConversion() {
+    InterpreterProperty property = mock(InterpreterProperty.class);
+    when(property.getType()).thenReturn("string");
+    when(property.getValue()).thenReturn("test");
+
+    properties.put("property", property);
+
+    Map<String, InterpreterProperty> resultProperties = 
request.getProperties();
+
+    verify(property, never()).setValue(any());
+    assertEquals(properties, resultProperties);
+  }
+
+  /**
+   * Tests getDependencies method to confirm that it returns the correct 
dependencies list.
+   */
+  @Test
+  void testGetDependencies() {
+    assertEquals(dependencies, request.getDependencies());
+  }
+
+  /**
+   * Tests getOption method to confirm that it returns the correct interpreter 
option.
+   */
+  @Test
+  void testGetOption() {
+    assertEquals(option, request.getOption());
+  }
+}

Reply via email to