/ java

Filtrar properties por ambiente en Maven

Maven provee la capacidad de generar perfiles, en los cuales se pueden agregar properties por cada perfil, esto brinda la facilidad de intercambiar de una configuración a otra, aquí te mostramos como hacerlo

Profiles

Los perfiles nos permiten intercambiar configuraciones (entre otras cosas), el concepto en su versión más resumida es:

  • Quiero modificar la configuración para cada ambiente: desarrollo, pruebas y producción

Configuración

Entonces, definimos los siguientes elementos en el archivo pom.xml:

Indicar los recursos a utilizar:

<build>
  <resources>
    <resource>
      <!-- el path partiendo del src root del proyecto -->
      <directory>src/main/resources</directory>
      <!-- indicar que utilizaremos filtros en el build -->
      <filtering>true</filtering>
    </resource>
  </resources>
</build>

Agregar los perfiles:

<profiles>
  <profile>
    <!-- nombre del perfil, en este caso, el ambiente a configurar -->
    <id>dev</id>
    <!--
      indicamos que este perfil es el default,
      para no tener que indicarlo al compilar, esto sirve como seguridad
      en caso de que alguien compile una versión en su ambiente local,
      no se conecte a PROD u otro ambiente de mayor impacto al negocio
    -->
    <activeByDefualt>true</activeByDefault>
    <!--
      aquí van todas las configuraciones (properties)
      que vamos a parametrizar por ambiente
    -->
    <properties>
      <db.connection.url>LA_CADENA_DE_CONEXION_LOCAL</db.connection.url>
      <db.connection.showSql>true</db.connecioon.showSql>
    </properties>
  </profile>
  
  <!-- configuración para producción -->
  <profile>
    <id>PROD</id>
    <activateByDefault>false</activateByDefault>
    <properties>
      <db.connection.url>CONEXION_A_PROD</db.connection.url>
      <db.connection.showSql>false</db.connection.showSql>
    </properties>
  </profile>
</profiles>

La manera de cuadrar esto con tu archivo de propiedades es la siguiente, suponiendo un archivo application.properties:

cualquier.configuracion=cualquierValor
activar.esto=true

# propiedades inyectadas por ambiente
database.url=${db.connection.url}
database.showQueries=${db.connection.showSql}

Ejecución

Para ejecutar un perfil, basta indicarle el parámetro -P <profileId>, por ejemplo:

mvn install -P dev ó mvn install -P PROD

Generación de properties

Básicamente, dentro del ciclo de vida de compilado / ejecución en maven, existe un goal llamado resources, el cual genera los recursos (como el properties file) y utiliza las definiciones indicadas en el archivo pom.xml

En función de las propiedades, maven realizará un reemplazo de los valores de las propiedades con los valores definidos con las propiedades del perfil de maven, este archivo se genera dentro de ~/proyecto_maven/target, esto quiere decir:

Profile dev generará:

cualquier.configuracion=cualquierValor
activar.esto=true

# propiedades inyectadas por ambiente
database.url=LA_CADENA_DE_CONEXION_LOCAL
database.showQueries=true

Profile PROD generará:

cualquier.configuracion=cualquierValor
activar.esto=true

# propiedades inyectadas por ambiente
database.url=CONEXION_A_PROD
database.showQueries=false

Complicando las cosas

Esto es bastante útil, sin embargo, hay propiedades que no queremos guardar en el repositorio, por distintos motivos:

  • URL de conexión a la BD local, ya que cada developer tendría un esquema local distinto y credenciales distintas
  • URL de conexión a la BD de PROD, debido a que este sería un hueco de seguridad al compartir la conexión con todos los desarrolladores

Sobreescribiendo parámetros por línea de comando

Como alternativa directa, podemos sobreescribir cualquier valor del perfil indicando la propiedad como parámetro de ejecución, por ejemplo:

mvn install -P PROD -Ddb.connection.url=LA_CADENA_REAL_DE_PRODUCCION

De esta manera, podemos hacer la configuración del ambiente dependiente del input y no sólo a la definición del perfil

Desacoplar los archivos properties

Es posible generar archivos de propiedades distintos con tan sólo algunos ajustes a la configuración previamente indicada. Por ejemplo:

application.properties <<== archivo base de propiedades
application-dev.properties <<== configuración de desarrollo
application-prod.properties <<== configuración de producción

Esto permite realizar las siguientes adecuaciones:

  • Ignorar el archivo application-dev.properties del repositorio, por lo que cada desarrollador debería agregar su configuración local sin alterar nada en el repositorio
  • Separar las configuraciones delicadas de las configuraciones bases

Configuración

Indicador del perfil que se ejecuta:

<profile>
  <id>dev</id>
  <!-- el resto como estaba.. -->
  
  <properties>
    <!--
      crear un property para filtrar el archivo
      properties que vamos a utilizar en base al perfil
    -->
    <build.profile.id>dev</build.profile.id>
  </properties>
</profile>

Dentro del tag build, agregaremos lo siguiente:

<build>
  <!-- lo demás como estaba.. -->
  
  <filters>
    <!--
      indicar el filtro en base al property del perfil que se está ejecutando
    -->
    <filter>
      src/main/resources/application-${build.profile.id}.properties
    </filter>
  </filters>
</build>

Conclusión

Maven provee de varios mecanismos para parametrizar las propiedades, las cuales podemos utilizar para preparar nuestras configuraciones por ambiente (o cualquier otro use case que necesites)

Los métodos principales son:

  • Definición de propiedades en los perfiles
  • Sobreescribir propiedades mediante la línea de comandos
  • Definir distintos archivos de propiedades (por perfil)