isortegah / apirest-dropwizard

Api restfull con maven y dropwizard

Home Page:http://api.isortegah.me/swagger

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

APIREST-DROPWIZARD

Indice

Iniciando Proyecto Base

Creacion de proyecto en NetBeans

  • El proyecto parent fue creado en NetBeans con la opción: Maven -> POM Project

alt text

  • Para los modulos se utiliza la opción: Maven -> Java Application

alt text

Arriba

Ajustes en el POM

  • Agregar propiedad de versión de Dropwizard
    <properties>
        <dropwizard.version>INSERT VERSION HERE</dropwizard.version>
    </properties>
  • Adicionar la libreria como dependencia.
<dependencies>
    <dependency>
        <groupId>io.dropwizard</groupId>
        <artifactId>dropwizard-core</artifactId>
        <version>${dropwizard.version}</version>
    </dependency>
</dependencies>

Arriba

Creando la clase de Configuracion

  • Crear clase RestConfiguration.java base:
import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.Configuration;
import org.hibernate.validator.constraints.NotEmpty;
import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;

/**
 *
 * @author ISORTEGAH
 */
public class RestConfiguration extends Configuration{
    @NotEmpty
    @JsonProperty
    private String baseUrl;

    public String getBaseUrl() {
        return baseUrl;
    }

    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }
    
    @JsonProperty("swagger")
    public SwaggerBundleConfiguration swaggerBundleConfiguration;
}

Referencia a ejemplo básico

  • Adicionar al pom.xml del modulo rest la siguiente dependencia:
<dependency>
    <groupId>com.smoketurner</groupId>
    <artifactId>dropwizard-swagger</artifactId>
    <version>1.0.0-rc2-1</version>
</dependency>
  • Contruir el archivo de configuración config.yml
baseUrl: http://localhost
swagger:
    resourcePackage: com.corpfolder.rest.resources
server:
  applicationConnectors:
    - type: http
      port: 8080

Arriba

Crear la clase de la aplicacion

  • Dentro del siguiente código se puede ver la integración de swagger como opción de exposición gráfica de los servicios.
import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import io.federecio.dropwizard.swagger.SwaggerBundle;
import io.federecio.dropwizard.swagger.SwaggerBundleConfiguration;

/**
 *
 * @author ISORTEGAH
 */
public class ApiRestService extends Application<RestConfiguration>{
    
    public static void main(String[] args) throws Exception {
            new ApiRestService().run(args);
    }
    
    @Override
    public void initialize(Bootstrap<RestConfiguration> bootstrap) {
        bootstrap.addBundle(new SwaggerBundle<RestConfiguration>() {
            protected SwaggerBundleConfiguration getSwaggerBundleConfiguration(RestConfiguration configuration) {
                return configuration.swaggerBundleConfiguration;
            }           
        });
    }

    @Override
    public void run(RestConfiguration configuration,
                    Environment environment) {
    }
  • Adicionar healthCheck

Archivo AppHealthCheck.java

public class AppHealthCheck extends HealthCheck {
    @Override
    protected Result check() throws Exception {
        return Result.healthy();
    }

}

Adicionar al archivo ApiRestService.java

@Override
    public void run(RestConfiguration configuration,
                    Environment environment) {
        configFromAws( configuration.getAws() );
        environment.healthChecks().register("app", new AppHealthCheck());
    }

Esto evitara que se muestre el mensaje:

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!    THIS APPLICATION HAS NO HEALTHCHECKS. THIS MEANS YOU WILL NEVER KNOW      !
!     IF IT DIES IN PRODUCTION, WHICH MEANS YOU WILL NEVER KNOW IF YOU'RE      !
!    LETTING YOUR USERS DOWN. YOU SHOULD ADD A HEALTHCHECK FOR EACH OF YOUR    !
!         APPLICATION'S DEPENDENCIES WHICH FULLY (BUT LIGHTLY) TESTS IT.       !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Referencia

Application Health Checks with DropWizard Dropwizard Core

  • Adicionar plugins de contrucción del jar
    <build>
	<plugins>
            <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.17</version>
                    <configuration>
                            <skipTests>true</skipTests>
                    </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.isortegah.rest.ApiRestService</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>1.2.1</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>java</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                            <mainClass>com.isortegah.rest.ApiRestService</mainClass>
                            <arguments>
                                    <argument>server</argument>
                                    <argument>config.yml</argument>
                            </arguments>
                    </configuration>
            </plugin>
        </plugins>
    </build>

Arriba

Crear clase ejemplo

VersionResource.java

import com.codahale.metrics.annotation.Timed;
import com.isortegah.dtos.res.version.VersionDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 *
 * @author ISORTEGAH
 */
@Path("/version")
@Api(value = "/version")
@Produces(MediaType.APPLICATION_JSON)
public class VersionResource {
    @GET
    @Timed
    @ApiOperation(value = "Obtiene la información de la versión", position = 0)
    public VersionDTO version() {
        
       return new VersionDTO();
       
    }
}
  • Adicionar modulo dtos

alt text

