6

Estoy utilizando Java EE 6 y necesito cargar la configuración desde un archivo ".properties". ¿Existe una forma recomendada (mejor práctica) de cargar los valores del archivo de configuración mediante la inyección de dependencia? Encontré anotaciones para esto en Spring, pero no he encontrado una anotación "estándar" para Java EE.Inyección de dependencia con el archivo ".properties"

Este tipo han desarrollado una solución a partir de cero:

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

"No pude encontrar un ejemplo sencillo de cómo configurar la aplicación con CDI mediante la lectura de la configuración de los atributos de un archivo. .."

Pero me pregunto si hay una manera más estándar en lugar de crear una fábrica de configuración ...

Respuesta

1

Aunque no cubre exactamente su pregunta, this part de la documentación de Weld puede ser de su interés.

Habiendo mencionado esto, no, no hay una forma estándar de inyectar recursos/archivos de recursos arbitrarios. Supongo que simplemente está más allá del alcance de una especificación estandarizar un requisito tan altamente dependiente de la costumbre (Spring no es una especificación, simplemente pueden implementar lo que quieran). Sin embargo, lo que CDI proporciona es un mecanismo fuerte (también conocido como tipo seguro) para inyectar beans que contienen configuración en un lado, y un mecanismo productor flexible para leer y crear dichos beans en el otro lado. Definitivamente esta es la forma recomendada por la que preguntabas.

El enfoque al que se está vinculando es ciertamente bastante bueno, aunque podría ser demasiado para sus necesidades, dependiendo del tipo de propiedades que planea inyectar.

Una manera muy CDI-ish de continuar sería desarrollar una extensión CDI (que encapsularía muy bien todas las clases requeridas) y desplegarla independientemente con sus proyectos. Por supuesto, también puede contribuir al CDI-extension catalog o incluso al Apache Deltaspike.

+0

"Primavera ninguna especificación, que por supuesto puede implementar lo que quieran "- sí, pero specificati ons no vienen del cielo. Alguien lo ha escrito, como alguien escribió Spring. –

1

La única forma "estándar" de hacer esto sería usar un calificador con un miembro de anotación no vinculante y asegurarse de que todas sus inyecciones tengan un ámbito dependiente. Luego, en su productor, puede obtener InjectionPoint y obtener la clave del calificador en el punto de inyección. Lo que quiere algo como esto:

@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); 
} 

es evidente que hay algunas mejoras que se pueden hacer a ese código, pero debe ser suficiente para que pueda empezar por el camino correcto.

1

Ver @ConfigProperty de Apache DeltaSpike anotación

3

configuración

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 fábrica configuración podría ser:

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

gracias! ¿Cómo podemos cambiar programáticamente el BUNDLE_FILE_NAME aquí? Por ejemplo, el programa A a puede usar "a.properies" y el programa B "b.propiedades "pero me gustaría compartir este código. –

+0

¿cómo se define el archivo que se está inyectando? y de dónde lo lee? – f1wade

Cuestiones relacionadas