Ir al contenido principal

Destacado

Introducción a Axon Framework - Parte 1

Investigando sobre arquitecturas CQRS encontre el Axon Framework.  Te comparto mis apuntes en mi camino a aprender este framework.


¿Que es CQRS?
CQRS es una forma de crear sistemas de software que hace hincapié en separar la parte  que cambia el estado de la aplicación y la parte que consulta el estado de la aplicación. 

¿Que es el Framework Axon? Es un framework para implementar CQRS en Java. Se describe asi mismo como un framework que te permite construir aplicaciones escalables, extensibles y mantenibles; permitiendo a los desarrolladores aplicar el patrón arquitectónico Command Query Responsibility Segregation (CQRS). El cual nos da ciertos bloques importantes con sus implementaciones respectivas para crear estos sistemas como: agregados, repositorios y bus de eventos (el mecanismo de envío para eventos).  Estos últimos términos provienen del Domain Driven Design (DDD). 
En palabras simples: CQRS es escribir y leer en forma separada. 
En búsqueda de tener bajo acoplamiento, el tr…

Usando CrudRepository con Kotlin


Ahora vamos a ver si podemos aplicar lo aprendido con Spring Boot y cambiar nuestro código con Kotlin.

Esta vez seguimos con Gradle



Nos aseguramos de tener las siguientes dependencias en buildScript:




buildscript {
 ext {
  kotlinVersion = '1.1.3-2'
  springBootVersion = '1.5.6.RELEASE'
 }
 repositories {
  mavenCentral()
 }
 dependencies {
  classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
        classpath("org.jetbrains.kotlin:kotlin-noarg:$kotlinVersion")
  classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}")
  classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}")
 }
}

El compiler plugin allopen nos evitara estar colocando la palabra reservada open. El compiler plugin noarg agrega un constructor sin argumento donde se encuentre la anotación específica.


// Or "kotlin-jpa" for the Java Persistence API support
apply plugin: "kotlin-noarg"

En nuestro caso usaremos kotlin-jpa para tener un constructor sin argumento en nuestras entidades. Los plugins finalmente serán:


apply {
    plugin("kotlin")
    plugin("kotlin-spring")
    plugin("kotlin-jpa")
    plugin("org.springframework.boot")
}


El plugin kotlin-spring es para poder usar todas las anotaciones de Spring.

Las dependencias del proyecto serán:





dependencies {
 compile('org.springframework.boot:spring-boot-starter-data-jpa')
 compile('org.springframework.boot:spring-boot-starter-web')
 compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:${kotlinVersion}")
 compile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
 compile("com.h2database:h2")
 compile("com.fasterxml.jackson.module:jackson-module-kotlin")
 testCompile('org.springframework.boot:spring-boot-starter-test')
}



Nuestra Entidad Alumno

Esta será una entidad JPA. El código es el siguiente:




package com.example.demoCrudRepository

import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id

/**
 * Created by josediaz on 7/27/17.
 */
@Entity
class Alumno(
        val firstName: String,
        val lastName: String,
        @Id @GeneratedValue(strategy = GenerationType.AUTO)
        val id: Long = -1) {

    override fun toString(): String {
        return "Alumno(id=$id, firstName='$firstName', lastName='$lastName')"
    }
}

Sobreescribimos el método toString para poder generar un log mas humano. Luego creamos una interface que herede de CrudRepository.


CrudRepository de Spring Data


package com.example.demoCrudRepository

import org.springframework.data.repository.CrudRepository

/**
 * Created by josediaz on 7/27/17.
 */
interface AlumnoRepository : CrudRepository{

    fun findByLastName(lastName: String): Iterable
}


Application con CommandLineRunner

Luego en la clase Application creamos algunos Alumnos y probamos los métodos que Spring Data nos provee con CrudRepository.


package com.example.demoCrudRepository


import org.slf4j.LoggerFactory
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.Bean

@SpringBootApplication
class DemoCrudRepositoryApplication{



        private val log = LoggerFactory.getLogger(DemoCrudRepositoryApplication::class.java)

        @Bean
        fun init(repository: AlumnoRepository) = CommandLineRunner {
            // save a couple of alumnos
            repository.save(Alumno("Elias", "Diaz"))
            repository.save(Alumno("Felipe", "Diaz"))
            repository.save(Alumno("Deborah", "Diaz"))
            repository.save(Alumno("Maria", "Diaz"))
            repository.save(Alumno("Daniel", "Diaz"))

            // fetch all alumnos
            log.info("Alumnos found with findAll():")
            log.info("-------------------------------")
            for (alumno in repository.findAll()) {
                log.info(alumno.toString())
            }
            log.info("")

            // fetch an individual alumno by ID
            val alumno = repository.findOne(1L)
            log.info("Alumno found with findOne(1L):")
            log.info("--------------------------------")
            log.info(alumno.toString())
            log.info("")

            // fetch alumnos by last name
            log.info("Alumno found with findByLastName('Bauer'):")
            log.info("--------------------------------------------")
            for (diaz in repository.findByLastName("Diaz")) {
                log.info(diaz.toString())
            }
            log.info("")
        }


}

fun main(args: Array) {
    SpringApplication.run(DemoCrudRepositoryApplication::class.java, *args)
}




Controller

Finalmente, si queremos usarlo en un Controller.



package com.example.demoCrudRepository;

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RestController

@RestController
class AlumnoController(val repository: AlumnoRepository) {

    @GetMapping("/")
    fun findAll() = repository.findAll()

    @GetMapping("/{lastName}")
    fun findByLastName(@PathVariable lastName:String)
            = repository.findByLastName(lastName)


}



Si probamos el resultado es:


Comentarios