Аннотация Spring @Validated предотвращает внедрение значения @ConfigurationProproperties, почему?

Я пытаюсь с @ConfigurationProperties и нахожу две вещи:

  • чтобы тесты работали, я должен поместить файлы свойств конфигурации (yml) в пакет test; требуются сеттеры и пустой конструктор.
  • Если бы я аннотировал класс с помощью @Validated, внедрение просто завершилось бы неудачей со всеми значениями null.

Если вы скажете, что первое понятно, а второе? Почему?

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

У меня есть этот yaml для отображения:

accertify:
  fr:
    merchant1:
      host: "sandbox.accertify.dev"
      protocol: "https"
      user: "fraud"
      password: "temporal"
      merchant: "merchant1FR"
    merchant2:
      host: "sandbox.accertify.dev"
      protocol: "https"
      user: "fraud"
      password: "temporal"
      merchant: "merchant2FR"
  es:
    merchant1:
      host: "sandbox.accertify.dev"
      protocol: "https"
      user: "fraud"
      password: "temporal"
      merchant: "merchant1ES"
    merchant2:
      host: "sandbox.accertify.dev"
      protocol: "https"
      user: "fraud"
      password: "temporal"
      merchant: "merchant2ES"

У меня есть этот класс для сопоставления вложенных конфигураций:

import com.westerngun.fraud.jfps.dto.provider.accertify.country.ConfigurationEs;
import com.westerngun.fraud.jfps.dto.provider.accertify.country.ConfigurationFr;
import com.westerngun.fraud.jfps.service.client.ConnectionDetailsInterface;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;

import javax.validation.Valid;

/**
 * Class to read Accertify provider connection credentials.
 */
@Getter
@Setter
@Configuration
@ConfigurationProperties(prefix = "accertify")
@Validated   // <--- this seems the problem
@NoArgsConstructor
@AllArgsConstructor
public class AccertifyConnectionDetail extends ConnectionDetails {

    @Valid
    private ConfigurationFr fr;

    @Valid
    private ConfigurationEs es;
}

И его интерфейс:

public abstract class ConnectionDetails {
    public abstract ConfigurationFr getFr();
    public abstract ConfigurationEs getEs();
}

И ConfigurationEs, и ConfigurationFr являются подклассами:

@Component
public class CountryConfigDetail {
    @Getter
    @Setter
    @Valid
    private Merchant1 merchant1;

    @Getter
    @Setter
    @Valid
    private Merchant2 merchant2;
}

Merchant1 и Merchant2 являются подклассом:

@Data
@Component
public class MerchantConfigDetail {

    @NotEmpty
    @NotNull
    private String user;

    @NotEmpty
    @NotNull
    private String password;

    ...
    @NotEmpty
    @NotNull
    private Map<String, String> headers;
}

Когда я пытаюсь ввести некоторые @Autowired тесты без @Validated в первом классе, это работает (fr и es имеют значения в файле yml)

Аннотация Spring @Validated предотвращает внедрение значения @ConfigurationProproperties, почему?

Когда я добавляю @Validated, fr и es равны нулю.

Тестовое задание:

@RunWith(SpringRunner.class)
@SpringBootTest
public class AccertifyConfigurationTest {

    @Autowired
    private AccertifyConnectionDetail accertifyConnectionDetail; // <--- this field should be injected


    @Test
    public void givenAAccertifyClientService_WhenClientIsBuild_ShouldHaveTheProviderConfigurationCorrect() {
        AccertifyConfiguration accertifyConfiguration = new AccertifyConfiguration(accertifyConnectionDetail);
        accertifyConfiguration.buildConfiguration("FR", "Merchant1");

        Assert.assertEquals("fraud", accertifyConfiguration.getUser());
        Assert.assertEquals("temporal", accertifyConfiguration.getPassword());
        Assert.assertTrue(accertifyConfiguration.getHost().startsWith("sandbox.accertify."));
        Assert.assertEquals("merchant1FR", accertifyConfiguration.getMerchantCode());
    }
...

Пожалуйста, добавьте код для этого вопроса, он не соответствует моему использованию.

Darren Forsythe 02.04.2019 11:48

Добавьте свой тест как код, а не как изображения. Вы используете прокси, поэтому вы, вероятно, делаете то, что не должны делать в первую очередь. Кроме того, вы, вероятно, не хотите @Configuration на @ConfigurationProperties уроке.

M. Deinum 02.04.2019 15:06

Меняю @Configuration на @Component и прокси превращаются в настоящие объекты. А с @Validated он по-прежнему содержит все null. Насчет @Configuration и @ConfigurationProperties вы правы.

WesternGun 02.04.2019 15:19

Конечно, они null, поскольку вы их не создаете. Фреймворк не создаст новый экземпляр, вам придется сделать это самостоятельно при инициализации поля. Проверьте ServerProperties, который заранее создает экземпляры вложенных свойств. Будут созданы только поля, для которых существует конвертор или редактор, остальные, для привязки, придется создавать самому.

M. Deinum 02.04.2019 15:33

Я имел в виду, что без @Validated, когда я отлаживаю эти строки, accertifyConnectionDetail правильно @Autowired, значения считываются из файлов yaml и они не равны нулю, как показано на изображении, потому что Spring знает, что это @ConfigurationProperties; но, только раскомментировав @Validated, автопроводка не работает.

WesternGun 04.04.2019 10:01

Я сталкиваюсь с той же проблемой: пытаюсь внедрить @ConfigurationProperties bean-компонент в @Configuration-класс. Свойства конфигурации установлены правильно ... пока я не поставлю аннотацию @Validated. Какую версию загрузки вы используете?

ch4mp 10.06.2019 17:28

Я с 2.1.1.RELEASE

WesternGun 11.06.2019 12:47

кажется, что эта проблема все еще существует github.com/spring-projects/spring-boot/issues/8173 вы нашли обходной путь

Mr.Q 01.10.2019 17:10

Нет, у меня пока нет решения. Пока не пользуюсь @Validated.

WesternGun 01.10.2019 17:58
1
9
569
0

Другие вопросы по теме