2009-06-08 9 views
35

Quiero almacenar la configuración para un proyecto web fuera del proyecto web (archivo ear/war). La aplicación no debe saber en qué contenedor se está ejecutando (WebSphere/JBoss, etc.).¿Cómo puedo almacenar los parámetros de configuración de Java EE fuera de un EAR o WAR?

¿Cuál es la mejor manera de manejar esto?

¿Es JNDI una manera limpia? Si JNDI puede resolver mis problemas, ¿cómo debo configurarlo? (¿Objetos personalizados?)

En mi caso, solo existen pares simples de Clave => Valor (Cadena, Cadena) para los puntos finales SOAP/WS.

+2

Java EE 8 puede presentar algo llamado "servicio de configuración" para cosas como esta. Ver http://www.jfokus.se/jfokus13/preso/jf13_JavaEEConfiguration.pdf también ver http: // java.net/jira/browse/JAVAEE_SPEC-19 –

+0

¿Por qué no utilizar argumentos jva? – djmj

Respuesta

26

ver este question para leer el archivo de propiedades fuera del archivo WAR.

Consulte este question para leer valores de variables de JNDI. Creo que esta es la mejor solución. Puede leer una variable String con este código:

Context initialContext = new InitialContext(); 
String myvar = (String) initialContext.lookup("java:comp/env/myvar"); 

El código anterior funcionará en todos los contenedores. En Tomcat declara lo siguiente en conf/server.xml:

<GlobalNamingResources ...> 
    <Environment name="myvar" value="..." 
     type="java.lang.String" override="false"/> 
</GlobalNamingResources> 

Lo anterior creará un recurso global. También es posible definir un recurso en el contexto de la aplicación. En la mayoría de los contenedores, los recursos JNDI están disponibles a través de una Consola de administración de MBeans. Algunos de ellos ofrecen una interfaz gráfica para editarlos. Como máximo, se necesita reiniciar la aplicación cuando se realiza un cambio.

Cómo se definen y editan los recursos JNDI es específico del contenedor. Es el trabajo del configurador/administrador aplicar las configuraciones apropiadas.

Estos son los beneficios que ofrece JNDI:

  • Se pueden definir los valores por defecto de los parámetros en el archivo WAR/EAR.
  • Los parámetros se pueden configurar fácilmente en el contenedor.
  • No necesita reiniciar el contenedor cuando modifica el valor de un parámetro.
+2

En mi caso, los usuarios finales "desentrenados" debían realizar la configuración de parámetros: navegar un archivo XML complejo para encontrar la única cosa que necesitaban cambiar no era una opción (demasiado riesgo de que cambien algo) no debe y romper todo el contenedor.) – Jared

+0

¿Qué hace un usuario final no capacitado administrando un contenedor? – Draemon

+4

En muchas organizaciones, la configuración la realizan los administradores de red. En algunos casos, solo un administrador puede configurar contraseñas u otros datos confidenciales. Estas personas pueden tener poca experiencia con XML. – kgiannakakis

10

