APIREST-DROPWIZARD
Indice
Iniciando Proyecto Base
- 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
Adicionales
Temas a considerar
Creacion de proyecto en NetBeans
- 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
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. ```xml
[Arriba](#indice)
## Creando la clase de Configuracion
* Crear clase `RestConfiguration.java` base:
```java
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
```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. ```java 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;
- type: http
port: 8080
```
Arriba
/** *
-
@author ISORTEGAH */ public class ApiRestService extends Application
{ public static void main(String[] args) throws Exception { new ApiRestService().run(args); }
@Override public void initialize(Bootstrap
bootstrap) { bootstrap.addBundle(new SwaggerBundle () { 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>
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
- 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()); }
Configuracion ejecucion en NetBeans
-
Adicionar
Configutarion
sobre modulorest
-
Registrar la configuración
- 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
Proceso de dockerizacion
- 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
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 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
Heroku
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](https://devcenter.heroku.com/articles/container-registry-and-runtime) |
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
JWT
- Crear modulo
authentication
- Agregar dependencia al
pom.xml
del moduloauthentication
```xml
* Para resolver el problema de ejecución del `jar` del proyecto se requiere agregar lo siguiente en el `pom.xml`del modulo `rest`.
```xml
<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
Aws
- Crear modulo
aws
- Adicionar dependencia a
pom.xml
```xml
* Adicionar al archivo `config.yml` la configuración para `aws`
```yaml
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
```yml version: ‘3’ services: web: image: api-rest env_file:- ./.env environment:
- AMBIENTE=”DEV” ports:
- “8080:8080” ```
- Crear archivo
-
- 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
.
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