15 - Casos practicos y ejemplos completos

Objetivo del tema

Aplicaras Gradle en proyectos reales: desde un proyecto Java con pruebas hasta un multi-modulo con Spring Boot, una app Android y un flujo de publicacion en Maven Central.

Al finalizar, tendras plantillas para iniciar proyectos end-to-end y adaptar builds a requisitos empresariales.

15.1 Proyecto Java sencillo con dependencias y pruebas

Un proyecto Java clasico incluye dependencias, pruebas unitarias y scripts para ejecutar la aplicacion.

plugins {
  id 'application'
}

repositories {
  mavenCentral()
}

dependencies {
  implementation 'com.google.guava:guava:33.0.0-jre'
  implementation 'org.apache.commons:commons-lang3:3.14.0'
  testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
  testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.10.2'
}

application {
  mainClass = 'com.ejemplo.App'
}

tasks.withType(Test).configureEach {
  useJUnitPlatform()
}

Incluye el bloque repositories { mavenCentral() } para que Gradle resuelva las dependencias. Agrega testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.10.2' para disponer del launcher en tiempo de ejecucion de pruebas. Ejecuta gradle run y gradle test para validar funcionalidad y cobertura basica.

La estructura de directorios sugerida es:

src/
  main/
    java/
      com/
        ejemplo/
          App.java
  test/
    java/
      com/
        ejemplo/
          AppTest.java

App.java contiene el punto de entrada de la aplicacion:

package com.ejemplo;

import com.google.common.base.Joiner;

public class App {
  public static void main(String[] args) {
    String mensaje = Joiner.on(" ").join("Hola", "Gradle", "desde", "un", "proyecto", "Java");
    System.out.println(mensaje);
  }
}

La clase de prueba AppTest.java verifica el comportamiento usando JUnit 5:

package com.ejemplo;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class AppTest {
  @Test
  void mensajePrincipal() {
    String[] argumentos = {};
    App.main(argumentos); // no lanza excepciones
    assertEquals(1, 1, "Prueba basica de sanidad");
  }
}

Ajusta los paquetes y los contenidos segun la logica de tu aplicacion.

Estructura de carpetas de proyecto Gradle

15.2 Proyecto multi-modulo con Spring Boot

Un entorno corporativo puede incluir modulos independientes que comparten logica. Usa settings.gradle para registrar modulos y un build raiz que defina convenciones.

// settings.gradle
rootProject.name = 'plataforma-servicios'
include 'api-rest'
// build.gradle (raiz)
plugins {
  id 'io.spring.dependency-management' version '1.1.6'
}

subprojects {
  apply plugin: 'java'
  apply plugin: 'org.springframework.boot'

  bootJar { enabled = false }
  jar { enabled = true }

  repositories { mavenCentral() }

  dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
  }
}

tasks.register('bootAll') {
  dependsOn subprojects.collect { it.tasks.named('bootJar') }
}

Para cada modulo crea el arbol de directorios dentro de api-rest, servicio-autenticacion y cliente-web. Por ejemplo, el modulo api-rest puede comenzar con:

api-rest/
  src/
    main/
      java/
        com/
          ejemplo/
            api/
              ApiRestApplication.java
    resources/
      application.yml

Contenido basico de ApiRestApplication.java:

package com.ejemplo.api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class ApiRestApplication {
  public static void main(String[] args) {
    SpringApplication.run(ApiRestApplication.class, args);
  }

  @RestController
  static class HelloController {
    @GetMapping("/saludo")
    String saludo() {
      return "Hola desde api-rest";
    }
  }
}

Para pruebas en api-rest, crea src/test/java/com/ejemplo/api/ApiRestApplicationTests.java:

package com.ejemplo.api;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ApiRestApplicationTests {
  @Test
  void contextLoads() {
  }
}

Repite la estructura para servicio-autenticacion y cliente-web, ajustando paquetes y controladores. Por ejemplo, en servicio-autenticacion:

servicio-autenticacion/
  src/
    main/
      java/
        com/
          ejemplo/
            auth/
              ServicioAutenticacionApplication.java
              AuthController.java
    resources/
      application.yml

Contenido basico para autenticacion:

package com.ejemplo.auth;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class ServicioAutenticacionApplication {
  public static void main(String[] args) {
    SpringApplication.run(ServicioAutenticacionApplication.class, args);
  }
}

@RestController
class AuthController {
  @PostMapping("/login")
  AuthResponse login(@RequestBody AuthRequest request) {
    return new AuthResponse(request.username(), true);
  }

  record AuthRequest(String username, String password) {}
  record AuthResponse(String username, boolean authenticated) {}
}

El modulo cliente-web puede exponer una interfaz sencilla:

cliente-web/
  src/
    main/
      java/
        com/
          ejemplo/
            web/
              ClienteWebApplication.java
              ProxyController.java
    resources/
      application.yml

Ejemplo de controlador en cliente web:

package com.ejemplo.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class ClienteWebApplication {
  public static void main(String[] args) {
    SpringApplication.run(ClienteWebApplication.class, args);
  }
}

@RestController
class ProxyController {
  @GetMapping("/ping")
  String ping() {
    return "Cliente web operativo";
  }
}

Finalmente, ejecuta gradle :api-rest:bootRun para iniciar el microservicio de ejemplo y gradle bootAll para construir todos los modulos.

15.3 Proyecto Android con Gradle

Android Studio genera un build basado en Gradle. Ajusta variantes, flavors y tareas de empaquetado segun tus necesidades.

plugins {
  id 'com.android.application'
  id 'org.jetbrains.kotlin.android'
}

android {
  namespace 'com.ejemplo.app'
  compileSdk 35

  defaultConfig {
    applicationId 'com.ejemplo.app'
    minSdk 24
    targetSdk 35
    versionCode 5
    versionName '1.2.0'
  }

  buildTypes {
    release {
      signingConfig signingConfigs.release
      minifyEnabled true
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
  }
}

// Generar APK debug: gradle assembleDebug

Agrega tareas personalizadas (por ejemplo uploadArtifacts) para automatizar la distribucion via Play Store o herramientas internas.

// build.gradle (modulo Android)
tasks.register('uploadArtifacts') {
  group = 'distribucion'
  description = 'Sube el APK generado a un repositorio interno'
  mustRunAfter 'assembleRelease'
  doLast {
    def apk = file('build/outputs/apk/release/app-release.apk')
    if (!apk.exists()) {
      throw new GradleException('El APK release no existe. Ejecuta gradle assembleRelease primero.')
    }
    println "Subiendo ${apk.name} al repositorio interno..."
    // Integrar aqui la API de subida a Play Store o repositorio interno
  }
}

// Ejecutar: gradle assembleRelease uploadArtifacts

15.4 Ejemplo con publicacion en Maven Central

Combina los conceptos de versionado, firma y publicacion para distribuir bibliotecas.

plugins {
  id 'java-library'
  id 'maven-publish'
  id 'signing'
}

version = '1.0.0'

publishing {
  publications {
    create('mavenJava', MavenPublication) {
      from components.java
      artifact tasks.named('javadocJar')
      artifact tasks.named('sourcesJar')
    }
  }
  repositories {
    maven {
      url = uri('https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/')
      credentials {
        username = findProperty('sonatypeUser')
        password = findProperty('sonatypePassword')
      }
    }
  }
}

signing {
  sign publishing.publications['mavenJava']
}

Genera Javadoc y sources con tareas javadocJar y sourcesJar. Ejecuta gradle publish para subir artefactos.

Resumen didactico

Los ejemplos practicos muestran como Gradle se adapta a diferentes escenarios: aplicaciones Java, plataformas multi-modulo, apps Android y librerias publicadas en Maven Central. Reutiliza estas plantillas para iniciar builds robustos en minutos.