Utilizo una variable de entorno para apuntar a una URL (que probablemente sea un archivo: // URL) que tiene mi configuración en ella. Esto es muy simple de configurar y no requiere la infraestructura JNDI.

He aquí algunos ejemplos de código (a máquina de la memoria - No he compilado/probado este):

public void loadConfiguration() { 
    String configUrlStr = System.getenv("CONFIG_URL"); // You'd want to use a more 
                 // Specific variable name. 
    if(configUrlStr == null || configUrlStr.equals("") { 
     // You would probably want better exception handling, too. 
     throw new RuntimeException("CONFIG_URL is not set in the environment."); 
    } 


    try { 
     URI uri = new URI(configUrlStr); 
     File configFile = new File(uri); 
     if(!configFile.exists()) { 
      throw new RuntimeException("CONFIG_URL points to non-existant file"); 
     } 
     if(!configFile.canRead()) { 
      throw new RuntimeException("CONFIG_URL points to a file that cannot be read."); 
     } 
     this.readConfiguration(configFile); 
    } catch (URISyntaxException e) { 
     throw new RuntimeException("Malformed URL/URI in CONFIG_URL"); 
    } 



} 
+0

Por simple que sea, tiene la desventaja de que necesita reiniciar el contenedor si necesita cambiar un valor. – kgiannakakis

+1

Solo tiene que reiniciar el contenedor si necesita cambiar la ubicación del archivo; puede ejecutar loadConfiguration() cada vez que necesite volver a leer el contenido del archivo. – Jared

4

Mis lugares favoritos son: Variables de entorno y Archivos de propiedades

Tabla Base de Datos de propiedades de entorno almacenar

Sin embargo, una de otras soluciones más simples es tener la base de datos (como se sugiere por Jared y kgiannakakis anteriormente). tabla de almacenamiento de las propiedades del entorno.

Si la aplicación utiliza la base de datos

  • esto es relativamente fácil de configurar
  • da paso muy fácil de controlar valora/cambio
  • Se puede integrar en el proceso, así por lo que es parte de DB scripts
+2

+1: Si ya está utilizando una base de datos, entonces almacenar los parámetros de configuración en una tabla es la solución más simple. Como ya tendrá bases de datos de producción/desarrollo/prueba, puede almacenar fácilmente diferentes valores para las diferentes implementaciones. Ni siquiera tiene que reiniciar la aplicación cuando se realiza un cambio. – kgiannakakis

+2

Pero, ¿cómo se obtiene la información de conexión para conectarse a la base de datos (ese es exactamente el tipo de información que me gustaría obtener de esta solución)? Este es un problema de huevo de gallina. – Jared

+1

De acuerdo - Jared. Diría que para DB confías en JNDI con la misma cadena JNDI. Por lo tanto, su aplicación siempre apuntará a java: comp/db/datasource. La información de configuración sobre DB (URL, usuario, pwd, etc.) se almacena fuera de contenedor. Las propiedades de DB funcionarán para cosas como URLs, cadenas externas, env. valores constantes dependientes, etc. Algunos contenedores proporcionan especificar todos estos como JNDI, pero no todos (por ejemplo, Websphere permite asociar valores de cadena con JNDI, Weblogic, por lo que sé, no) –

9

puede simplemente almacenar, entonces, es un archivo de propiedades java normal que se encuentra en la ruta de la clase y solo cargar las propiedades?

es sencillo y bastante simple .. a menos que me falta algo

+2

Aunque esto suena demasiado simple para ser bueno, en realidad es un buena alternativa. Muchos servidores de aplicaciones tienen rutas que se agregan a la ruta de clase, por lo que puede soltar archivos .properties allí. – alex

+0

Muchas aplicaciones que cambian de jndi a esta alternativa, agregando/etc a classpath –

11

Tuvimos un requisito configuración similar al desplegar una aplicación web para diferentes desarrolladores, y en EC2 de Amazon: ¿Cómo separamos de configuración desde el código binario? En mi experiencia, JNDI es demasiado complejo y varía demasiado entre contenedores para ser utilizado. Además, la edición manual de XML es muy susceptible a los errores de sintaxis, por lo que la idea se descartó. Se resolvieron con un diseño basado en unas pocas reglas:

1) único nombre sencilla = entradas de valor se deben utilizar

2) nuevas configuraciones debe ser cargable cambiando sólo un parámetro

3) nuestra binario guerra debe ser reconfigurable w/o reenvasado que

4) parámetros sensibles (contraseñas) nunca serán empaquetados en el binario

usando .properties archivos para toda la configuración, y el uso de System.getProperty("domain"); para cargar los archivos de propiedades apropiados, pudimos cumplir con los requisitos. Sin embargo, la propiedad del sistema no apunta a un archivo URL, en su lugar, creamos un concepto que llamamos "dominio" para especificar la configuración a usar. La ubicación de la configuración siempre es:
$HOME/appName/config/$DOMAIN.properties.

Así que si quiero ejecutar mi aplicación con mi propia configuración, comienzo de la aplicación estableciendo el dominio a mi nombre:
-Ddomain=jason
en el arranque, y la aplicación carga el archivo:
/home/jason/appName/config/jason.properties
Este permite a los desarrolladores compartir configuraciones para que podamos recrear el mismo estado de la aplicación para probar e implementar sin volver a compilar o volver a empaquetar. El valor del dominio se usa para cargar .properties desde una ubicación estándar, fuera del WAR incluido.

puedo recrear completamente el entorno de producción en mi estación de trabajo mediante el uso de la configuración de producción como:
-Ddomain=ec2 que cargar:
/home/jason/appName/config/ec2.properties

Esta configuración permite que tienen ciclos dev/GC/liberación con exactamente -uno- conjunto de binarios compilados, usando diferentes configuraciones en cada entorno. No hay riesgo de tener contraseñas/etc incluidas en los binarios, y las personas pueden compartir sus configuraciones para recrear los problemas que estamos viendo.

+0

¿Funciona para diferentes servidores de aplicaciones? –

+0

Hola Martin, sí, funciona para diferentes servidores de aplicaciones, ya que no existe dependencia de la aplicación. Estamos usando esto para Tomcat y Jetty, y se comportan de la misma manera. Debería funcionar para cualquier aplicación que no sea web. –

+0

Agradable. Sin embargo, creo que algunos servidores de aplicaciones pueden restringir su acceso al sistema de archivos, y entonces esto no funcionará para ellos. –

Cuestiones relacionadas