Spring boot jar не читает/разбирает корневую папку application.properties

Ситуация

У меня есть толстый .jar загрузочного приложения Spring. Я внедрил свою конфигурацию в файл application.properties. Этот файл находится в той же папке, что и .jar, и я запускаю .jar из командной строки из той же папки (с помощью команды «java -jar $jarFileName»).

Затем выбрасывается исключение:

nested exception is org.springframework.beans.TypeMismatchException: 
Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is 
java.lang.NumberFormatException: For input string: "${elasticsearch.port}"

Как видите, вместо того, чтобы читать значение из файла свойств, он просто устанавливает строку как текст в аннотации @Value, которая выглядит так:

@Value("${elasticsearch.port}")
private int elkPort;

Класс, в котором это происходит, помечен @Component. Согласно документам Spring: экстернализация конфигурации, Spring должен прочитать файл application.properties за пределами банки.

Когда тот же файл application.properties помещается в src/main/resources, он работает нормально, поэтому файл конфигурации кажется правильным.

Любые идеи, почему он не загружает внешний файл конфигурации?

РЕДАКТИРОВАТЬ 1 Я также пытался запустить его с --spring.config.location=file:application.properties и --spring.config.location=file:/full/path/to/application.properties, но с тем же результатом, что и выше.

EDIT 2: попытка пути к классам Также попробовал classpath вместо file, то же самое, что и команды выше, но file заменил на classpath. Наконец попробовал без них, так что просто --spring.config.location=/path/to/file; снова как с относительным, так и с полным путем к application.properties. Все попытки дали один и тот же результат/исключение.

EDIT 3 Мое аннотированное приложение:

@SpringBootApplication
public class ApplicationName {

    public static void main(String[] args) {
        SpringApplication.run(ApplicationName.class, args);
    }
}

EDIT 4 Попытался добавить PropertySourcesPlaceholderConfigurer следующим образом:

@Configuration
public class PropertyConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

А затем для каждого @Value я добавил значение по умолчанию; он по-прежнему разрешается только значениями по умолчанию, а не значениями application.properties.


person Oromë    schedule 01.05.2018    source источник
comment
Файл читается? Имеет ли он правильные разрешения, чтобы ваше приложение действительно могло читать файл.   -  person M. Deinum    schedule 01.05.2018
comment
Да, это. Просто чтобы убедиться, что это не ошибка, я дал каждому использованному доступ для чтения и также запустил банку от имени администратора.   -  person Oromë    schedule 01.05.2018
comment
Как выглядит ваш аннотированный класс @SpringBootApplication. Вы же не пытаетесь загрузить файл самостоятельно, используя @PropertySource?   -  person M. Deinum    schedule 01.05.2018
comment
Нет, нет, и я добавил свой класс @SpringBootApplication в основной пост.   -  person Oromë    schedule 01.05.2018
comment
Не добавляйте PropertySourcesPlaceholderConfigurer Spring Boot позаботится об этом. Если это не работает, что-то в вашем приложении отключает обычное поведение.   -  person M. Deinum    schedule 02.05.2018


Ответы (3)


Хорошо, после некоторой борьбы я нашел решение. Я был близок с PropertySourcesPlaceholderConfigurer, но еще не совсем; это полный класс сейчас:

@Configuration
public class PropertyConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        final PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();

        ppc.setIgnoreResourceNotFound(true);

        final List<Resource> resources = new ArrayList<>();

        resources.add(new FileSystemResource("relative/path/to/application.properties"));

        ppc.setLocations(resources.toArray(new Resource[]{}));

        return ppc;
    }
}

ИЗМЕНИТЬ

Чтобы продемонстрировать проблему, я создал репозиторий, чтобы показать проблему, см. здесь: https://github.com/Locitao/test-external-properties

person Oromë    schedule 01.05.2018
comment
В этом нет необходимости, так как это уже сделано Spring Boot. Тот факт, что это не работает, означает, что в вашем классе (пути) должно быть что-то, что отключает обычное поведение. - person M. Deinum; 02.05.2018
comment
Я сделал базовый репозиторий, который максимально точно имитирует мой собственный проект с точки зрения зависимостей, чтобы продемонстрировать проблему. Я понятия не имею, в чем причина проблемы, но она присутствует и в демо, см. здесь: github .com/Locitao/test-external-properties - person Oromë; 02.05.2018
comment
Почему вы используете Shadowjar? Вы в основном работаете с Spring Boot с этим плагином... Вы должны использовать плагин Spring Boot. - person M. Deinum; 02.05.2018
comment
Удаление этого (и настройка jar) и просто использование обычного способа создания jar с помощью плагина Spring Boot работает как шарм. Поэтому в основном удалите теневой плагин и настройки jar и просто используйте gradle clean build, чтобы получить исполняемый jar. Вы пытаетесь перехитрить Spring Boot и в процессе разрушаете то, как он работает. - person M. Deinum; 02.05.2018
comment
На самом деле, при использовании gradle clean build или gradle clean assemble я возвращаюсь к предыдущей проблеме, которая у меня была: stackoverflow.com/questions/50040181/ - person Oromë; 02.05.2018
comment
Это может быть, но дело в том, что вы все еще пытаетесь быть умнее, чем используемые вами фреймворки. Из того, что я вижу, единственное, что вы хотите сделать, это добавить дополнительные внешние зависимости в ваше приложение Spring Boot. Что вам нужно сделать, так это настроить приложение на использование PropertiesLauncher, а в точке входа в докер использовать loader.path для добавления внешних зависимостей. См. docs.spring.io/spring-boot/docs/current/reference/html/ - person M. Deinum; 02.05.2018

Как сказано на упомянутой странице, вы должны указать внешнее местоположение конфигурации.

    $ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

Попробуйте без ключевого слова файла --spring.config.location=/full/path/application.properties

person Pavel M    schedule 01.05.2018
comment
Пробовал это как с относительными, так и с полными путями к файлу конфигурации; а также с classpath и file; все их комбинации давали одну и ту же ошибку. - person Oromë; 01.05.2018

Я только что вынул свой application.properties из проекта Eclipse Spring Boot, и это не удалось. Затем я положил файл в папку cfg в корне проекта и добавил аргумент программы:

--spring.config.location=cfg/application.properties

и это снова сработало. Возможно, если вы попробуете указать относительный путь (без ведущего /) к файлу (без «файла:»), он будет работать.

person Jan Larsen    schedule 01.05.2018
comment
Пробовал именно так, с папкой cfg, к сожалению та же проблема осталась. - person Oromë; 01.05.2018