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

zehnder pushed a commit to branch 
2353-nullpointer-exception-when-misconfiguring-resource-files-for-processing-element
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to 
refs/heads/2353-nullpointer-exception-when-misconfiguring-resource-files-for-processing-element
 by this push:
     new f385d3489 fix(#2353): Add exception with detailed description for 
missing resource files
f385d3489 is described below

commit f385d348905986e63d933c0a763f300e3c4bf04c
Author: Philipp Zehnder <[email protected]>
AuthorDate: Wed Dec 20 11:22:29 2023 +0100

    fix(#2353): Add exception with detailed description for missing resource 
files
---
 .../management/locales/LabelGenerator.java         | 160 ++++++++++++++-------
 .../management/locales/LabelGeneratorTest.java     | 100 +++++++++++++
 .../extensions/html/page/WelcomePageGenerator.java |   7 +-
 3 files changed, 213 insertions(+), 54 deletions(-)

diff --git 
a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/locales/LabelGenerator.java
 
b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/locales/LabelGenerator.java
index 8e47e2092..a1be4db1d 100644
--- 
a/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/locales/LabelGenerator.java
+++ 
b/streampipes-extensions-management/src/main/java/org/apache/streampipes/extensions/management/locales/LabelGenerator.java
@@ -44,9 +44,9 @@ public class LabelGenerator<T extends NamedStreamPipesEntity> 
{
 
   private static final Logger LOG = 
LoggerFactory.getLogger(LabelGenerator.class);
 
-  private static final String Delimiter = ".";
-  private static final String Title = "title";
-  private static final String Description = "description";
+  protected static final String DELIMITER = ".";
+  protected static final String TITLE = "title";
+  protected static final String DESCRIPTION = "description";
 
   private T desc;
 
@@ -56,34 +56,51 @@ public class LabelGenerator<T extends 
NamedStreamPipesEntity> {
 
   public T generateLabels() throws IOException {
     if (existsLocalesFile()) {
-      Properties props = makeProperties();
+      Properties props = laodResourceAndMakeProperties();
       desc.setName(getTitle(props, desc.getAppId()));
       desc.setDescription(getDescription(props, desc.getAppId()));
 
       if (isAdapter()) {
-        ((AdapterDescription) desc).getConfig().forEach(sp -> 
generateLabels(props, sp));
+        ((AdapterDescription) desc).getConfig()
+                                   .forEach(sp -> generateLabels(props, sp));
       }
 
       if (isConsumable()) {
-        ((ConsumableStreamPipesEntity) desc).getStaticProperties().forEach(sp 
-> {
-          generateLabels(props, sp);
-        });
+        ((ConsumableStreamPipesEntity) desc).getStaticProperties()
+                                            .forEach(sp -> {
+                                              generateLabels(props, sp);
+                                            });
       }
 
       if (isDataProcessor()) {
-        ((DataProcessorDescription) desc).getOutputStrategies().forEach(os -> {
-          if (os instanceof AppendOutputStrategy) {
-            ((AppendOutputStrategy) os).getEventProperties().forEach(ep -> {
-              ep.setLabel(getTitle(props, ep.getRuntimeId()));
-              ep.setDescription(getDescription(props, ep.getRuntimeId()));
-            });
-          } else if (os instanceof FixedOutputStrategy) {
-            ((FixedOutputStrategy) os).getEventProperties().forEach(ep -> {
-              ep.setLabel(getTitle(props, ep.getRuntimeId()));
-              ep.setDescription(getDescription(props, ep.getRuntimeId()));
-            });
-          }
-        });
+        ((DataProcessorDescription) desc).getOutputStrategies()
+                                         .forEach(os -> {
+                                           if (os instanceof 
AppendOutputStrategy) {
+                                             ((AppendOutputStrategy) 
os).getEventProperties()
+                                                                        
.forEach(ep -> {
+                                                                          
ep.setLabel(getTitle(
+                                                                              
props,
+                                                                              
ep.getRuntimeId()
+                                                                          ));
+                                                                          
ep.setDescription(getDescription(
+                                                                              
props,
+                                                                              
ep.getRuntimeId()
+                                                                          ));
+                                                                        });
+                                           } else if (os instanceof 
FixedOutputStrategy) {
+                                             ((FixedOutputStrategy) 
os).getEventProperties()
+                                                                       
.forEach(ep -> {
+                                                                         
ep.setLabel(getTitle(
+                                                                             
props,
+                                                                             
ep.getRuntimeId()
+                                                                         ));
+                                                                         
ep.setDescription(getDescription(
+                                                                             
props,
+                                                                             
ep.getRuntimeId()
+                                                                         ));
+                                                                       });
+                                           }
+                                         });
       }
     } else {
       LOG.error("Could not find assets directory to generate labels for app 
id:" + desc.getAppId());
@@ -92,31 +109,52 @@ public class LabelGenerator<T extends 
NamedStreamPipesEntity> {
     return desc;
   }
 
+
+  /**
+   * Returns the tile of the element description based on the data of the 
resource files
+   */
+  public String getElementTitle() throws IOException {
+    var props = checkIfResourceFileExistsAndMakeProperties();
+    return getTitle(props, desc.getAppId());
+  }
+
+  /**
+   * Returns the description of the element description based on the data of 
the resource files
+   */
+  public String getElementDescription() throws IOException {
+    var props = checkIfResourceFileExistsAndMakeProperties();
+    return getDescription(props, desc.getAppId());
+  }
+
+
   private StaticProperty generateLabels(Properties props, StaticProperty sp) {
     sp.setLabel(getTitle(props, sp.getInternalName(), sp.getLabel()));
     sp.setDescription(getDescription(props, sp.getInternalName(), 
sp.getDescription()));
     if (sp instanceof CollectionStaticProperty) {
 
       if (((CollectionStaticProperty) sp).getMembers() != null) {
-        ((CollectionStaticProperty) sp).getMembers().forEach(a -> {
-          generateLabels(props, a);
-        });
+        ((CollectionStaticProperty) sp).getMembers()
+                                       .forEach(a -> {
+                                         generateLabels(props, a);
+                                       });
       } else {
         ((StaticPropertyGroup) ((CollectionStaticProperty) 
sp).getStaticPropertyTemplate()).getStaticProperties()
-            .forEach(a -> {
-              generateLabels(props, a);
-            });
+                                                                               
            .forEach(a -> {
+                                                                               
              generateLabels(props, a);
+                                                                               
            });
       }
 
     } else if (sp instanceof StaticPropertyGroup) {
-      ((StaticPropertyGroup) sp).getStaticProperties().forEach(g -> {
-        g.setLabel(getTitle(props, g.getInternalName(), g.getLabel()));
-        g.setDescription(getDescription(props, g.getInternalName(), 
g.getDescription()));
-      });
+      ((StaticPropertyGroup) sp).getStaticProperties()
+                                .forEach(g -> {
+                                  g.setLabel(getTitle(props, 
g.getInternalName(), g.getLabel()));
+                                  g.setDescription(getDescription(props, 
g.getInternalName(), g.getDescription()));
+                                });
     } else if (sp instanceof StaticPropertyAlternatives) {
-      ((StaticPropertyAlternatives) sp).getAlternatives().forEach(a -> {
-        generateLabels(props, a);
-      });
+      ((StaticPropertyAlternatives) sp).getAlternatives()
+                                       .forEach(a -> {
+                                         generateLabels(props, a);
+                                       });
     } else if (sp instanceof StaticPropertyAlternative) {
       if (((StaticPropertyAlternative) sp).getStaticProperty() != null) {
         generateLabels(props, ((StaticPropertyAlternative) 
sp).getStaticProperty());
@@ -126,26 +164,37 @@ public class LabelGenerator<T extends 
NamedStreamPipesEntity> {
     return sp;
   }
 
-  private Properties makeProperties() throws IOException {
+  protected Properties checkIfResourceFileExistsAndMakeProperties() throws 
IOException {
+    throwIOExceptionIfResourceDoesNotExist();
+    return laodResourceAndMakeProperties();
+  }
+
+  private Properties laodResourceAndMakeProperties() throws IOException {
     Properties props = new Properties();
     props.load(new InputStreamReader(loadResource(), StandardCharsets.UTF_8));
 
     return props;
   }
 
-  public String getElementTitle() throws IOException {
-    Properties props = makeProperties();
-    return getTitle(props, desc.getAppId());
+  protected boolean existsLocalesFile() {
+    return this.getClass()
+               .getClassLoader()
+               .getResource(
+                   getPath()
+               ) != null;
   }
 
-  public String getElementDescription() throws IOException {
-    Properties props = makeProperties();
-    return getDescription(props, desc.getAppId());
+  private void throwIOExceptionIfResourceDoesNotExist() throws IOException {
+    if (!existsLocalesFile()) {
+      throw new IOException(
+          "Could not find assets directory to generate labels for app id: 
%s".formatted(desc.getAppId())
+      );
+    }
   }
 
-  private boolean existsLocalesFile() {
-    return this.getClass().getClassLoader().getResourceAsStream(makePath(desc,
-        this.desc.getIncludedLocales().get(0))) != null;
+  private String getPath() {
+    return makePath(desc, desc.getIncludedLocales()
+                              .get(0));
   }
 
   private boolean isConsumable() {
@@ -161,36 +210,41 @@ public class LabelGenerator<T extends 
NamedStreamPipesEntity> {
   }
 
   private InputStream loadResource() {
-    if (desc.getIncludedLocales().size() > 0) {
-      return getResourceFile(desc.getIncludedLocales().get(0));
+    if (desc.getIncludedLocales()
+            .size() > 0) {
+      return getResourceFile(desc.getIncludedLocales()
+                                 .get(0));
     } else {
-      throw new IllegalArgumentException("Could not find any language files");
+      throw new IllegalArgumentException("Could not find any language files 
for %s".formatted(desc.getAppId()));
     }
   }
 
   private String getTitle(Properties props, String id, String defaultValue) {
-    return getValue(props, Title, id, defaultValue);
+    return getValue(props, TITLE, id, defaultValue);
   }
 
   private String getTitle(Properties props, String id) {
-    return getValue(props, Title, id, "");
+    return getValue(props, TITLE, id, "");
   }
 
   private String getDescription(Properties props, String id) {
-    return getValue(props, Description, id, "");
+    return getValue(props, DESCRIPTION, id, "");
   }
 
   private String getDescription(Properties props, String id, String 
defaultValue) {
-    return getValue(props, Description, id, defaultValue);
+    return getValue(props, DESCRIPTION, id, defaultValue);
   }
 
   private String getValue(Properties props, String type, String id, String 
defaultValue) {
-    return props.getProperty(id + Delimiter + type, defaultValue);
+    return props.getProperty(id + DELIMITER + type, defaultValue);
   }
 
 
   private InputStream getResourceFile(String filename) {
-    return this.getClass().getClassLoader().getResourceAsStream(makePath(desc, 
filename));
+    var path = makePath(desc, filename);
+    return this.getClass()
+               .getClassLoader()
+               .getResourceAsStream(path);
   }
 
 }
diff --git 
a/streampipes-extensions-management/src/test/java/org/apache/streampipes/extensions/management/locales/LabelGeneratorTest.java
 
b/streampipes-extensions-management/src/test/java/org/apache/streampipes/extensions/management/locales/LabelGeneratorTest.java
new file mode 100644
index 000000000..4ca674f67
--- /dev/null
+++ 
b/streampipes-extensions-management/src/test/java/org/apache/streampipes/extensions/management/locales/LabelGeneratorTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.streampipes.extensions.management.locales;
+
+import org.apache.streampipes.model.base.NamedStreamPipesEntity;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+public class LabelGeneratorTest {
+
+  private static final String TEST_APP_ID = "test-app-id";
+
+  @Test
+  public void getElementDescriptionThrowExceptiojn() {
+    var labelGenerator = getLabelGeneratorWithoutLocalesFile();
+    assertThrows(IOException.class, labelGenerator::getElementDescription);
+  }
+
+  @Test
+  public void getElementDescriptionReturnsCorrectDescription() throws 
IOException {
+    var expectedDescription = "test-description";
+    var properties = getProperties(LabelGenerator.DESCRIPTION, 
expectedDescription);
+
+    var labelGenerator = getLabelGeneratorWithProperties(properties);
+
+    assertEquals(expectedDescription, labelGenerator.getElementDescription());
+  }
+
+  @Test
+  public void getElementTitleThrowExceptiojn() {
+    var labelGenerator = getLabelGeneratorWithoutLocalesFile();
+    assertThrows(IOException.class, labelGenerator::getElementTitle);
+  }
+
+  @Test
+  public void getElementTitleReturnsCorrectDescription() throws IOException {
+    var expectedTitle = "test-title";
+    var properties = getProperties(LabelGenerator.TITLE, expectedTitle);
+
+    var labelGenerator = getLabelGeneratorWithProperties(properties);
+
+    assertEquals(expectedTitle, labelGenerator.getElementTitle());
+  }
+
+
+  private LabelGenerator getLabelGeneratorWithoutLocalesFile() {
+    var mockDescription = Mockito.mock(NamedStreamPipesEntity.class);
+    when(mockDescription.getAppId()).thenReturn(TEST_APP_ID);
+
+    var labelGenerator = new LabelGenerator(mockDescription);
+    var mockGenerator = spy(labelGenerator);
+    doReturn(false).when(mockGenerator)
+                   .existsLocalesFile();
+    return mockGenerator;
+  }
+
+  private LabelGenerator getLabelGeneratorWithProperties(Properties 
properties) throws IOException {
+    var mockDescription = Mockito.mock(NamedStreamPipesEntity.class);
+    when(mockDescription.getAppId()).thenReturn(TEST_APP_ID);
+
+    var labelGenerator = new LabelGenerator(mockDescription);
+    var mockGenerator = spy(labelGenerator);
+    doReturn(properties).when(mockGenerator)
+                        .checkIfResourceFileExistsAndMakeProperties();
+    return mockGenerator;
+  }
+
+  private Properties getProperties(String key, String value) {
+    var result = new Properties();
+    result.setProperty(TEST_APP_ID + LabelGenerator.DELIMITER + key, value);
+
+    return result;
+  }
+}
\ No newline at end of file
diff --git 
a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/html/page/WelcomePageGenerator.java
 
b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/html/page/WelcomePageGenerator.java
index d4ff6fe38..8aa99727e 100644
--- 
a/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/html/page/WelcomePageGenerator.java
+++ 
b/streampipes-rest-extensions/src/main/java/org/apache/streampipes/rest/extensions/html/page/WelcomePageGenerator.java
@@ -32,6 +32,9 @@ import org.apache.streampipes.model.graph.DataSinkDescription;
 import org.apache.streampipes.rest.extensions.html.model.Description;
 import org.apache.streampipes.sdk.utils.Assets;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -40,6 +43,8 @@ import java.util.List;
 
 public class WelcomePageGenerator {
 
+  private static final Logger LOG = 
LoggerFactory.getLogger(WelcomePageGenerator.class);
+
   protected List<Description> descriptions;
   protected Collection<IStreamPipesPipelineElement<?>> pipelineElements;
   protected Collection<StreamPipesAdapter> adapters;
@@ -129,7 +134,7 @@ public class WelcomePageGenerator {
         desc.setName(lg.getElementTitle());
         desc.setDescription(lg.getElementDescription());
       } catch (IOException e) {
-        e.printStackTrace();
+        LOG.error("Error while updating description of 
%s".formatted(entity.getAppId()), e);
       }
     }
   }

Reply via email to