6

".properties" Sto usando Java EE 6 e la necessità di caricare la configurazione da un file ".properties". Esiste un modo consigliato (best practice) per caricare i valori dal file di configurazione usando dependency injection? Ho trovato annotazioni per questo in primavera, ma non ho trovato un'annotazione "standard" per Java EE.Dependency Injection utilizzare file

Questo ragazzo ha sviluppato una soluzione da zero:

http://weblogs.java.net/blog/jjviana/archive/2010/05/18/applicaction-configuration-java-ee-6-using-cdi-simple-example

"Non riuscivo a trovare un semplice esempio di come configurare l'applicazione con CDI con la lettura della configurazione gli attributi da un file. .."

Ma mi chiedo se c'è un modo più standard invece di creare una fabbrica di configurazione ...

risposta

1

Anche se non copre esattamente la tua domanda, this part della documentazione di saldatura potrebbe essere di tuo interesse.

Dopo aver parlato di questo - no, non esiste un modo standard per iniettare file arbitrari risorse/risorse. Immagino che sia semplicemente oltre lo scopo di una specifica standardizzare questo requisito altamente dipendente dalla dipendenza (Spring non è una specifica, possono semplicemente implementare qualsiasi cosa vogliano). Tuttavia, ciò che CDI fornisce è un meccanismo forte (aka typesafe) per iniettare i bean di gestione della configurazione su un lato e un meccanismo flessibile del produttore per leggere e creare tali bean dall'altra parte. Sicuramente questo è il modo raccomandato che stavi chiedendo.

L'approccio che si sta creando un collegamento è certamente una abbastanza buona - anche se potrebbe anche me tanto per le vostre esigenze, a seconda del tipo di proprietà che si prevede di iniettare.

Un modo molto CDI-ish di continuare sarebbe quello di sviluppare un prolungamento CDI (che sarebbe bene incapsulare tutte le classi richieste) e distribuirlo in modo indipendente con i vostri progetti. Ovviamente puoi anche contribuire allo CDI-extension catalog o anche allo Apache Deltaspike.

+0

"La primavera è alcuna specificazione, possono semplicemente implementare quello che vogliono "- sì, ma specificati non vengono dal cielo Qualcuno lo ha scritto, proprio come qualcuno ha scritto Spring. –

1

L'unico modo "standard" di fare questo sarebbe quella di utilizzare un qualificatore di un membro di annotazione non vincolante, e assicurarsi che tutte le iniezioni sono dipendenti ambito. Poi nel tuo produttore puoi ottenere una sospensione di InjectionPoint e togliere la chiave dal qualificatore nel punto di iniezione. Che ci si vuole qualcosa di simile:

@Qualifier 
public @interface Property { 
    @Nonbinding String value default ""; 
} 

... 
@Inject @Property("myKey") String myKey; 


... 
@Produces @Property public String getPropertyByKey(InjectionPoint ip) { 
    Set<Annotation> qualifiers = ip.getQualifiers 

    // Loop through qualifers looking for Property.class save that off 
    return ResourceBundle.getBundle(...).getString(property.key); 
} 

Ci sono ovviamente alcuni miglioramenti si possono fare per quel codice, ma dovrebbe essere sufficiente per iniziare lungo la strada giusta.

1

Sede @ConfigProperty di Apache DeltaSpike

3

configurazione annotazione

package com.ubiteck.cdi; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import javax.enterprise.util.Nonbinding; 
import javax.inject.Qualifier; 

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
public @interface InjectedConfiguration { 
    /** 
    * Bundle key 
    * @return a valid bundle key or "" 
    */ 
    @Nonbinding String key() default ""; 
    /** 
    * Is it a mandatory property 
    * @return true if mandator 
    */ 
    @Nonbinding boolean mandatory() default false; 
    /** 
    * Default value if not provided 
    * @return default value or "" 
    */ 
    @Nonbinding String defaultValue() default ""; 
} 

La fabbrica di configurazione potrebbe apparire come:

import java.text.MessageFormat; 
import java.util.MissingResourceException; 
import java.util.ResourceBundle; 
import javax.enterprise.inject.Produces; 
import javax.enterprise.inject.spi.InjectionPoint; 

public class ConfigurationInjectionManager { 
    static final String INVALID_KEY="Invalid key '{0}'"; 
    static final String MANDATORY_PARAM_MISSING = "No definition found for a mandatory configuration parameter : '{0}'"; 
    private final String BUNDLE_FILE_NAME = "configuration"; 
    private final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_FILE_NAME); 

    @Produces 
    @InjectedConfiguration 
    public String injectConfiguration(InjectionPoint ip) throws IllegalStateException { 
     InjectedConfiguration param = ip.getAnnotated().getAnnotation(InjectedConfiguration.class); 
     if (param.key() == null || param.key().length() == 0) { 
      return param.defaultValue(); 
     } 
     String value; 
     try { 
      value = bundle.getString(param.key()); 
      if (value == null || value.trim().length() == 0) { 
       if (param.mandatory()) 
        throw new IllegalStateException(MessageFormat.format(MANDATORY_PARAM_MISSING, new Object[]{param.key()})); 
       else 
        return param.defaultValue(); 
      } 
      return value;    
     } catch (MissingResourceException e) { 
      if (param.mandatory()) throw new IllegalStateException(MessageFormat.format(MANDATORY_PARAM_MISSING, new Object[]{param.key()})); 
      return MessageFormat.format(INVALID_KEY, new Object[]{param.key()}); 
     } 
    } 

Tutorial with explanation and Arquillian test

+0

grazie! come possiamo cambiare programmaticamente il BUNDLE_FILE_NAME qui? Ad esempio, il programma A può utilizzare "a.properies" e il programma B "b.proprietà "ma vorrei condividere questo codice –

+0

come si definisce il file che viene iniettato e da dove lo legge? – f1wade

Problemi correlati