JHipster

II parte: Uno sguardo dietro le quintedi e e

Introduzione

In questo articolo daremo una sguardo a cosa genera JHipster sia lato server che lato client. Analizzeremo il codice generato per l’applicazione “monolitica” di esempio jhmoka [1]. Si ricorda che JHipster è in grado di creare applicazioni sia tradizionali three tier, cosiddette “monolitiche”, sia applicazioni microservices.

Infatti la prima domanda che JHipster chiede in fase di generazione è il tipo di applicazione che si desidera creare dando la possibilità di scegliere tra due stili di architettura:

  • architettura "monolitica" (Monolithic application) che è l’opzione di default “one-size- fits-all” e contiene sia il codice AngularJS front-end che back-end in un unico progetto maven;
  • architettura a "microservizi" (Microservice application) che divide il front-end e back-end mediante un gateway (Microservice gateway) in modo che sia più facile scalare su infrastrutture distribuite.

 

Server side

Iniziamo adesso a vedere cosa JHipster genera dietro le quinte partendo dalla parte server.

Figura 1 – Tecnologie JHipster server-side

Figura 1 – Tecnologie JHipster server-side

 

La configurazione di base di JHipster realizza una web application con le impostazioni server side utilizzando la configurazione di Spring Boot, e client side con la configurazione AngularJS.

Figura 2 – Overview class diagram server-side jhmoka

Figura 2 – Overview class diagram server-side jhmoka

 

La tecnologia lato server di base, realizzata automaticamente nella Jhipster webapp, utilizza principalmente la convention over configuration di Spring Boot. La struttura dei package rispetta, infatti, quella richiesta da Spring Boot per una più semplice configurazione della webapp, così come la struttura delle cartelle per i file di configurazione non Java [9].

JHipster usa i più famosi moduli Spring come Spring Security, Spring Data JPA e Spring MVC. JHipster inoltre imposta tutta la gestione del database tramite Liquibase che è una libreria per la gestione e il versioning di un database [10]. La libreria utilizzata per standardizzare le API REST è Swagger, una libreria che permette di uniformare la documentazione delle API e renderle fruibili [8].

 

Classi di startup

Come una classica configurazione di Spring Boot, JHipster realizza il package di default inserito da riga di comando (nel nostro caso: it.mokabyte.jhmoka) e crea due classi per lo start dell’applicazione: JhmokaApp e ApplicationWebXml.

JhmokaApp

JhmokaApp è la classe per lo start dell’applicazione come Java stand alone.

@ComponentScan
 @EnableAutoConfiguration(exclude
 = { MetricFilterAutoConfiguration.class,MetricRepositoryAutoConfiguration.class })
 @EnableConfigurationProperties({ JHipsterProperties.class, LiquibaseProperties.class })
 public class JhmokaApp {
 . . . . .
 public static void main(String[] args) throws UnknownHostException {
  SpringApplication app = new SpringApplication(JhmokaApp.class);
  DefaultProfileUtil.addDefaultProfile(app);
 Environment env = app.run(args).getEnvironment();
 }
}

ApplicationWebXml

ApplicationWebXml è classe per lo start dell’applicazione come WAR deployato in un Java EE container.

package it.mokabyte.jhmoka;
public class ApplicationWebXml extends SpringBootServletInitializer {
 @Override
 protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
  DefaultProfileUtil.addDefaultProfile(application.application());
  return application.sources(JhmokaApp.class);
 }
}
Figura 3 – Classi di startup dell’applicazione jhmoka

Figura 3 – Classi di startup dell’applicazione jhmoka

 

Il package domain e repository

Nel package domain, ci sono le entities che saranno utilizzati dall’applicazione.

Figura 4 – Classi di dominio Author e AuthorRepository dell’applicazione jhmoka.

Figura 4 – Classi di dominio Author e AuthorRepository dell’applicazione jhmoka.

 

L’entity su cui si basa jhmoka è l’entity Author di classe it.mokabyte.jhmoka.domain.Author; è l’Entity Bean generato da JHipster a fronte del comando da console [1].

yo jhipster:entity Author
 package it.mokabyte.jhmoka.domain;
 . . .
 /**
 * A Author.
 */
 @Entity
 @Table(name = "author")
 @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
 public class Author implements Serializable {
  private static final long serialVersionUID = 1L;
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  . . .
  @NotNull
  @Size(min = 3)
  @Pattern(regexp = "^\\w+@[a-zA-Z_]+?\\.[a-zA-Z]{2,3}$")
  @Column(name = "email", nullable = false)
  private String email;
  . . .
  public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 @Override
 public boolean equals(Object o) {
 . . .
 }
}

La classe AuthorRepository è il relativo Repository Hibernate.

 

I servizi

Le classi per la logica di business già presenti nell’applicazione di base sono indicate nella figura che segue.

Figura 5 – Classi dei servizi dell’applicazione jhmoka

Figura 5 – Classi dei servizi dell’applicazione jhmoka

 

L’interfaccia it.mokabyte.jhmoka.service.AuthorService espone i metodi CRUD (Create, Read, Update, Delete) che saranno implementati dalla classe concreta it.mokabyte.jhmoka.service.impl.AuthorServiceImpl

package it.mokabyte.jhmoka.service;
/**
 * Service Interface for managing Author.
 */
 public interface AuthorService {
  /**
  * Save a author.
  * @param author the entity to save
  * @return the persisted entity
  */
  Author save(Author author);
  /**
  * Get all the authors.
  * @param pageable the pagination information
  * @return the list of entities
  */
  Page<Author> findAll(Pageable pageable);
 /**
  * Get the "id" author.
  *
  * @param id the id of the entity
  * @return the entity
  */
  Author findOne(Long id);
 /**
  * Delete the "id" author.
  *
  * @param id the id of the entity
  */
  void delete(Long id);
}

 

I controller rest

Nei package rest ci sono le API implementate tramite i Rest Controller di Spring. Questi sono utilizzati dai controller Angular per ottenere le informazioni di back end dallo strato dei servizi. Il Controller Rest core di jhmoka è it.mokabyte.jhmoka.web.rest.AuthorResource.

Figura 6 – Package dei servizi REST dell’applicazione jhmoka

Figura 6 – Package dei servizi REST dell’applicazione jhmoka

 

Client side

Proseguiamo ora con la descrizione della parte client.

Figura 7 – Tecnologie JHipster client-side

Figura 7 – Tecnologie JHipster client-side

 

Struttura delle cartelle

JHipster , seguendo il pattern di AngularJS, imposta la struttura delle cartelle client side molto ben organizzata e consente una facile lettura e manutenzione.

Figura 8 – Dettaglio della cartella webapp dell’applicazione jhmoka

Figura 8 – Dettaglio della cartella webapp dell’applicazione jhmoka

 

Nella cartella root, troviamo già i file utili per la struttura di base di una web application:

  • html: layout per gestire il messaggio di pagina non trovata.
  • ico: l’icona da associare all’applicazione web.
  • txt: il file per definire cosa indicizzare per i motori di ricerca.
  • index.html: la pagina iniziale con tutti gli import javascript/css e le configurazioni di base per caricare la GUI secondo il pattern AngularJS. All’interno di questa pagina è presente uno script utile all’abilitazione degli strumenti Google Analytics. Lo script risulta commentato di default.

Oltre ai file sopra citati è presente la seguente struttura di cartelle:

  • app: con le sottocartelle e i file per la realizzazione della struttura javascript/html secondo il pattern di AngularJS (approfondiremo meglio nel paragrafo successivo).
  • bower_components: la cartella contenente le librerie javascript di terze parti.
  • content: con le immagini e i file css.
  • i18n: contenente i file di properties nelle varie lingue scelte.
  • swagger-ui: la cartella con i file necessari per la renderizzazione della documentazione delle API.

 

AngularJS

JHipster usa AngularJS come framework JavaScript di riferimento per lo sviluppo della User Interface che è uno dei più famosi framework JavaScript open source utilizzato per la realizzazione di single page application. AngularJS utilizza il pattern MVC all’interno di una pagina web tramite controller e services javascript e invocando i servizi REST di back end [12]. AngularJS è molto famoso nella community web e dispone di una vasta scelta di plugin.

JHipster adotta alcuni dei plugin più famosi già nella configurazione di base; ad esempio Angular UI Router usato per semplificare l’architettura di AngularJS e la gestione della navigazione tra le pagine web [13].

Nell’immagine successiva, un esempio di come avviene il routing dalla homepage alla pagina degli autori, passando dal link Author presente nel menù sotto la voce Entities.

Figura 9 – Overview del funzionamento della parte client jhmoka

Figura 9 – Overview del funzionamento della parte client jhmoka

 

Il link Author è definito all’interno del file navbar.html, aggiornato man mano che aggiungiamo le entities al nostro progetto con la pagina CRUD creata da JHipster. Sul link c’è un attributo dal nome ui-sref che connette il link alle impostazioni di state definite nel file JavaScript degli stati di riferimento all’entità (in questo caso author.state.js).

