Archivos Por autor

spring-boot-modulesEl otro día me pregunté el cómo hacía Spring para tener tantos @EnableFoo, @EnableBa, etc… y viendo lo sencillo que es me he decido por compartirlo con vosotros.

Todo surge ante una necesidad, que es la de tener alguna configuración común que queramos reutilizar entre distintos proyectos. Imaginemos que todos nuestros proyectos hacen uso de la misma Base de Datos, la cual tenemos configurada con Spring Data JPA, pero queremos hacer la configuración de la misma muy sencilla (añadir dependencia y listo).

Lo primero que hacemos es crearnos un módulo de Spring Boot aparte, pero a este le borramos la clase de Application que nos genera, más que nada no es una aplicación. Y le vamos a añadir toda la configuración de Spring Data JPA: dependencias y propiedades que ya teníamos (estamos moviendo las cosas de sitio).

Eso sí, antes cuando levantábamos la aplicación Spring Boot hacia toda la magia, pero ahora eso no sucederá, tendremos que hacerlo nosotros. Para ello, definimos una clase de configuración que cargue todo.

@Configuration
@EnableAutoConfiguration
@PropertySource(value = {"classpath:jpa-${spring.profiles.active}.properties"}, ignoreResourceNotFound = true)
public class JpaSupportConfiguration {
}

Se utilizan ficheros properties en vez de yml porque con Spring no existe una forma tan sencilla de cargarlos y que spring data coja la configuración correcta.

Tendremos un fichero de propiedades por entorno y lo cargamos dependiendo del perfil activo de Spring (spring.profiles.active). A destacar, que todas las propiedades se podrán sobrescribir con tan solo añadirla al application.yml de nuestro proyecto.

Una vez en este punto, tenemos tres opciones para cargar nuestro módulo:

Uso de @Import

Eso es dentro de alguna clase de configuración de nuestra aplicación hacer un

@Import(JpaSupportConfiguration.class)

Uso de @EnableJpaSupport

Para ello creamos en el módulo una anotación que lo único que hará es el @Import de más arriba.

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import(JpaSupportConfiguration.class)
@Configuration
public @interface EnableJpaSupport {
}

De esta forma podemos sustituir el @Import por:

@EnableJpaSupport

Auto configuración

Por último, está la opción de que se auto-configure por el simple hecho de añadir la dependencia. Para ello añadimos dentro del classpath el fichero META-INF/spring.factories en el cual añadiremos una línea con nuestra clase de configuración:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
edu.cinfantesa.config.JpaSupportConfiguration

Conclusiones

Como hemos podido ver, es muy sencillo crear módulo con Spring Boot. De forma que si nuestro proyecto es grande, nos permite tener cada configuración en su sitio y no replicada entre las distintas aplicaciones.

A mi personalmente, el modo de importar un módulo que más me gusta es el segundo, tal y como hace Spring con sus @EnableFoo….

Para temas más técnicos si que nos puede aportar algo más la parte de auto-configuración.

El tema de las anotaciones son más que conocidas en el mundo java y hoy en día casi todo lo configuramos con anotaciones, aquellos tiempos en los que se hacía todo en interminables ficheros xml que nadie era capaz de seguir se acabaron (gracias a dios).

Pero cuantas veces, sobre todo para los que usamos Spring Framework, hemos visto aquello de @EnableSomething y luego hacer uso de @Something? no os habéis preguntado nunca como funciona?

Todo esto surge, porque hace poco me surgió una necesidad en la que encajaba completamente una custom annotation para reutilizar el código. El caso en cuestión era suscribirse a eventos en kafka y me resultaba tedioso el tener que configurar kafka en cada módulo donde quisiera escuchar un evento y más aún los if que surgían… pongamos un ejemplo:

@KafkaListener(topics = "mitopic)
public void listener(String payload){
Event event = Event.from(payload);
if (event.name == "READ") {
// do something
} else if (event.name == "WRITE" {
// do something
} else if (event.name == "DELETE" {
// do something
}
}

Esta solución al menos a mi, me hace sangrar los ojos.. y es que no me llevo bien con los ifs y menos aún, con los concatenados.

Podríamos pensar en crear tres métodos distintos, uno para cada evento. Pero ni con esas vamos a conseguir quitarnos los ifs. Sin embargo, resultaría super sencillo contar con algo así:

@MyCustomAnnotation({Event.READ, Event.WRITE, Event.DELETE})
public void onEvent(String payload){
// do something
}

Incluso si quisiésemos separarlo, hasta quedaría bien:

@MyCustomAnnotation({Event.READ})
public void onRead(String payload){
// do something
}
@MyCustomAnnotation({Event.WRITE})
public void onWrite(String payload){
// do something
} 
@MyCustomAnnotation({Event.DELETE})
public void onDelete(String payload){
// do something
} 

¿A que queda mejor? ¿pero como hacerlo? Lo veremos en la segunda parte…

Ultimamente dedico más tiempo al mundo javascript que al java, más concretamente a entornos MEAN y mi mente se está pasando a un estilo de vida asíncrono. El stack MEAN y el desarrollo en node es relativamente ‘nuevo’, y siempre surgen dudas acerca de la seguridad.

Leer el resto de esta entrada »

Después de un mes que ha pasado volando, volvemos con otro artículo sobre docker. Y es que por poco que hayas “jugado” con contenedores, te habrás topado con el problema de la hora dentro del propio contenedor. Veamos pues cómo solucionarlo!!!

Leer el resto de esta entrada »

Cuando en nuestro flujo de trabajo tenemos el uso de contenedores, existe un momento a partir del cual la pereza se apodera de nosotros al existir una cantidad inhumana de versiones distintas.

Leer el resto de esta entrada »

A %d blogueros les gusta esto: