Archivos para la categoría: java

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.

Anuncios

Pues me encuentro en fase de pensar substituir unos websockets que tenemos por server-sent events (SSE). Lo utilizamos sólo para recibir eventos, con lo que para nuestro caso de uso nos podemos olvidar de la bidireccionalidad que ofrece el websocket.

Si alguien se encuentra en un caso similar, puede ver el código fuente en este enlace.

El ejemplo se compone de tres piezas:

API Node.js

Hacer estas cosas en Node.js me encanta por su sencillez, y no tener necesidad de importar ninguna dependencia externa ni nada. Si no fuera una PoC el código sería hasta más bonito. Esta api simplemente abre un stream de datos, donde se envía un número aleatorio cada segundo (uno distinto para cada request), siempre y cuando la petición esté abierta.

Cliente Angular

Una sencilla aplicación creada con el CLI de Angular.

Dispone cuatro componentes iguales que se suscriben a los eventos enviados por la API Node.js. El EventSource se crea en la primera suscripción, y se cierra cuando ya no hay más observers. Podemos ver cómo se ha impementado en este servicio.

API Gateway

Realizado con Spring Cloud Gateway, utiliza el RouteLocatorBuilder. para mapear las peticiones contra el servicio Node.js (ruta /sse) o contra el cliente web (ruta /*).

Y bueno, el ejemplo funcionando tiene esta pinta.

sse.gif

Recomiendo descargarlo y trastear con él. Incluye un docker-compose.yml para que sea más fácil montarlo.

¡Ah! Y para seguir cacharreando, node y java utilizan las imágenes distroless de Google.

Quiero hacer también otra versión en que los SSE se emitan desde un proyecto Spring Boot, pero es que es taaan fácil hacer esto con Node…

Cuando estén las dos, quiero hacer una versión para utilizarlo en conjunción con Protocol Buffers, que también venimos usándolo, aunque sólo con JavaScript. Así veremos su uso en varios lenguajes.

We are currently doing some spike applications that involve part of the Spring Cloud Netflix stack.

One of them is a Zuul edge server to proxy some microservices and handle authentication. On these microservices we need some special, custom headers. So we are going to see how to create a custom Zuul filter in our Spring context that add the user’s name on a header before proxying:
Leer el resto de esta entrada »

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…

Aaay! Los IDEs. Cuánto bien y cuánto mal hacen en nuestras vidas. Qué haríamos sin la indentación automática del código o sin los imports automáticos. Y qué bonico cuando tenemos unos cuantos imports del mismo paquete, y se nos agrupan todos en un import con wilcards, ¿no? Leer el resto de esta entrada »

Muchos tendremos repositorios maven añadidos de la siguiente forma, en nuestros ficheros pom.xml o settings.xml:

<repository>
   <id>apache.snapshots</id>
   <name>JBoss Maven2 repository</name>
   <url>http://repository.jboss.com/maven2/</url>
   <releases>
      <enabled>false</enabled>
      <updatePolicy>always</updatePolicy>
      </releases>
   <snapshots>
      <enabled>true</enabled>
      <updatePolicy>always</updatePolicy>
   </snapshots>
</repository>

El atributo updatePolicy hace referencia a la frecuencia con la que descargaremos las actualizaciones de ese repositorio. Si trabajamos con snapshots que sabemos que tienen mucho movimiento, sí que tiene sentido usar una política always. Sin embargo, si trabajamos con versiones estables que no van a verse modificadas, esto no tiene ningún sentido y lo único que hace es comerse ancho de banda y retrasar las construcciones. Y si internet te va un poco lento ese día, tómate varios cafés.

Así que si éste es nuestro caso, mejor cambiar el valor de updatePolicy a daily (es el valor por defecto) para que sólo haga esta comprobación una vez al día. Podríamos ser más restrictivos aún y establecerlo a never, de forma que sólo realizaría las comprobaciones si la información no existe a nivel local.

Fuente: Maven Reference.

Ahora que codehaus ha cerrado y ya no sirve repositorios de maven, tenemos que modificar nuestra configuración de maven para apuntar a algún otro repositorio y que no casquen.

Por ejemplo, el de mulesoft cubre todas nuestras necesidades. Editaremos nuestro fichero ~/.m2/settings.xml para incluir este repositorio:

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

   <!-- CONFIGURACIÓN EXTRA QUE PUEDA TENER -->

   <profiles>
      <profile>
         <id>myProfile</id>
         <repositories>

            <!-- TODOS MIS REPOSITORIOS -->

            <repository>
               <id>codehaus-mule-repo</id>
               <name>codehaus-mule-repo</name>
               <url>https://repository-master.mulesoft.org/nexus/content/groups/public</url>
               <layout>default</layout>
            </repository>
         </repositories>
      </profile>
   </profiles>

	<activeProfiles>
		<activeProfile>myProfile</activeProfile>
	</activeProfiles>
</settings>

Fuente: codehaus.

Uno de los servicios que ofrece Google en su plataforma app engine, es el acceso de usuarios a través de las sus cuentas de Google. Es la interfaz UserService la encargada de proporcionarnos esta información de usuario, así como de autenticarlo contra Google.
Leer el resto de esta entrada »

A %d blogueros les gusta esto: