SlideShare a Scribd company logo
1 of 37
Download to read offline
MAD · NOV 24-25 · 2017
Taller de JHipster
1
Adolfo Sanz de Diego
@asanzdiego
¿Quién soy?
Asesor técnico docente en la
Consejería de Educación de la CAM.
Colaboro como profesor en la UAH y
como formador en Pronoide.
https://about.me/asanzdiego
2
HackathonLovers
Comunidad de desarrolladores,
diseñadores, emprendedores...
...amantes de los hackathones.
http://hackathonlovers.com
3
¿Qué es JHipster?
JHipster es una plataforma de
desarrollo para generar,
desarrollar e implementar
aplicaciones web con
SpringBoot y Angular.
4
Tecnologías Front (I)
- Angular
- Bootstrap
- Sass
- Webpack
5
Tecnologías Front (II)
- Karma
- Protactor
- Brosersync
- Yarn
6
Tecnologías Back (I)
- Spring Boot
- Hibernate
- ElasticSearch
- Gradle
7
Tecnologías Back (II)
- Gatlin
- Cucumber
- Liquibase
- Swagger
8
Ventajas
- Genera una aplicación muy completa.
- Incluye autenticación, i18n, métricas, logs, etc.
- El código generado es bastante bueno.
- Es bastante fácil modificar el código generado.
- Usa un stack bastante probado y conocido.
- Tiene un editor UML muy útil para generar entidades.
- El equipo que hay detrás es muy activo.
- La comunidad que hay detrás es bastante grande.
9
Desventajas
- Conflictos si regeneras una vez modificado el código.
- Conflictos cuando actualizas la versión.
- Tienes que conocer todo el stack para ser productivo.
- Puedes pecar de sobre-ingeniería.
- Algunas cosas no están bien optimizadas (ej. imágenes).
10
Mi experiencia
- Ideal para prototipado de aplicaciones.
- Ideal para aplicaciones CRUD no muy grandes.
- Ideal para equipos de desarrollo pequeños.
- Necesario que los desarrolladores sean full-stack.
- Velocidad de desarrollo alta (al principio).
- Partir de un primer diagrama UML para generar.
- Luego solo añadir entidades por consola.
- Solo actualizar versión para arreglar fallos críticos.
11
Instalación (I)
http://www.jhipster.tech/installation/
Local installation with Yarn (recommended for normal users)
Quick setup when using Angular
12
Instalación (II)
Install Oracle Java 8 (https://www.java.com/es/download/)
Install NodeJS LTS (https://nodejs.org/)
Install Yarn (https://yarnpkg.com/en/docs/install)
$ yarn global add yo
$ yarn global add generator-jhipster
export PATH="$PATH:`yarn global bin`
export PATH="$PATH~/.config/yarn/global/node_modules/.bin
13
Nueva Aplicación
http://www.jhipster.tech/creating-an-app/
$ mkdir myapplication
$ cd myapplication/
$ jhipster
Responder a las preguntas...
$ ./mvnw (o $ ./gradlew) > abrir en el navegador http://localhost:8080
$ yarn start (en otra consola) > abrir en el navegador http://localhost:9000
14
JDL y JDL-Studio
http://www.jhipster.tech/jdl/
http://www.jhipster.tech/jdl-studio/
$ jhipster import-jdl your-jdl-file.jdl
15
JDL-Studio
enum Priority {
HIGH, NORMAL, LOW
}
entity Task {
title String required,
priority Priority required,
user String required,
expirationDate LocalDate
}
entity Category {
title String required,
image ImageBlob
}
relationship OneToMany {
Category{task} to Task{category}
}
paginate Task, Category with pagination
16
Menú administración
- Gestión de usuarios
- Métricas
- Salud
- Configuración
- Auditorías
- Logs
- API
- Base de datos
(en producción algunos están deshabilitados por defecto)
17
Securizar un método del back
./src/main/java/jhipster/web/rest/CategoryResource.java
18
@PostMapping("/categories")
@Timed
@Secured(AuthoritiesConstants.ADMIN)
public ResponseEntity<Category> createCategory(@Valid @RequestBody Category category)
throws URISyntaxException {
log.debug("REST request to save Category : {}", category);
if (category.getId() != null) {
throw new BadRequestAlertException("Cannot already have an ID", ENTITY_NAME, "idexists");
}
Category result = categoryRepository.save(category);
return ResponseEntity.created(new URI("/api/categories/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
Modificar el menú - solo si logueado
19
./src/main/webapp/app/layouts/navbar/navbar.component.html
<li *ngSwitchCase="true" class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
<a class="nav-link" routerLink="task" (click)="collapseNavbar()">
<span>
<i class="fa fa-home" aria-hidden="true"></i>
<span jhiTranslate="global.menu.entities.task">Task</span>
</span>
</a>
</li>
Modificar el menú - solo si admin
20
./src/main/webapp/app/layouts/navbar/navbar.component.html
<li *jhiHasAnyAuthority="'ROLE_ADMIN'" class="nav-item" routerLinkActive="active"
[routerLinkActiveOptions]="{exact: true}">
<a class="nav-link" routerLink="category" (click)="collapseNavbar()">
<span>
<i class="fa fa-home" aria-hidden="true"></i>
<span jhiTranslate="global.menu.entities.category">Category</span>
</span>
</a>
</li>
Internalización
./src/main/webapp/i18n/es/priority.json
21
{
"jhipsterApp": {
"Priority" : {
"null": "",
"HIGH": "ALTA",
"NORMAL": "NORMAL",
"LOW": "BAJA"
}
}
}
Filtrar por usuario - Repository
./src/main/java/codemotion/repository/TaskRepository.java
22
@SuppressWarnings("unused")
@Repository
public interface TaskRepository extends JpaRepository<Task, Long> {
Page<Task> findAllByUser(String usuer, Pageable pageable);
}
Filtrar por usuario - RestControler - createTask
./src/main/java/codemotion/web/rest/TaskResource.java
23
public ResponseEntity<Task> createTask(@Valid @RequestBody Task task) throws URISyntaxException {
log.debug("REST request to save Task : {}", task);
if (task.getId() != null) {
throw new BadRequestAlertException("A new task cannot already have an ID", ENTITY_NAME, "idexists");
}
if (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
task.setUser(SecurityUtils.getCurrentUserLogin());
}
Task result = taskRepository.save(task);
return ResponseEntity.created(new URI("/api/tasks/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
Filtrar por usuario - RestControler - updateTask
./src/main/java/codemotion/web/rest/TaskResource.java
24
public ResponseEntity<Task> updateTask(@Valid @RequestBody Task task) throws URISyntaxException {
if (task.getId() == null) {
return createTask(task);
}
Task taskSaved = taskRepository.findOne(task.getId());
if (taskSaved == null || (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)
&& !SecurityUtils.getCurrentUserLogin().equals(taskSaved.getUser()))) {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
Task result = taskRepository.save(task);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, task.getId().toString()))
.body(result);
}
Filtrar por usuario - Repository - getAllTasks
./src/main/java/codemotion/repository/TaskRepository.java
25
public ResponseEntity<List<Task>> getAllTasks(@ApiParam Pageable pageable) {
log.debug("REST request to get a page of Tasks");
final Page<Task> page;
if (SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) {
page = this.taskRepository.findAll(pageable);
} else {
page = this.taskRepository.findAllByUser(SecurityUtils.getCurrentUserLogin(), pageable);
}
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/tasks");
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
}
Filtrar por usuario - Repository - getTask
./src/main/java/codemotion/repository/TaskRepository.java
26
public ResponseEntity<Task> getTask(@PathVariable Long id) {
log.debug("REST request to get Task : {}", id);
Task task = taskRepository.findOne(id);
if (task == null || (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)
&& !SecurityUtils.getCurrentUserLogin().equals(task.getUser()))) {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
return ResponseUtil.wrapOrNotFound(Optional.ofNullable(task));
}
Filtrar por usuario - Repository - deleteTask
./src/main/java/codemotion/repository/TaskRepository.java
27
public ResponseEntity<Void> deleteTask(@PathVariable Long id) {
log.debug("REST request to delete Task : {}", id);
Task taskSaved = taskRepository.findOne(id);
if (taskSaved == null || (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)
&& !SecurityUtils.getCurrentUserLogin().equals(taskSaved.getUser()))) {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
taskRepository.delete(id);
return ResponseEntity.ok()
.headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build();
}
Filtrar por usuario - Component - ts
./src/main/webapp/app/entities/task/task-dialog.component.ts
28
constructor(
...
private principal: Principal
) { }
ngOnInit() {
this.principal.identity().then((account) => {
this.task.user = account.login;
});
...
}
Filtrar por usuario - Component - html
./src/main/webapp/app/entities/task/task-dialog.component.html
29
<div *jhiHasAnyAuthority="'ROLE_ADMIN'" class="form-group">
<label class="form-control-label" jhiTranslate="codemotionApp.task.user" for="field_user">User</label>
<input type="text" class="form-control" name="user" id="field_user"
[(ngModel)]="task.user" required />
<div [hidden]="!(editForm.controls.user?.dirty && editForm.controls.user?.invalid)">
<small class="form-text text-danger"
[hidden]="!editForm.controls.user?.errors?.required" jhiTranslate="entity.validation.required">
This field is required.
</small>
</div>
</div>
Cambiar id por nombre categoría - Component - html
./src/main/webapp/app/entities/task/task-dialog.component.html
30
<div class="form-group">
<label class="form-control-label" jhiTranslate="codemotionApp.task.category"
for="field_category">Category</label>
<select class="form-control" id="field_category" name="category" [(ngModel)]="task.category" >
<option [ngValue]="null"></option>
<option [ngValue]="categoryOption.id === task.category?.id ? task.category : categoryOption"
*ngFor="let categoryOption of categories; trackBy: trackCategoryById">{{categoryOption.title}}</option>
</select>
</div>
Cambiar color según prioridad - Component - ts
./src/main/webapp/app/entities/task/task.component.ts
31
getTrClassFromTask(task: Task) {
if (task.priority.toString() === 'HIGH') {
return 'table-danger';
} else if (task.priority.toString() === 'NORMAL') {
return 'table-warning';
} else if (task.priority.toString() === 'LOW') {
return 'table-success';
}
return '';
}
Cambiar color según prioridad - Component - html
./src/main/webapp/app/entities/task/task.component.html
32
<tr *ngFor="let task of tasks ;trackBy: trackId" class="{{getTrClassFromTask(task)}}">
<td><a [routerLink]="['../task', task.id ]">{{task.id}}</a></td>
<td>{{task.title}}</td>
<td jhiTranslate="{{'codemotionApp.Priority.' + task.priority}}">{{task.priority}}</td>
<td>{{task.user}}</td>
<td>{{task.expirationDate | date:'mediumDate'}}</td>
<td>
<div *ngIf="task.category">
<a [routerLink]="['../category', task.category?.id ]" >{{task.category?.title}}</a>
</div>
</td>
Subida a producción
./src/main/resources/config/application-prod.yml
33
$./mvnw -Pprod clean package
Código del taller
https://github.com/asanzdiego/codemotion-2017-taller-de-jhipster
34
Feedback
http://bit.ly/codemotion2017-taller
35
Licencia
Esta obra tiene una licencia:
CreativeCommons-Reconocimiento-CompartirIgual
36
MAD · NOV 24-25 · 2017
¡Gracias!
37

More Related Content

Similar to Codemotion 2017 - Taller de JHipster

Similar to Codemotion 2017 - Taller de JHipster (20)

Presentacion YII
Presentacion YIIPresentacion YII
Presentacion YII
 
JSDays Desarrolla tu primera API
JSDays Desarrolla tu primera APIJSDays Desarrolla tu primera API
JSDays Desarrolla tu primera API
 
Taller Práctico de Android
Taller Práctico de AndroidTaller Práctico de Android
Taller Práctico de Android
 
Progressive Web Apps
Progressive Web AppsProgressive Web Apps
Progressive Web Apps
 
Segundo laboratorio de Android
Segundo laboratorio de AndroidSegundo laboratorio de Android
Segundo laboratorio de Android
 
Introducción a NodeJS
Introducción a NodeJSIntroducción a NodeJS
Introducción a NodeJS
 
Gwt II - trabajando con gwt
Gwt II - trabajando con gwtGwt II - trabajando con gwt
Gwt II - trabajando con gwt
 
Presentacion #bbmnk
Presentacion #bbmnkPresentacion #bbmnk
Presentacion #bbmnk
 
Web Mapping con Django
Web Mapping con DjangoWeb Mapping con Django
Web Mapping con Django
 
Introducción a AngularJS
Introducción a AngularJS Introducción a AngularJS
Introducción a AngularJS
 
JQuery
JQueryJQuery
JQuery
 
Django
DjangoDjango
Django
 
(Muy breve) Introduccion a jQuery
(Muy breve) Introduccion a jQuery(Muy breve) Introduccion a jQuery
(Muy breve) Introduccion a jQuery
 
Prueba De Aplicaciones Web con Selenium 2 y WebDriver
Prueba De Aplicaciones Web con Selenium 2 y WebDriverPrueba De Aplicaciones Web con Selenium 2 y WebDriver
Prueba De Aplicaciones Web con Selenium 2 y WebDriver
 
Un atlas en la palma de la mano
Un atlas en la palma de la manoUn atlas en la palma de la mano
Un atlas en la palma de la mano
 
Webpack desde cero
Webpack desde ceroWebpack desde cero
Webpack desde cero
 
Manual compilacion de java en dos
Manual compilacion de java en dosManual compilacion de java en dos
Manual compilacion de java en dos
 
Manual compilacion de java en dos
Manual compilacion de java en dosManual compilacion de java en dos
Manual compilacion de java en dos
 
Introduccion a Android
Introduccion a AndroidIntroduccion a Android
Introduccion a Android
 
Cross development - React para desarrolladores de asp.net
Cross development - React para desarrolladores de asp.netCross development - React para desarrolladores de asp.net
Cross development - React para desarrolladores de asp.net
 

More from Adolfo Sanz De Diego

De 0 a 100 con Bash Shell Scripting y AWK
De 0 a 100 con Bash Shell Scripting y AWKDe 0 a 100 con Bash Shell Scripting y AWK
De 0 a 100 con Bash Shell Scripting y AWKAdolfo Sanz De Diego
 
Desarrollo de aplicaciones descentralizadas en la Blockchain de Ethereum
Desarrollo de aplicaciones descentralizadas en la Blockchain de EthereumDesarrollo de aplicaciones descentralizadas en la Blockchain de Ethereum
Desarrollo de aplicaciones descentralizadas en la Blockchain de EthereumAdolfo Sanz De Diego
 
Codemotion 2017 - La Revolución del Software Libre
Codemotion 2017 - La Revolución del Software LibreCodemotion 2017 - La Revolución del Software Libre
Codemotion 2017 - La Revolución del Software LibreAdolfo Sanz De Diego
 
Open Expo 2017 - La Revolución del Software Libre
Open Expo 2017 - La Revolución del Software LibreOpen Expo 2017 - La Revolución del Software Libre
Open Expo 2017 - La Revolución del Software LibreAdolfo Sanz De Diego
 
JustiApps #hackTheJustice - Y si quiero desarrollar mi propia app, ¿qué debo ...
JustiApps #hackTheJustice - Y si quiero desarrollar mi propia app, ¿qué debo ...JustiApps #hackTheJustice - Y si quiero desarrollar mi propia app, ¿qué debo ...
JustiApps #hackTheJustice - Y si quiero desarrollar mi propia app, ¿qué debo ...Adolfo Sanz De Diego
 
¿Qué es un hackathon y por qué deberías asistir?
¿Qué es un hackathon y por qué deberías asistir?¿Qué es un hackathon y por qué deberías asistir?
¿Qué es un hackathon y por qué deberías asistir?Adolfo Sanz De Diego
 
Nuestro primer HackLab -We want you for HackthonLovers #wantu4hl
Nuestro primer HackLab -We want you for HackthonLovers #wantu4hlNuestro primer HackLab -We want you for HackthonLovers #wantu4hl
Nuestro primer HackLab -We want you for HackthonLovers #wantu4hlAdolfo Sanz De Diego
 

More from Adolfo Sanz De Diego (20)

Redes
RedesRedes
Redes
 
Computación
ComputaciónComputación
Computación
 
Angular
AngularAngular
Angular
 
TypeScript
TypeScriptTypeScript
TypeScript
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Java 8
Java 8Java 8
Java 8
 
De 0 a 100 con Bash Shell Scripting y AWK
De 0 a 100 con Bash Shell Scripting y AWKDe 0 a 100 con Bash Shell Scripting y AWK
De 0 a 100 con Bash Shell Scripting y AWK
 
Desarrollo de aplicaciones descentralizadas en la Blockchain de Ethereum
Desarrollo de aplicaciones descentralizadas en la Blockchain de EthereumDesarrollo de aplicaciones descentralizadas en la Blockchain de Ethereum
Desarrollo de aplicaciones descentralizadas en la Blockchain de Ethereum
 
JavaScript
JavaScriptJavaScript
JavaScript
 
Codemotion 2017 - La Revolución del Software Libre
Codemotion 2017 - La Revolución del Software LibreCodemotion 2017 - La Revolución del Software Libre
Codemotion 2017 - La Revolución del Software Libre
 
Git, Github y Markdown
Git, Github y MarkdownGit, Github y Markdown
Git, Github y Markdown
 
Open Expo 2017 - La Revolución del Software Libre
Open Expo 2017 - La Revolución del Software LibreOpen Expo 2017 - La Revolución del Software Libre
Open Expo 2017 - La Revolución del Software Libre
 
JustiApps #hackTheJustice - Y si quiero desarrollar mi propia app, ¿qué debo ...
JustiApps #hackTheJustice - Y si quiero desarrollar mi propia app, ¿qué debo ...JustiApps #hackTheJustice - Y si quiero desarrollar mi propia app, ¿qué debo ...
JustiApps #hackTheJustice - Y si quiero desarrollar mi propia app, ¿qué debo ...
 
¿Qué es un hackathon y por qué deberías asistir?
¿Qué es un hackathon y por qué deberías asistir?¿Qué es un hackathon y por qué deberías asistir?
¿Qué es un hackathon y por qué deberías asistir?
 
Codemotion 2016 - Hackathones 101
Codemotion 2016 - Hackathones 101Codemotion 2016 - Hackathones 101
Codemotion 2016 - Hackathones 101
 
Hackeando el #psd2Hackathon
Hackeando el #psd2HackathonHackeando el #psd2Hackathon
Hackeando el #psd2Hackathon
 
Open Expo 2016 - Ética Hacker
Open Expo 2016 - Ética HackerOpen Expo 2016 - Ética Hacker
Open Expo 2016 - Ética Hacker
 
Nuestro primer HackLab -We want you for HackthonLovers #wantu4hl
Nuestro primer HackLab -We want you for HackthonLovers #wantu4hlNuestro primer HackLab -We want you for HackthonLovers #wantu4hl
Nuestro primer HackLab -We want you for HackthonLovers #wantu4hl
 
T3chFest - 2016 - Ética Hacker
T3chFest - 2016 - Ética HackerT3chFest - 2016 - Ética Hacker
T3chFest - 2016 - Ética Hacker
 
Git, GitHub y Markdown
Git, GitHub y MarkdownGit, GitHub y Markdown
Git, GitHub y Markdown
 

Recently uploaded

ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...Neo4j
 
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...FabianCruz73
 
Tipos de pensamiento y pensamiento lógico
Tipos de pensamiento y pensamiento lógicoTipos de pensamiento y pensamiento lógico
Tipos de pensamiento y pensamiento lógicoMaxCaldern2
 
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxMacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxcalzadillasluis134
 
Delitos informáticos en Slideshare.pptx
Delitos informáticos en  Slideshare.pptxDelitos informáticos en  Slideshare.pptx
Delitos informáticos en Slideshare.pptxmaykolmagallanes012
 
Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.CZSOTEC
 
Webinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfWebinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfAnaRosaMontenegro
 
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Neo4j
 
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOSISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOELIAMARYTOVARFLOREZD
 
SQL server Analysis Services & SQL Server Reporting Services.pptx
SQL server Analysis Services & SQL Server Reporting Services.pptxSQL server Analysis Services & SQL Server Reporting Services.pptx
SQL server Analysis Services & SQL Server Reporting Services.pptxRAMIROANTONIOGALINDO
 
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosBBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosNeo4j
 

Recently uploaded (11)

ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
 
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
Estructura del lenguaje c++. Operaciones básicas y su jerarquía aplicada en e...
 
Tipos de pensamiento y pensamiento lógico
Tipos de pensamiento y pensamiento lógicoTipos de pensamiento y pensamiento lógico
Tipos de pensamiento y pensamiento lógico
 
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptxMacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
MacOS SISTEMA OPERATIVO CARACTERISTICAS.pptx
 
Delitos informáticos en Slideshare.pptx
Delitos informáticos en  Slideshare.pptxDelitos informáticos en  Slideshare.pptx
Delitos informáticos en Slideshare.pptx
 
Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.Instalacion de servicios windows, configuracion y aplicacion.
Instalacion de servicios windows, configuracion y aplicacion.
 
Webinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdfWebinar Resolucion2335 de 2023 Kubapp.pdf
Webinar Resolucion2335 de 2023 Kubapp.pdf
 
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
Graph Everywhere - Josep Taruella - Por qué Graph Data Science en tus modelos...
 
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVOSISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
SISTEMA INTEGRADO DE ADMINISTRACION FINANCIERA - SIAF MODULO ADMINISTRATIVO
 
SQL server Analysis Services & SQL Server Reporting Services.pptx
SQL server Analysis Services & SQL Server Reporting Services.pptxSQL server Analysis Services & SQL Server Reporting Services.pptx
SQL server Analysis Services & SQL Server Reporting Services.pptx
 
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafosBBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
BBVA - GraphSummit Madrid - Caso de éxito en BBVA: Optimizando con grafos
 

Codemotion 2017 - Taller de JHipster

  • 1. MAD · NOV 24-25 · 2017 Taller de JHipster 1 Adolfo Sanz de Diego @asanzdiego
  • 2. ¿Quién soy? Asesor técnico docente en la Consejería de Educación de la CAM. Colaboro como profesor en la UAH y como formador en Pronoide. https://about.me/asanzdiego 2
  • 3. HackathonLovers Comunidad de desarrolladores, diseñadores, emprendedores... ...amantes de los hackathones. http://hackathonlovers.com 3
  • 4. ¿Qué es JHipster? JHipster es una plataforma de desarrollo para generar, desarrollar e implementar aplicaciones web con SpringBoot y Angular. 4
  • 5. Tecnologías Front (I) - Angular - Bootstrap - Sass - Webpack 5
  • 6. Tecnologías Front (II) - Karma - Protactor - Brosersync - Yarn 6
  • 7. Tecnologías Back (I) - Spring Boot - Hibernate - ElasticSearch - Gradle 7
  • 8. Tecnologías Back (II) - Gatlin - Cucumber - Liquibase - Swagger 8
  • 9. Ventajas - Genera una aplicación muy completa. - Incluye autenticación, i18n, métricas, logs, etc. - El código generado es bastante bueno. - Es bastante fácil modificar el código generado. - Usa un stack bastante probado y conocido. - Tiene un editor UML muy útil para generar entidades. - El equipo que hay detrás es muy activo. - La comunidad que hay detrás es bastante grande. 9
  • 10. Desventajas - Conflictos si regeneras una vez modificado el código. - Conflictos cuando actualizas la versión. - Tienes que conocer todo el stack para ser productivo. - Puedes pecar de sobre-ingeniería. - Algunas cosas no están bien optimizadas (ej. imágenes). 10
  • 11. Mi experiencia - Ideal para prototipado de aplicaciones. - Ideal para aplicaciones CRUD no muy grandes. - Ideal para equipos de desarrollo pequeños. - Necesario que los desarrolladores sean full-stack. - Velocidad de desarrollo alta (al principio). - Partir de un primer diagrama UML para generar. - Luego solo añadir entidades por consola. - Solo actualizar versión para arreglar fallos críticos. 11
  • 12. Instalación (I) http://www.jhipster.tech/installation/ Local installation with Yarn (recommended for normal users) Quick setup when using Angular 12
  • 13. Instalación (II) Install Oracle Java 8 (https://www.java.com/es/download/) Install NodeJS LTS (https://nodejs.org/) Install Yarn (https://yarnpkg.com/en/docs/install) $ yarn global add yo $ yarn global add generator-jhipster export PATH="$PATH:`yarn global bin` export PATH="$PATH~/.config/yarn/global/node_modules/.bin 13
  • 14. Nueva Aplicación http://www.jhipster.tech/creating-an-app/ $ mkdir myapplication $ cd myapplication/ $ jhipster Responder a las preguntas... $ ./mvnw (o $ ./gradlew) > abrir en el navegador http://localhost:8080 $ yarn start (en otra consola) > abrir en el navegador http://localhost:9000 14
  • 16. JDL-Studio enum Priority { HIGH, NORMAL, LOW } entity Task { title String required, priority Priority required, user String required, expirationDate LocalDate } entity Category { title String required, image ImageBlob } relationship OneToMany { Category{task} to Task{category} } paginate Task, Category with pagination 16
  • 17. Menú administración - Gestión de usuarios - Métricas - Salud - Configuración - Auditorías - Logs - API - Base de datos (en producción algunos están deshabilitados por defecto) 17
  • 18. Securizar un método del back ./src/main/java/jhipster/web/rest/CategoryResource.java 18 @PostMapping("/categories") @Timed @Secured(AuthoritiesConstants.ADMIN) public ResponseEntity<Category> createCategory(@Valid @RequestBody Category category) throws URISyntaxException { log.debug("REST request to save Category : {}", category); if (category.getId() != null) { throw new BadRequestAlertException("Cannot already have an ID", ENTITY_NAME, "idexists"); } Category result = categoryRepository.save(category); return ResponseEntity.created(new URI("/api/categories/" + result.getId())) .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString())) .body(result); }
  • 19. Modificar el menú - solo si logueado 19 ./src/main/webapp/app/layouts/navbar/navbar.component.html <li *ngSwitchCase="true" class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}"> <a class="nav-link" routerLink="task" (click)="collapseNavbar()"> <span> <i class="fa fa-home" aria-hidden="true"></i> <span jhiTranslate="global.menu.entities.task">Task</span> </span> </a> </li>
  • 20. Modificar el menú - solo si admin 20 ./src/main/webapp/app/layouts/navbar/navbar.component.html <li *jhiHasAnyAuthority="'ROLE_ADMIN'" class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}"> <a class="nav-link" routerLink="category" (click)="collapseNavbar()"> <span> <i class="fa fa-home" aria-hidden="true"></i> <span jhiTranslate="global.menu.entities.category">Category</span> </span> </a> </li>
  • 21. Internalización ./src/main/webapp/i18n/es/priority.json 21 { "jhipsterApp": { "Priority" : { "null": "", "HIGH": "ALTA", "NORMAL": "NORMAL", "LOW": "BAJA" } } }
  • 22. Filtrar por usuario - Repository ./src/main/java/codemotion/repository/TaskRepository.java 22 @SuppressWarnings("unused") @Repository public interface TaskRepository extends JpaRepository<Task, Long> { Page<Task> findAllByUser(String usuer, Pageable pageable); }
  • 23. Filtrar por usuario - RestControler - createTask ./src/main/java/codemotion/web/rest/TaskResource.java 23 public ResponseEntity<Task> createTask(@Valid @RequestBody Task task) throws URISyntaxException { log.debug("REST request to save Task : {}", task); if (task.getId() != null) { throw new BadRequestAlertException("A new task cannot already have an ID", ENTITY_NAME, "idexists"); } if (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) { task.setUser(SecurityUtils.getCurrentUserLogin()); } Task result = taskRepository.save(task); return ResponseEntity.created(new URI("/api/tasks/" + result.getId())) .headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString())) .body(result); }
  • 24. Filtrar por usuario - RestControler - updateTask ./src/main/java/codemotion/web/rest/TaskResource.java 24 public ResponseEntity<Task> updateTask(@Valid @RequestBody Task task) throws URISyntaxException { if (task.getId() == null) { return createTask(task); } Task taskSaved = taskRepository.findOne(task.getId()); if (taskSaved == null || (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN) && !SecurityUtils.getCurrentUserLogin().equals(taskSaved.getUser()))) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } Task result = taskRepository.save(task); return ResponseEntity.ok() .headers(HeaderUtil.createEntityUpdateAlert(ENTITY_NAME, task.getId().toString())) .body(result); }
  • 25. Filtrar por usuario - Repository - getAllTasks ./src/main/java/codemotion/repository/TaskRepository.java 25 public ResponseEntity<List<Task>> getAllTasks(@ApiParam Pageable pageable) { log.debug("REST request to get a page of Tasks"); final Page<Task> page; if (SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)) { page = this.taskRepository.findAll(pageable); } else { page = this.taskRepository.findAllByUser(SecurityUtils.getCurrentUserLogin(), pageable); } HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/tasks"); return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK); }
  • 26. Filtrar por usuario - Repository - getTask ./src/main/java/codemotion/repository/TaskRepository.java 26 public ResponseEntity<Task> getTask(@PathVariable Long id) { log.debug("REST request to get Task : {}", id); Task task = taskRepository.findOne(id); if (task == null || (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN) && !SecurityUtils.getCurrentUserLogin().equals(task.getUser()))) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } return ResponseUtil.wrapOrNotFound(Optional.ofNullable(task)); }
  • 27. Filtrar por usuario - Repository - deleteTask ./src/main/java/codemotion/repository/TaskRepository.java 27 public ResponseEntity<Void> deleteTask(@PathVariable Long id) { log.debug("REST request to delete Task : {}", id); Task taskSaved = taskRepository.findOne(id); if (taskSaved == null || (!SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN) && !SecurityUtils.getCurrentUserLogin().equals(taskSaved.getUser()))) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } taskRepository.delete(id); return ResponseEntity.ok() .headers(HeaderUtil.createEntityDeletionAlert(ENTITY_NAME, id.toString())).build(); }
  • 28. Filtrar por usuario - Component - ts ./src/main/webapp/app/entities/task/task-dialog.component.ts 28 constructor( ... private principal: Principal ) { } ngOnInit() { this.principal.identity().then((account) => { this.task.user = account.login; }); ... }
  • 29. Filtrar por usuario - Component - html ./src/main/webapp/app/entities/task/task-dialog.component.html 29 <div *jhiHasAnyAuthority="'ROLE_ADMIN'" class="form-group"> <label class="form-control-label" jhiTranslate="codemotionApp.task.user" for="field_user">User</label> <input type="text" class="form-control" name="user" id="field_user" [(ngModel)]="task.user" required /> <div [hidden]="!(editForm.controls.user?.dirty && editForm.controls.user?.invalid)"> <small class="form-text text-danger" [hidden]="!editForm.controls.user?.errors?.required" jhiTranslate="entity.validation.required"> This field is required. </small> </div> </div>
  • 30. Cambiar id por nombre categoría - Component - html ./src/main/webapp/app/entities/task/task-dialog.component.html 30 <div class="form-group"> <label class="form-control-label" jhiTranslate="codemotionApp.task.category" for="field_category">Category</label> <select class="form-control" id="field_category" name="category" [(ngModel)]="task.category" > <option [ngValue]="null"></option> <option [ngValue]="categoryOption.id === task.category?.id ? task.category : categoryOption" *ngFor="let categoryOption of categories; trackBy: trackCategoryById">{{categoryOption.title}}</option> </select> </div>
  • 31. Cambiar color según prioridad - Component - ts ./src/main/webapp/app/entities/task/task.component.ts 31 getTrClassFromTask(task: Task) { if (task.priority.toString() === 'HIGH') { return 'table-danger'; } else if (task.priority.toString() === 'NORMAL') { return 'table-warning'; } else if (task.priority.toString() === 'LOW') { return 'table-success'; } return ''; }
  • 32. Cambiar color según prioridad - Component - html ./src/main/webapp/app/entities/task/task.component.html 32 <tr *ngFor="let task of tasks ;trackBy: trackId" class="{{getTrClassFromTask(task)}}"> <td><a [routerLink]="['../task', task.id ]">{{task.id}}</a></td> <td>{{task.title}}</td> <td jhiTranslate="{{'codemotionApp.Priority.' + task.priority}}">{{task.priority}}</td> <td>{{task.user}}</td> <td>{{task.expirationDate | date:'mediumDate'}}</td> <td> <div *ngIf="task.category"> <a [routerLink]="['../category', task.category?.id ]" >{{task.category?.title}}</a> </div> </td>
  • 36. Licencia Esta obra tiene una licencia: CreativeCommons-Reconocimiento-CompartirIgual 36
  • 37. MAD · NOV 24-25 · 2017 ¡Gracias! 37