@Значение не задано в одном конкретном классе

#spring #spring-boot #spring-annotations

#spring #spring-boot #spring-аннотации

Вопрос:

Я совершенно уверен, что веду себя как идиот, но, хоть убей, я этого не вижу.

У меня есть большое приложение Spring Boot 2.1, которое широко использует внедрение свойств через аннотацию @Value. Это отлично работает, работает годами. Но есть один конкретный, совершенно новый объект, для которого я не могу установить значения. Они всегда равны нулю.

Я знаю, что проблема не в самих значениях, потому что некоторые из тех же значений просто отлично внедряются в другие объекты. Но я просто не вижу, что не так с ЭТИМ объектом, и был бы благодарен за ваши глаза.

Значения в этом объекте (который находится в том же каталоге и строится просто отлично) всегда равны null:

 @Service
public class SSOUtil {
    private String domain = "https://login.microsoftonline.com/";
    private String tenantId = "[deleted guid]";
    public static String localEnvironment = "local";
    public static String devEnvironment = "dev";
    public static String testEnvironment = "test";
    public static String prodEnvironment = "prod";

    @Value("${actions.PROD.touchnet_azure_ad_client_secret}")
    private String clientSecretTouchnetProd;
    @Value("${actions.TEST.touchnet_azure_ad_client_secret}")
    private String clientSecretTouchnetTest;
    @Value("${actions.DEV.touchnet_azure_ad_client_secret}")
    private String clientSecretTouchnetDev;

    @Value("${actions.touchnet_azure_ad_client_id_dev}")
    private String clientIdDev;
    @Value("${actions.touchnet_azure_ad_client_id_test}")
    private String clientIdTest;
    @Value("${actions.touchnet_azure_ad_client_id_prod}")
    private String clientIdProd;

    @Value("${touchnet.redirectURLDev}")
    private String redirectURLDev;
    @Value("${touchnet.redirectURLTest}")
    private String redirectURLTest;
    @Value("${touchnet.redirectURLProd}")
    private String redirectURLProd;

    private String clientId;
    private String clientSecret;
    private String redirectURI;

    public SSOUtil() {
        this.redirectURI = redirectURLTest;
        this.clientSecret = clientSecretTouchnetTest;
    }

    public String getADLoginURL() {
        String returnURL = "";
        System.out.println(clientIdTest); // always prints null
    }
}
 

Однако значения в этом объекте работают просто отлично, и обратите внимание, что одно из них является тем же @Value, что и в другом классе:

 @Service
public class LibraryHelpServiceBean implements LibraryHelpService {
    private CourseServiceBean courseServiceBean;
    private final RestTemplate restTemplate;

    @Value("${actions.libraryhelp_lti_api_key}")
    private String apikey;

    @Value("${actions.touchnet_azure_ad_client_id_test}")
    String clientIdTest;

    public LibraryHelpServiceBean(CourseServiceBean courseServiceBean, RestTemplateBuilder restTemplateBuilder) {
        this.courseServiceBean = courseServiceBean;
        this.restTemplate = restTemplateBuilder.build();
    }

    public void doesValueWork() {
        this.apikey = this.apikey;
        System.out.println(this.clientIdTest); // always prints correct value, a guid
    }
 }
 

Оба объекта инициализируются аналогичным образом: прямо или косвенно через аннотацию @Autowired в других объектах, которые я использую (и которые отлично работают и отлично работали целую вечность). Вот создание SSOUtil (мой проблемный класс):

 @RestController
@RequestMapping(value = "/web")
public class SSOLandingController {

    @Autowired
    private SSOUtil ssoUtil;

 [rest of class omitted]
}
 

И вот создание LibraryHelpServiceBean, который работает нормально и все @Values заполняются правильно:

 @Service
public class LibraryHelpStreamServiceBean implements LibraryHelpStreamService {

    private LibraryHelpServiceBean libraryHelpServiceBean;
    
    public LibraryHelpStreamServiceBean(LibraryHelpServiceBean libraryHelpServiceBean){
         this.libraryHelpServiceBean = libraryHelpServiceBean;
    }
}
 

Я уже пробовал изменить аннотацию класса для SSOUtil с @Service на @Component (и @Configuration, просто так).

Что может быть причиной того, что @Values в SSOUtil возвращает значение null, даже если некоторые из тех же @Values отлично заполняются в других классах?

Я убежден, что мне не хватает чего-то очевидного. Я надеюсь, что это что-то маленькое, например, опечатка. Я нервничаю, что это что-то большое, как будто я совершенно неправильно понял, как работает Spring IOC в течение последних нескольких лет.

Спасибо за вашу помощь.

Комментарии:

1. Привет и добро пожаловать! В каком пакете («каталоге») находится SSOUtil ? .. он подбирается с помощью сканирования компонентов / автоматической настройки ?? 😉

2. Можете ли вы поделиться своей структурой проекта? Кроме того, попробуйте переместить все свои свойства в один класс @Component с помощью getter и setters, а затем вводить класс всякий раз, когда вы хотите использовать свойства.

3. Большое вам спасибо за любезный прием! Оба находятся в одном пакете, package edu.mycompanyname.its.actions.service . Библиотечная помощь;

4. И, Дэни, я думаю, что это отличный обходной путь, спасибо. Вероятно, я сделаю именно это, если не смогу разобраться в этом к полудню или около того в пятницу. Структура проекта довольно обширная — я унаследовал ее много лет назад, и у меня никогда не было проблем с ее расширением, поэтому я не могу легко поделиться здесь (и в любом случае это было бы не очень понятно). Но я думаю, что важным фактом является то, что и LibraryHelpServiceBean, и SSOUtil находятся в одном пакете, и у LibraryHelpServiceBean нет проблем с проверкой компонента.

Ответ №1:

Я проверил ваш случай на своем компьютере, но я не могу воспроизвести вашу проблему. Когда происходят подобные вещи, попробуйте что-то очень простое, например

 package no.mycompany.springbootapp;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

 @Component
 public class SSOUtil2 {
    @Value("${actions.touchnet_azure_ad_client_id_test}")
    private String clientIdTest;
 }
 

Вставьте этот компонент в свой контроллер, установите точку останова внутри вашего метода контроллера и проверьте введенный экземпляр.

По моему опыту, некоторые необъяснимые случаи, в которых я участвовал здесь, на SO, были решены путем очистки сборки или удаления папки .m2.