  • Crear la clase VersionDTO.java

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 *
 * @author ISORTEGAH
 */
public class VersionDTO {
    
    @JsonProperty
    private String nombre = "Versión 0.0.1-SNAPSHOT";

    @JsonProperty
    private String numero = "0.0.1";
    
    @JsonProperty
    private String autor = "ISORTEGAH";

    public String getAutor() {
        return autor;
    }

    public void setAutor(String autor) {
        this.autor = autor;
    }

    public String getNombre() {
            return nombre;
    }

    public void setNombre(String nombre) {
            this.nombre = nombre;
    }

    public String getNumero() {
            return numero;
    }

    public void setNumero(String numero) {
            this.numero = numero;
    }
    
}
  • Adicionar la dependencia del modulo dtos al pom.xml del modulo rest
<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>dtos</artifactId>
    <version>${project.version}</version>
    <type>jar</type>
</dependency>  
  • Registrar el servicio en ApiRestService.java
@Override
    public void run(RestConfiguration configuration,
                    Environment environment) {
        environment.jersey().register(new VersionResource());
    }

Arriba

Configuracion ejecucion en NetBeans

  • Adicionar Configutarion sobre modulo rest
    Alt Text

  • Registrar la configuración
    Alt Text

  • Seleccionar la opción Run y dentro seleccionar la configuración adicionada con los siguientes parametros:

Main Class: com.isortegah.rest.ApiRestService
Arguments: server config.yml
Alt Text

Arriba

Proceso de dockerizacion

  1. Crear Dockerfile
FROM isortegah/java8:v1


EXPOSE 8080

RUN mkdir -p /app
WORKDIR /app

ADD bootstrap.sh bootstrap.sh
ADD rest/target/rest-0.1-SNAPSHOT.jar rest.jar
ADD config.yml config.yml

ENTRYPOINT ["/bin/bash", "./bootstrap.sh"]
  1. Crear archivo bootstrap.sh
#!/usr/bin/env bash
java -jar rest.jar server config.yml
  1. Construcción de imagen
docker build -t api-rest .
  1. Ejecución de imagen
docker run -it -p 8080:8080 < imagen id >
  1. Ejecutar bash
docker exec -it < id container > /bin/bash
  1. Borrar contenedores finalizados
docker ps -a | egrep Exited | cut -d ' ' -f 1|xargs docker rm
  1. Borrar imagenes < none >
docker images | egrep none | cut -c 41-53| xargs docker rmi

Adicionales

Log4j2

  • Agregar al POM del proyecto la siguiente dependencia:
<dependency> 
    <groupId>org.apache.logging.log4j</groupId> 
    <artifactId>log4j-core</artifactId>
    <version>2.8.2</version> 
</dependency>
  • Agregar el archivo de configuración en la carpeta resource del proyecto, con el nombre log4j.<properties|xml|yaml|json>.

Ejemplos

alt text

  • Código Java
import org.apache.logging.log4j.LogManager; 
import org.apache.logging.log4j.Logger; 

//Ejemplo de declaración de variable 
private static final Logger log = LogManager.getLogger("VersionResource");  

//Ejemplo de implementación
log.info("Se requiere servicio version"); 

Referencias

Log4j Users Guide
Referencia 1
Referencia 2
Referencia 3
Referencia 4
Referencia 5
Referencia 6

Heroku

Pre requisitos

heroku create < nombre app >
  • Establecer buildpack
heroku buildpacks:set heroku/java
  • Establecer stack para despliegue con git
 heroku stack:set heroku-18
  • Establecer stack para despliegue como docker
 heroku stack:set container

Despliege en Heroku

