[ 
https://issues.apache.org/jira/browse/CONFIGURATION-833?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Matthias Hanisch updated CONFIGURATION-833:
-------------------------------------------
    Description: 
With Properties files as configuration sources there not so much scenarios 
where exceptions can be raised:
 # Properties File itself cannot be found
 # Properties File is invalid, e.g. contains "invalidValue=\uZZZZ"
 # Properties File contains an "include" but the included file cannot be found

If the PropertiesConfiguration is marked as optional all errors are ignored and 
the Configuration is silently not considered.

In our case we would like to have scenarios 2 and 3 considered as serious 
errors where the whole logic should fail independent if the configuration is 
optional or not.

While looking at the code it seems that all exceptions are transformed to 
ConfigurationExceptions and then are ignored if the configuration is optional.

It would be nice to have a possibility to decide from application point of view 
the severity of the error and based on that having different logic, e.g. let 
the whole thing fail.

Here is some test code that illustrates the problem:

Test Class;

 
{code:java}
package commons.configuration.issues;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.io.File;

import org.apache.commons.configuration2.CombinedConfiguration;
import 
org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.junit.Test;

public class VariousErrorsAllIgnoredWithOptional {
        @Test
        public void nonOptionalIncludeNotFound() {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-include-not-found.xml")));
                /*
                 * Non optional leads always to an error
                 */
                System.setProperty("propertiesOptional", "false");
                assertThatThrownBy(() -> 
builder.getConfiguration()).isInstanceOf(ConfigurationException.class)
                                .hasMessage("Cannot resolve include file 
not_exist.properties");
        }

        @Test
        public void optionalIncludeNotFound() throws ConfigurationException {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-include-not-found.xml")));
                System.setProperty("propertiesOptional", "true");

                /*
                 * If optional then a non-working include is ignored. This is 
not desired.
                 * Would be nice to configure that as serious problem that 
leads to a general error independent of optional.
                 */
                assertThat(builder.getConfiguration()).isNotNull();
        }

        @Test
        public void nonOptionalPropertyNotFound() {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-property-not-found.xml")));
                /*
                 * Non optional leads always to an error
                 */
                System.setProperty("propertiesOptional", "false");
                assertThatThrownBy(() -> 
builder.getConfiguration()).isInstanceOf(ConfigurationException.class)
                                .hasMessageContainingAll("Could not locate", 
"not-exist.properties");
        }

        @Test
        public void optionalPropertyNotFound() throws ConfigurationException {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-properties-file-not-found.xml")));

                /*
                 * If optional then a non-working include is ignored. This is 
ok.
                 */
                System.setProperty("propertiesOptional", "true");
                assertThat(builder.getConfiguration()).isNotNull();
        }

        @Test
        public void nonOptionalInvalidPropertiesFile() {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-invalid-properties-file.xml")));
                /*
                 * Non optional leads always to an error
                 */
                System.setProperty("propertiesOptional", "false");
                assertThatThrownBy(() -> 
builder.getConfiguration()).isInstanceOf(ConfigurationException.class).cause().isInstanceOf(ConfigurationRuntimeException.class)
                                .hasMessage("Unable to parse unicode value: 
ZZZZ");
        }

        @Test
        public void optionalInvalidPropertiesFile() throws 
ConfigurationException {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-invalid-properties-file.xml")));

                /*
                 * If optional then an invalid property file is ignored. This 
is not desired.
                 * Would be nice to configure that as serious problem that 
leads to a general error independent of optional.
                 */
                System.setProperty("propertiesOptional", "true");
                CombinedConfiguration configuration = 
builder.getConfiguration();
                // At least all keys are consistently not set.
                
assertThat(configuration.getString("valueBeforeInvalid")).isNull();
                assertThat(configuration.getString("invalidValue")).isNull();
                
assertThat(configuration.getString("valueAfterInvalid")).isNull();
        }
}
{code}
error-handling-include-not-found.xml:
{code:java}
<configuration>
        <properties basePath="src/test/resources/commons-configuration-issues"
                fileName="error-handling-include-not-found.properties" 
config-optional="${sys:propertiesOptional}"/>
</configuration>{code}
error-handling-include-not-found.properties:
{code:java}
include = not_exist.properties
{code}
error-handling-properties-file-not-found.xml
{code:java}
<configuration>
        <properties basePath="src/test/resources/commons-configuration-issues"
                fileName="not-exist.properties" 
config-optional="${sys:propertiesOptional}"/>
</configuration>
{code}
error-handling-invalid-properties-file-not-found.xml
{code:java}
<configuration>
        <properties basePath="src/test/resources/commons-configuration-issues"
                fileName="not-exist.properties" 
config-optional="${sys:propertiesOptional}"/>
</configuration>{code}
error-handling-invalid-properties-file-not-found.properties
{code:java}
valueBeforeInvalid=1
invalidValue=\uZZZZ
valueAfterInvalid=2
{code}

  was:
With Properties files as configuration sources there not so much scenarios 
where exceptions can be raised:
 # Properties File itself cannot be found
 # Properties File is invalid, e.g. contains "invalidValue=\uZZZZ"
 # Properties File contains an "include" but the included file cannot be found

If the PropertiesConfiguration is marked as optional all errors are ignored and 
the Configuration is silently not considered.

In our case we would like to have scenarios 2 and 3 considered as serious 
errors where the whole logic should fail independent if the configuration is 
optional or not.

While looking at the code it seems that all exceptions are transformed to 
ConfigurationExceptions and then are ignored if the configuration is optional.

It would be nice to have a possibility to decide from application point of view 
the severity of the error and based on that having different logic, e.g. let 
the whole thing fail.

Here is some test code that illustrates the problem:

Test Class;

 
{code:java}
package commons.configuration.issues;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.io.File;

import org.apache.commons.configuration2.CombinedConfiguration;
import 
org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.junit.Test;

public class VariousErrorsAllIgnoredWithOptional {
        @Test
        public void nonOptionalIncludeNotFound() {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-include-not-found.xml")));
                /*
                 * Non optional leads always to an error
                 */
                System.setProperty("propertiesOptional", "false");
                assertThatThrownBy(() -> 
builder.getConfiguration()).isInstanceOf(ConfigurationException.class)
                                .hasMessage("Cannot resolve include file 
not_exist.properties");
        }

        @Test
        public void optionalIncludeNotFound() throws ConfigurationException {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-include-not-found.xml")));
                System.setProperty("propertiesOptional", "true");

                /*
                 * If optional then a non-working include is ignored. This is 
not desired.
                 * Would be nice to configure that as serious problem that 
leads to a general error independent of optional.
                 */
                assertThat(builder.getConfiguration()).isNotNull();
        }

        @Test
        public void nonOptionalPropertyNotFound() {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-property-not-found.xml")));
                /*
                 * Non optional leads always to an error
                 */
                System.setProperty("propertiesOptional", "false");
                assertThatThrownBy(() -> 
builder.getConfiguration()).isInstanceOf(ConfigurationException.class)
                                .hasMessageContainingAll("Could not locate", 
"not-exist.properties");
        }

        @Test
        public void optionalPropertyNotFound() throws ConfigurationException {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-properties-file-not-found.xml")));

                /*
                 * If optional then a non-working include is ignored. This is 
ok.
                 */
                System.setProperty("propertiesOptional", "true");
                assertThat(builder.getConfiguration()).isNotNull();
        }

        @Test
        public void nonOptionalInvalidPropertiesFile() {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-invalid-properties-file.xml")));
                /*
                 * Non optional leads always to an error
                 */
                System.setProperty("propertiesOptional", "false");
                assertThatThrownBy(() -> 
builder.getConfiguration()).isInstanceOf(ConfigurationException.class).cause().isInstanceOf(ConfigurationRuntimeException.class)
                                .hasMessage("Unable to parse unicode value: 
ZZZZ");
        }

        @Test
        public void optionalInvalidPropertiesFile() throws 
ConfigurationException {
                CombinedConfigurationBuilder builder = new 
CombinedConfigurationBuilder()
                                .configure(new 
Parameters().fileBased().setFile(new File(
                                                
"src/test/resources/commons-configuration-issues/error-handling-invalid-properties-file.xml")));

                /*
                 * If optional then an invalid property file is ignored. This 
is not desired.
                 * Would be nice to configure that as serious problem that 
leads to a general error independent of optional.
                 */
                System.setProperty("propertiesOptional", "true");
                CombinedConfiguration configuration = 
builder.getConfiguration();
                // At least all keys are consistently not set.
                
assertThat(configuration.getString("valueBeforeInvalid")).isNull();
                assertThat(configuration.getString("invalidValue")).isNull();
                
assertThat(configuration.getString("valueAfterInvalid")).isNull();
        }
}
{code}
error-handling-include-not-found.xml:
 
 
{code:java}
<configuration>
        <properties basePath="src/test/resources/commons-configuration-issues"
                fileName="error-handling-include-not-found.properties" 
config-optional="${sys:propertiesOptional}"/>
</configuration>{code}
error-handling-include-not-found.properties:

 
{code:java}
include = not_exist.properties
{code}
error-handling-properties-file-not-found.xml

 

 
{code:java}
<configuration>
        <properties basePath="src/test/resources/commons-configuration-issues"
                fileName="not-exist.properties" 
config-optional="${sys:propertiesOptional}"/>
</configuration>
{code}
error-handling-invalid-properties-file-not-found.xml

 

 
{code:java}
<configuration>
        <properties basePath="src/test/resources/commons-configuration-issues"
                fileName="not-exist.properties" 
config-optional="${sys:propertiesOptional}"/>
</configuration>{code}
error-handling-invalid-properties-file-not-found.properties
{code:java}
valueBeforeInvalid=1
invalidValue=\uZZZZ
valueAfterInvalid=2
{code}


> PropertiesConfiguration: Possibility to distinguish between "serious" and 
> "non-serious" exceptions for optional configurations
> ------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CONFIGURATION-833
>                 URL: https://issues.apache.org/jira/browse/CONFIGURATION-833
>             Project: Commons Configuration
>          Issue Type: Improvement
>            Reporter: Matthias Hanisch
>            Priority: Major
>
> With Properties files as configuration sources there not so much scenarios 
> where exceptions can be raised:
>  # Properties File itself cannot be found
>  # Properties File is invalid, e.g. contains "invalidValue=\uZZZZ"
>  # Properties File contains an "include" but the included file cannot be found
> If the PropertiesConfiguration is marked as optional all errors are ignored 
> and the Configuration is silently not considered.
> In our case we would like to have scenarios 2 and 3 considered as serious 
> errors where the whole logic should fail independent if the configuration is 
> optional or not.
> While looking at the code it seems that all exceptions are transformed to 
> ConfigurationExceptions and then are ignored if the configuration is optional.
> It would be nice to have a possibility to decide from application point of 
> view the severity of the error and based on that having different logic, e.g. 
> let the whole thing fail.
> Here is some test code that illustrates the problem:
> Test Class;
>  
> {code:java}
> package commons.configuration.issues;
> import static org.assertj.core.api.Assertions.assertThat;
> import static org.assertj.core.api.Assertions.assertThatThrownBy;
> import java.io.File;
> import org.apache.commons.configuration2.CombinedConfiguration;
> import 
> org.apache.commons.configuration2.builder.combined.CombinedConfigurationBuilder;
> import org.apache.commons.configuration2.builder.fluent.Parameters;
> import org.apache.commons.configuration2.ex.ConfigurationException;
> import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
> import org.junit.Test;
> public class VariousErrorsAllIgnoredWithOptional {
>       @Test
>       public void nonOptionalIncludeNotFound() {
>               CombinedConfigurationBuilder builder = new 
> CombinedConfigurationBuilder()
>                               .configure(new 
> Parameters().fileBased().setFile(new File(
>                                               
> "src/test/resources/commons-configuration-issues/error-handling-include-not-found.xml")));
>               /*
>                * Non optional leads always to an error
>                */
>               System.setProperty("propertiesOptional", "false");
>               assertThatThrownBy(() -> 
> builder.getConfiguration()).isInstanceOf(ConfigurationException.class)
>                               .hasMessage("Cannot resolve include file 
> not_exist.properties");
>       }
>       @Test
>       public void optionalIncludeNotFound() throws ConfigurationException {
>               CombinedConfigurationBuilder builder = new 
> CombinedConfigurationBuilder()
>                               .configure(new 
> Parameters().fileBased().setFile(new File(
>                                               
> "src/test/resources/commons-configuration-issues/error-handling-include-not-found.xml")));
>               System.setProperty("propertiesOptional", "true");
>               /*
>                * If optional then a non-working include is ignored. This is 
> not desired.
>                * Would be nice to configure that as serious problem that 
> leads to a general error independent of optional.
>                */
>               assertThat(builder.getConfiguration()).isNotNull();
>       }
>       @Test
>       public void nonOptionalPropertyNotFound() {
>               CombinedConfigurationBuilder builder = new 
> CombinedConfigurationBuilder()
>                               .configure(new 
> Parameters().fileBased().setFile(new File(
>                                               
> "src/test/resources/commons-configuration-issues/error-handling-property-not-found.xml")));
>               /*
>                * Non optional leads always to an error
>                */
>               System.setProperty("propertiesOptional", "false");
>               assertThatThrownBy(() -> 
> builder.getConfiguration()).isInstanceOf(ConfigurationException.class)
>                               .hasMessageContainingAll("Could not locate", 
> "not-exist.properties");
>       }
>       @Test
>       public void optionalPropertyNotFound() throws ConfigurationException {
>               CombinedConfigurationBuilder builder = new 
> CombinedConfigurationBuilder()
>                               .configure(new 
> Parameters().fileBased().setFile(new File(
>                                               
> "src/test/resources/commons-configuration-issues/error-handling-properties-file-not-found.xml")));
>               /*
>                * If optional then a non-working include is ignored. This is 
> ok.
>                */
>               System.setProperty("propertiesOptional", "true");
>               assertThat(builder.getConfiguration()).isNotNull();
>       }
>       @Test
>       public void nonOptionalInvalidPropertiesFile() {
>               CombinedConfigurationBuilder builder = new 
> CombinedConfigurationBuilder()
>                               .configure(new 
> Parameters().fileBased().setFile(new File(
>                                               
> "src/test/resources/commons-configuration-issues/error-handling-invalid-properties-file.xml")));
>               /*
>                * Non optional leads always to an error
>                */
>               System.setProperty("propertiesOptional", "false");
>               assertThatThrownBy(() -> 
> builder.getConfiguration()).isInstanceOf(ConfigurationException.class).cause().isInstanceOf(ConfigurationRuntimeException.class)
>                               .hasMessage("Unable to parse unicode value: 
> ZZZZ");
>       }
>       @Test
>       public void optionalInvalidPropertiesFile() throws 
> ConfigurationException {
>               CombinedConfigurationBuilder builder = new 
> CombinedConfigurationBuilder()
>                               .configure(new 
> Parameters().fileBased().setFile(new File(
>                                               
> "src/test/resources/commons-configuration-issues/error-handling-invalid-properties-file.xml")));
>               /*
>                * If optional then an invalid property file is ignored. This 
> is not desired.
>                * Would be nice to configure that as serious problem that 
> leads to a general error independent of optional.
>                */
>               System.setProperty("propertiesOptional", "true");
>               CombinedConfiguration configuration = 
> builder.getConfiguration();
>               // At least all keys are consistently not set.
>               
> assertThat(configuration.getString("valueBeforeInvalid")).isNull();
>               assertThat(configuration.getString("invalidValue")).isNull();
>               
> assertThat(configuration.getString("valueAfterInvalid")).isNull();
>       }
> }
> {code}
> error-handling-include-not-found.xml:
> {code:java}
> <configuration>
>       <properties basePath="src/test/resources/commons-configuration-issues"
>               fileName="error-handling-include-not-found.properties" 
> config-optional="${sys:propertiesOptional}"/>
> </configuration>{code}
> error-handling-include-not-found.properties:
> {code:java}
> include = not_exist.properties
> {code}
> error-handling-properties-file-not-found.xml
> {code:java}
> <configuration>
>       <properties basePath="src/test/resources/commons-configuration-issues"
>               fileName="not-exist.properties" 
> config-optional="${sys:propertiesOptional}"/>
> </configuration>
> {code}
> error-handling-invalid-properties-file-not-found.xml
> {code:java}
> <configuration>
>       <properties basePath="src/test/resources/commons-configuration-issues"
>               fileName="not-exist.properties" 
> config-optional="${sys:propertiesOptional}"/>
> </configuration>{code}
> error-handling-invalid-properties-file-not-found.properties
> {code:java}
> valueBeforeInvalid=1
> invalidValue=\uZZZZ
> valueAfterInvalid=2
> {code}



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to