web-dev-qa-db-fra.com

Fichier de propriétés de chargement de projet multi-module Spring-Boot

J'ai une application Spring-Boot en tant que projet multimodule dans maven. La structure est la suivante:

Parent-Project
|--MainApplication
|--Module1
|--ModuleN

Dans le projet MainApplication, il y a la classe de méthode main() annotée avec @SpringBootApplication et ainsi de suite. Comme toujours, ce projet a un fichier application.properties qui est chargé automatiquement. Je peux donc accéder aux valeurs avec l'annotation @Value

@Value("${myapp.api-key}")
private String apiKey;

Dans mon Module1, je souhaite également utiliser un fichier de propriétés (appelé module1.properties), dans lequel la configuration des modules est stockée. Ce fichier sera uniquement utilisé et utilisé dans le module. Mais je ne peux pas le charger. Je l'ai essayé avec @Configuration et @PropertySource mais pas de chance.

@Configuration
@PropertySource(value = "classpath:module1.properties")
public class ConfigClass {

Comment puis-je charger un fichier de propriétés avec Spring-Boot et accéder facilement aux valeurs? Impossible de trouver une solution valide.

Ma configuration  

@Configuration
@PropertySource(value = "classpath:tmdb.properties")
public class TMDbConfig {

    @Value("${moviedb.tmdb.api-key}")
    private String apiKey;

    public String getApiKey() {
        return apiKey;
    }

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

Appel de la configuration

@Component
public class TMDbWarper {

@Autowired
private TMDbConfig tmdbConfig;

private TmdbApi tmdbApi;

public TMDbWarper(){
    tmdbApi = new TmdbApi(tmdbConfig.getApiKey());
}

Je reçois une exception NullPointerException dans le constructeur lorsque je câble automatiquement le warper.

16
Daniel

Pour l'injection sur le terrain:

Les champs sont injectés juste après la construction d'un bean, avant que des méthodes de configuration ne soient appelées. Un tel champ de configuration ne doit pas nécessairement être public. Référez-vous Annotation auto-câblée pour une utilisation complète. Utilisez l'injection de constructeur dans ce cas comme ci-dessous:

@Component
public class TMDbWarper {

    private TMDbConfig tmdbConfig;

    private TmdbApi tmdbApi;

    @Autowired
    public TMDbWarper(final TMDbConfig tmdbConfig){
            this.tmdbConfig = tmdbConfig;
            tmdbApi = new TmdbApi(tmdbConfig.getApiKey());
    }

(ou)

Utilisez @PostConstruct pour initialiser comme ci-dessous:

@Component
public class TMDbWarper {

    @Autowired
    private TMDbConfig tmdbConfig;

    private TmdbApi tmdbApi;

    @PostConstruct
    public void init() {
        // any initialisation method
        tmdbConfig.getConfig();
    }
6
Subash J

Le câblage automatique est effectué juste après la création de l'objet (après avoir appelé le constructeur par réflexion). Donc, NullPointerException est attendu dans votre constructeur car le champ tmdbConfig serait nul lors de l'appel du constructeur

Vous pouvez résoudre ce problème en utilisant la méthode de rappel @PostConstruct comme indiqué ci-dessous:

@Component
public class TMDbWarper {

    @Autowired
    private TMDbConfig tmdbConfig;

    private TmdbApi tmdbApi;

    public TMDbWarper() {

    }

    @PostConstruct
    public void init() {
        tmdbApi = new TmdbApi(tmdbConfig.getApiKey());
    }

    public TmdbApi getTmdbApi() {
        return this.tmdbApi;
    }
}

Le reste de votre configuration me semble correct. 

J'espère que cela t'aides.

5
skadya

Voici un exemple de multi-module Spring Boot où vous pouvez obtenir des propriétés dans différents modules . Disons que j'ai main application module, dataparse-module , datasave-module.

StartApp.Java dans application module:

@SpringBootApplication
public class StartApp {

    public static void main(String[] args) {

        SpringApplication.run(StartApp.class, args);
    }
}

Configuration dans dataparse-module . ParseConfig.Java:

@Configuration
public class ParseConfig {
        @Bean
        public XmlParseService xmlParseService() {
            return new XmlParseService();
        }
}

XmlParseService.Java:

@Service
public class XmlParseService {...}

Configuration dans datasave-module . SaveConfig.Java:

@Configuration
@EnableConfigurationProperties(ServiceProperties.class)
@Import(ParseConfig.class)//get beans from dataparse-module - in this case XmlParseService
public class SaveConfig {

    @Bean
    public SaveXmlService saveXmlService() {
        return new SaveXmlService();

    }

}

ServiceProperties.Java:

@ConfigurationProperties("datasave")
public class ServiceProperties {

    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

application.properties dans le dossier datasave-module in resource/config:

datasave.message = Projet Maven multi-module! 

threads.xml.number = 5 

file.location.on.disk = D:\temp\registry

Ensuite, dans datasave-module , vous pouvez utiliser toutes vos propriétés via @Value.

SaveXmlService.Java:

@Service
public class SaveXmlService {

    @Autowired
    XmlParseService xmlParseService;

    @Value("${file.location.on.disk: none}")
    private String fileLocation;

    @Value("${threads.xml.number: 3}")
    private int numberOfXmlThreads;

    ...
}

Ou via ServiceProperties:

Service.Java:

@Component
public class Service {

    @Autowired
    ServiceProperties serviceProperties;

    public String message() {

        return serviceProperties.getMessage();

    }
}
3
Kirill Ch

J'ai eu cette situation auparavant, j'ai remarqué que le fichier de propriétés n'a pas été copié dans le pot.

J'ai fait le suivant pour le faire fonctionner:

  1. Dans le dossier des ressources, j'ai créé un package unique, puis stocké mon fichier application.properties à l'intérieur de celui-ci. par exemple: com/société/projet

  2. Dans le fichier de configuration, par exemple: TMDBConfig.Java, j'ai référencé le chemin complet de mon fichier .properties:

    @Configuration
    @PropertySource("classpath:/com/company/project/application.properties")
    public class AwsConfig
    

Construire et exécuter, cela fonctionnera comme par magie.

1

Vous pouvez autowire et utiliser le Enviornment bean pour lire la propriété

@Configuration
@PropertySource(value = "classpath:tmdb.properties")
public class TMDbConfig {

  @Autowired
  private Environment env;

  public String getApiKey() {
    return env.getRequiredProperty("moviedb.tmdb.api-key");
  }

}

Cela devrait garantir que la propriété est lue à partir du contexte lorsque vous appelez la méthode getApiKey(), que la résolution de @Value soit résolue par PropertySourcesPlaceholderConfigurer.

0
Karol Dowbecki