Estoy tratando de crear un SDK (una biblioteca personalizada) para mis microservicios Spring Boot usando Gradle (con Kotlin DSL) y Kotlin para enviar correos electrónicos, reutilizando la mayoría de las cosas y bibliotecas, usando AWS SES.
En primer lugar, no tengo mucha experiencia en la creación de bibliotecas de Java, por lo que podría haber muchas cosas que no estoy haciendo correctamente. Cualquier comentario es bienvenido.
De todos modos, quiero que esta biblioteca tome algunas propiedades del archivo application.yml en la aplicación final (la propia aplicación de microservicio) para instanciar algunos de los Beans de la biblioteca.
Esta biblioteca usa JavaEmailService y tiene algunos parámetros para usar el servidor de correo electrónico local cuando se desarrolla en local, o la implementación de AWS SES para las versiones implementadas.
Por ejemplo, en la configuración Bean de la librería tengo el siguiente código:
@Configuration internal class BeanConfig { // ... other properties @Value("\${sdk.mail.aws.access_key:}") private lateinit var awsMailAccessKey: String @Value("\${sdk.mail.aws.secret_key:}") private lateinit var awsMailSecretKey: String @Value("\${sdk.mail.aws.region:}") private lateinit var awsMailRegion: String @Value("\${sdk.mail.is_local:}") private var isLocal: Boolean? = null // ... other bean resolves @Bean fun amazonSimpleEmailService(): AmazonSimpleEmailService { if (isLocal == true) { return DummyAmazonSimpleEmailServiceImpl() } if (awsMailAccessKey.isEmpty() || awsMailSecretKey.isEmpty() || awsMailRegion.isEmpty()) { throw Exception("Missing AWS parameters (access_key, secret_key, region)") } return AmazonSimpleEmailServiceClientBuilder .standard() .withCredentials( AWSStaticCredentialsProvider( BasicAWSCredentials( awsMailAccessKey, awsMailSecretKey ) ) ) .withRegion(Regions.fromName(awsMailRegion)) .build() } } Quiero que tome los valores del archivo application.yml en la aplicación final así:
sdk: mail: is_local: false aws: access_key: ${AWS_MAIL_ACCESS_KEY:} secret_key: ${AWS_MAIL_SECRET_KEY:} region: ${${AWS_MAIL_REGION:} Hice una selección personalizada de las dependencias que deberían incluirse en el archivo jar final, ya que estaba recibiendo muchas ClassNotFoundException (cualquier recomendación en esta parte también es bienvenida, en la generación de jar de la biblioteca Java). Incluye en el jar final todas las dependencias necesarias para su funcionamiento.
Aquí las partes relevantes del archivo build.gradle.kts para la generación del archivo jar cuando ejecuto ./gradlew build :
plugins { id("org.springframework.boot") version "2.5.0" id("io.spring.dependency-management") version "1.0.11.RELEASE" kotlin("jvm") version "1.5.10" kotlin("plugin.spring") version "1.5.10" `java-library` `maven-publish` } // ... library version, name and trivial info dependencies { implementation(kotlin("stdlib")) implementation("org.springframework.boot:spring-boot-autoconfigure:2.5.0") implementation("org.springframework:spring-context-support:5.3.7") implementation("org.jetbrains.kotlin:kotlin-noarg:1.5.10") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") implementation("org.springframework.boot:spring-boot-starter-mail:2.5.0") implementation("org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE") implementation("com.amazonaws:aws-java-sdk-ses:1.12.131") testImplementation("org.junit.jupiter:junit-jupiter:5.7.2") testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.2") testImplementation(platform("org.junit:junit-bom:5.7.2")) testImplementation("io.mockk:mockk:1.10.3-jdk8") testImplementation("org.junit.platform:junit-platform-launcher:1.7.2") testImplementation("org.junit.jupiter:junit-jupiter-engine:5.7.2") testImplementation("org.junit.vintage:junit-vintage-engine:5.7.2") } tasks.withType<KotlinCompile> { kotlinOptions { freeCompilerArgs = listOf("-Xjsr305=strict") jvmTarget = "11" } } val exportPackages: List<String> = listOf( "spring-boot-starter-mail", "jakarta.mail", "jakarta.activation", "spring-context-support", "spring-boot-starter/", "spring-cloud-starter-aws", "spring-cloud-aws-context", "spring-cloud-aws-core", "javax.mail-api", "javax.activation", "aws-java-sdk-ses", "aws-java-sdk-core", "httpclient", "httpcore", "joda-time" ) // Here the custom part tasks.getByName<Jar>("jar") { enabled = true from ( configurations.compileClasspath.get().mapNotNull { if (exportPackages.any { exportPackage -> it.path.contains(exportPackage) }) { if (it.isDirectory) it else zipTree(it) } else null } ) duplicatesStrategy = DuplicatesStrategy.INCLUDE } Cuando ./gradlew build obtengo un archivo "sdk-mail-0.0.1-plain.jar". Esta parte funciona bastante bien si la incluí en la aplicación final con ese archivo en el mismo repositorio, así:
implementation(files("lib/sdk-mail-0.0.1-plain.jar"))EL PROBLEMA
Cuando lo publico en nuestro repositorio de paquetes y lo importo en la aplicación final como lo haría con cualquier otra biblioteca:
implementation("com.organization:sdk-mail:0.0.1")Se importa correctamente y puedo usar todas las clases durante el desarrollo, pero cuando ejecuto la aplicación encontré dos problemas:
application.yml definidas en la aplicación final (las encuentra cuando ejecuta el jar construido localmente) Aquí la sección de configuración de publicación en build.gradle.kts de la biblioteca:
publishing { repositories { // ... private repository settings } publications { create<MavenPublication>("default") { from(components["java"]) } } }Lo que realmente no entiendo es que, si descargo el jar publicado en el repositorio de paquetes y lo agrego como si lo generara construyendo el proyecto localmente, funciona correctamente. Lo que estoy adivinando es que la versión publicada que descarga gradle tiene algunas dependencias de arranque de primavera o algo así, pero realmente no tengo ni idea.
¿Podría alguien por favor ayudarme con eso?