  • Crear archivo `Procfile``
web: java -Ddw.server.applicationConnectors[0].port=$PORT -jar rest/target/rest-0.2.0-SNAPSHOT.jar server config.yml
  • Desplegar app
git push heroku master

Esta aplicación la podemos ver funcionando en api.isortegah.me/swagger Nota: Se encuentra desplegada como contenedor Docker.

Despliegue en heroku como docker

  • Instalar plugin
heroku plugins:install heroku-container-registry
  • Login en contenedor
heroku container:login
  • Push codigo
heroku container:push web
  • Desplegar como docker
heroku container:release web
  • Correr bash en heroku
heroku run bash

Referencia:

Container Registry and Runtime

Push multiple Docker images to Heroku Container Registry

Container Registry and Runtime | Heroku Dev Center

Especificar versión de Java

  • Crear archivo system.properties
"java.runtime.version=1.8" 
  • Verificar la versión de java en Heroku
heroku run java -version

Referencia 1

  • Crear modulo authentication

alt text

alt text

  • Agregar dependencia al pom.xml del modulo authentication
<dependencies>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.2.0</version>
        </dependency>
    </dependencies>
  • Para resolver el problema de ejecución del jar del proyecto se requiere agregar lo siguiente en el pom.xmldel modulo rest.
<filters>
    <filter>
        <artifact>*:*</artifact>
        <excludes>
            <exclude>META-INF/*.SF</exclude>
            <exclude>META-INF/*.DSA</exclude>
            <exclude>META-INF/*.RSA</exclude>
        </excludes>
    </filter>
</filters>
  • Verificar los cambios implementados para la funcionalidad de generar un token simple en GitHub.

Referencia

java-jwt JSON Web Token (JWT)

Aws

  • Crear modulo aws

alt text

alt text

  • Adicionar dependencia a pom.xml
<dependencies>       
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.11.671</version>
        </dependency> 
    </dependencies>
  • Adicionar al archivo config.yml la configuración para aws
aws: 
  credentialProvider: < File|Environment > @Deprecated
  region: <Clave de region aws>

Se depreco el uso de la clase AmazonS3Client y se implemento AmazonS3Client, para revisar la antigua documentación dirijase a la doc aws

Con la implementación de la clase AmazonS3Client, las credenciales para la conexión a aws es man sencilla, ya que toma las credneicales del archivo ~/.aws/credentials si existe, y de lo contrario busca las variables de ambiente.

El archivo credentials debe estar ubicado en el HOME del usuario:

~/.aws/credentials

~/ cat .aws/credentials

[default]
aws_secret_access_key=aaaa
aws_access_key_id=zzzz

Para el caso de las credenciales vía variables de ambiente el proceso es el siguiente:

  • Exportar las variables:
export AWS_ACCESS_KEY_ID="xyz"
export AWS_SECRET_ACCESS_KEY="aaa"

En MacOs y Linux agregarlas en el archivo .bashrc o .bash_profile y recargarlo.

source .bash_profile

Para Windows usar el comando:

set AWS_ACCESS_KEY_ID="xyz"
set AWS_SECRET_ACCESS_KEY="aaa"

Lo anterior para poder ejecutar el comando:

java -jar rest/target/rest-0.1-SNAPSHOT.jar server config.yml
  • En el archivo config.ymlcambiar el valor File por Environment.
aws: 
  credentialProvider: Environment
  region: US_EAST_1

Ejecución

Se presentan las siguientes opciones de ejecución de la imagen docker.

  • De forma directa:
docker run -it -p 8080:8080 -e PORT=8080 -e AWS_ACCESS_KEY_ID=xyzqwd -e AWS_SECRET_ACCESS_KEY=aaa fba5ce1e06db
  • Vía docker-compose:
    • Crear archivo docker-compose.yml
version: '3'
services:
  web:
    image: api-rest
    env_file: 
      - ./.env
    environment: 
      - AMBIENTE="DEV"
    ports: 
      - "8080:8080"
    • Crear archivo .env donde registraremos las variables de ambiente
AWS_ACCESS_KEY_ID=xyz
AWS_SECRET_ACCESS_KEY=aaa

Nota: Lo recomendable por practico y seguro, cuando ejecutemos en local, es usar el docker-compose, en el caso que estemos desarrollando podemos utilizar el archivo de credenciales.

  • Despliege a heroku:

Agregar las variables de ambiente en settings dentro de la app en heroku. alt text

Referencia

Instalacion

Instalación de la AWS CLI con el instalador agregado (Linux, macOS, or Unix)

Credenciales

set Environment Variables aws doc
Working with AWS Credentials Loading Credentials in Node.js from the Shared Credentials File

https://javatutorial.net/java-s3-example http://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html

Docker

Environment variables in Compose

Temas a considerar

Picked up JAVA_TOOL_OPTIONS: -Xmx350m -Xss512k -Dfile.encoding=UTF-8

About

Api restfull con maven y dropwizard

http://api.isortegah.me/swagger


Languages

Language:Java 96.4%Language:Dockerfile 2.2%Language:Shell 1.4%