In questo caso, nel file è definito uno state author e ha i riferimenti di routing, URL di riferimento, eventuali ruoli legati alla pagina, titolo della pagina e molto altro. Soffermiamoci sul routing che instrada al controller Angular di riferimento (AuthorController) e il template da invocare per il rendering delle informazioni (authors.html). Come in un classico pattern MVC dei framework Java più diffusi (p.e.:Spring MVC, Struts) definiamo Controller e View, però al posto di usare una classe Action (o Controller) che prepara i dati da passare a una JSP che li interpreta tramite JSTL o JSP Expression Languages, il Controller è una function JavaScript e la View è una pagina html con attributi sui tag interpretati da AngularJS.

L’AuthorController è il controller di riferimento in questo esempio: la function è già definita con dei parametri in ingresso che rappresentano servizi iniettati dal container 12 (proprio come una classica dependency injection di Spring). Tra i primi comandi che esegue è la funzione loadAll() che invoca il servizio Author e la sua funzione query. Il servizio, iniettato nel controller, è definito nel file author.service.js e implementa una classica angular resource [15] che si connette al RestController Java AuthorResource.java implementato seguendo gli standard REST verbs GET, POST, PUT e DELETE [14]. Il metodo di query invoca /api/authors caricando un array JSON con tutti gli autori presenti su database. A questo punto, il controller salverà nella function onSuccess l’array di dati in una variabile javascript authors.

Una volta eseguita la funzione del controller, AngularJS renderizza la pagina authors.html che, all’interno della table, itera gli authors e realizza una riga della tabella per ognuno di essi, impostando anche i link per le altre pagine da visualizzare di edit, delete e read.

Figura 10 – Classi di test generate da JHipster.

Figura 10 – Classi di test generate da JHipster.

 

Per concludere è bene notare che JHipster genera, sempre automaticamente, insieme al codice dell’applicazione, una serie di test automatici! I framework di test utilizzati sono: Junit, Cucumber, Karma.js, Gatling e Protractor.

 

Conclusioni

In questo articolo abbiamo dato una rapida scorsa a cosa viene generato dietro le quinte da JHipster dell’applicazione jhmoka creata e spiegata nello scorso articolo.

 

Riferimenti

[1] S. Rossini – M. Luly – D. Dello Preite, JHipster – I Parte: Introduciamo JHipster con un esempio pratico, MokaByte 220, settembre 2016

http://www.mokabyte.it/2016/09/jhipster-1/

 

[2] JHipster

https://jhipster.github.io/

 

[3] JHipster Tutorial

https://jhipster.github.io/presentation/#/

 

[4] JHipster tech stack

https://jhipster.github.io/tech-stack

 

[5] JHipster Microservices

https://jhipster.github.io/microservices-architecture/

 

[6] JHipster Tests

https://jhipster.github.io/running-tests/

 

[7] Logstash

https://www.elastic.co/guide/en/logstash/current/introduction.html

 

[8] Swagger

http://swagger.io/getting-started/

 

[9] Spring Boot

https://spring.io/guides/gs/spring-boot/

 

[10] LiquiBase

http://www.liquibase.org/

 

[11] Jakarta Tomcat

http://jakarta.apache.org/

 

[12] AngularJS

https://angularjs.org/

 

[13] AngularUI Router

https://ui-router.github.io/

 

[14] Tutorial API REST

http://www.restapitutorial.com/lessons/httpmethods.html

 

[15] Angular Resource

https://docs.angularjs.org/api/ngResource/service/$resource

 

Condividi

Pubblicato nel numero
221 ottobre 2016
Stefano Rossini è nato a Giussano (MI) il 29/10/1970 e ha conseguito il diploma universitario in Ingegneria Informatica presso il Politecnico di Torino. Ha maturato più di venti anni di esperienza in diversi progetti Enterprise mission-critical ricoprendo i ruoli di IT Program Manager, Project Manager & Software Architect presso importanti…
Marco Luly è nato a Messina l’8 luglio 1982. Da dieci anni lavora nella progettazione e sviluppo di applicazioni enterprise per enti pubblici, per il mercato Fashion/Luxury, per l’Automotive e per il settore bancario: da software strategici/gestionali a sistemi di autenticazione/SSO. Nei vari progetti in cui è stato coinvolto ha…
Davide Dello Preite è nato a San Pietro Vernotico il 21 agosto 1987. Da diversi anni lavora nella progettazione e sviluppo di applicazioni enterprise per il core business bancario ricoprendo nel tempo i ruoli di Software Engineer, Team Leader e Scrum Master. In questi anni di esperienza ha acquisito anche…
Articoli nella stessa serie
  • JHipster
    I parte: Introduciamo JHipster con un esempio pratico
Ti potrebbe interessare anche