- Creación de proyecto en NetBeans
- Ajustes en el POM
- Creando la clase de Configuración
- Crear la clase de la aplicación
- Crear clase ejemplo
- Configuración ejecución en NetBeans
- Proceso de dockerizacion
- El proyecto parent fue creado en NetBeans con la opción:
Maven -> POM Project
- Para los modulos se utiliza la opción:
Maven -> Java Application
- 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>
- 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 modulorest
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
- 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
- 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>
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
- 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
alpom.xml
del modulorest
<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());
}
-
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
- 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"]
- Crear archivo
bootstrap.sh
#!/usr/bin/env bash
java -jar rest.jar server config.yml
- Construcción de imagen
docker build -t api-rest .
- Ejecución de imagen
docker run -it -p 8080:8080 < imagen id >
- Ejecutar bash
docker exec -it < id container > /bin/bash
- Borrar contenedores finalizados
docker ps -a | egrep Exited | cut -d ' ' -f 1|xargs docker rm
- Borrar imagenes < none >
docker images | egrep none | cut -c 41-53| xargs docker rmi
- 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 nombrelog4j.<properties|xml|yaml|json>
.
- 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
Pre requisitos
-
Instalación de Heroku Cli
-
Crear app en Heroku
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
- Crear modulo
authentication
- Agregar dependencia al
pom.xml
del moduloauthentication
<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 elpom.xml
del modulorest
.
<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
- Crear modulo
aws
- 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 paraaws
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.yml
cambiar el valorFile
porEnvironment
.
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
- Crear archivo
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
- Crear archivo
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
.
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
Picked up JAVA_TOOL_OPTIONS: -Xmx350m -Xss512k -Dfile.encoding=UTF-8