SlideShare una empresa de Scribd logo
1 de 37
Descargar para leer sin conexión
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

Más contenido relacionado

Similar a Codemotion 2017 - Taller de JHipster

Similar a 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
 

Más de 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
 

Más de 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
 

Último

Simuladores de circuitos electrónicos.pdf
Simuladores de circuitos electrónicos.pdfSimuladores de circuitos electrónicos.pdf
Simuladores de circuitos electrónicos.pdfLeonardoOa4
 
Virus -Josue Cabascango _20240322_194349_0000.pdf
Virus -Josue Cabascango _20240322_194349_0000.pdfVirus -Josue Cabascango _20240322_194349_0000.pdf
Virus -Josue Cabascango _20240322_194349_0000.pdfMiSpotify
 
Algoritmos Paralelos - Actividad 14 - UNIBE.pdf
Algoritmos Paralelos - Actividad 14 - UNIBE.pdfAlgoritmos Paralelos - Actividad 14 - UNIBE.pdf
Algoritmos Paralelos - Actividad 14 - UNIBE.pdfdarosario3d
 
Formato de práctica reflexiva ante una problemática social.docx.pdf
Formato de práctica reflexiva ante una problemática social.docx.pdfFormato de práctica reflexiva ante una problemática social.docx.pdf
Formato de práctica reflexiva ante una problemática social.docx.pdfjuanrubenc78
 
Diseño de Algoritmos Paralelos. Mejorando la eficiencia computacional aprovec...
Diseño de Algoritmos Paralelos. Mejorando la eficiencia computacional aprovec...Diseño de Algoritmos Paralelos. Mejorando la eficiencia computacional aprovec...
Diseño de Algoritmos Paralelos. Mejorando la eficiencia computacional aprovec...AlexaRamirez39
 
Los mejores simuladores electrónicos que se pueden utilizar
Los mejores simuladores electrónicos que se pueden utilizarLos mejores simuladores electrónicos que se pueden utilizar
Los mejores simuladores electrónicos que se pueden utilizarjosuesj13
 
Herramientas de Mantenimiento_Soporte Técnico_David Andrade.pdf
Herramientas de Mantenimiento_Soporte Técnico_David Andrade.pdfHerramientas de Mantenimiento_Soporte Técnico_David Andrade.pdf
Herramientas de Mantenimiento_Soporte Técnico_David Andrade.pdfdaa100407
 
02 - RUP_Introduccion_Definicion.pdf
02 - RUP_Introduccion_Definicion.pdf02 - RUP_Introduccion_Definicion.pdf
02 - RUP_Introduccion_Definicion.pdfRodrigo Cerón
 
03 - RUP_Elaboracion_Construccion_1_2024.pdf
03 - RUP_Elaboracion_Construccion_1_2024.pdf03 - RUP_Elaboracion_Construccion_1_2024.pdf
03 - RUP_Elaboracion_Construccion_1_2024.pdfRodrigo Cerón
 

Último (9)

Simuladores de circuitos electrónicos.pdf
Simuladores de circuitos electrónicos.pdfSimuladores de circuitos electrónicos.pdf
Simuladores de circuitos electrónicos.pdf
 
Virus -Josue Cabascango _20240322_194349_0000.pdf
Virus -Josue Cabascango _20240322_194349_0000.pdfVirus -Josue Cabascango _20240322_194349_0000.pdf
Virus -Josue Cabascango _20240322_194349_0000.pdf
 
Algoritmos Paralelos - Actividad 14 - UNIBE.pdf
Algoritmos Paralelos - Actividad 14 - UNIBE.pdfAlgoritmos Paralelos - Actividad 14 - UNIBE.pdf
Algoritmos Paralelos - Actividad 14 - UNIBE.pdf
 
Formato de práctica reflexiva ante una problemática social.docx.pdf
Formato de práctica reflexiva ante una problemática social.docx.pdfFormato de práctica reflexiva ante una problemática social.docx.pdf
Formato de práctica reflexiva ante una problemática social.docx.pdf
 
Diseño de Algoritmos Paralelos. Mejorando la eficiencia computacional aprovec...
Diseño de Algoritmos Paralelos. Mejorando la eficiencia computacional aprovec...Diseño de Algoritmos Paralelos. Mejorando la eficiencia computacional aprovec...
Diseño de Algoritmos Paralelos. Mejorando la eficiencia computacional aprovec...
 
Los mejores simuladores electrónicos que se pueden utilizar
Los mejores simuladores electrónicos que se pueden utilizarLos mejores simuladores electrónicos que se pueden utilizar
Los mejores simuladores electrónicos que se pueden utilizar
 
Herramientas de Mantenimiento_Soporte Técnico_David Andrade.pdf
Herramientas de Mantenimiento_Soporte Técnico_David Andrade.pdfHerramientas de Mantenimiento_Soporte Técnico_David Andrade.pdf
Herramientas de Mantenimiento_Soporte Técnico_David Andrade.pdf
 
02 - RUP_Introduccion_Definicion.pdf
02 - RUP_Introduccion_Definicion.pdf02 - RUP_Introduccion_Definicion.pdf
02 - RUP_Introduccion_Definicion.pdf
 
03 - RUP_Elaboracion_Construccion_1_2024.pdf
03 - RUP_Elaboracion_Construccion_1_2024.pdf03 - RUP_Elaboracion_Construccion_1_2024.pdf
03 - RUP_Elaboracion_Construccion_1_2024.pdf
 

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