Creare una web application con Spring Boot, MongoDB, Angular 4 e TypeScript e deployarla in cloud come Microsoft Azure Webapp – Parte 10

Qui la parte precedente dell’articolo: Creare una web application con Spring Boot, MongoDB, Angular 4 e TypeScript e deployarla in cloud come Microsoft Azure Webapp – Parte 9

CONVERTIRE IL MODEL IN VIEWMODEL

Implementiamo ora la classe che costituirà il nostro converter tra le entità User e i viewmodel UserViewModel. Come sempre, scegliamo un approccio flessibile e sfruttiamo il meccanismo dei Generics per definire una generica interfaccia di conversione tra Model e ViewModel che andremo ad implementare di volta in volta che avremo necessità di convertire le nostre entità in DTO e viceversa.

Aggiungiamo al nostro un progetto un nuovo package che chiamiamo “converters” e, al suo interno, creiamo l’interfaccia IModelViewModelConverter definendola, genericamente, come:

public interface IModelViewModelConverter<M, VM>

All’interno di questa interfaccia una serie di metodi per:

  • Convertire un oggetto del Model in oggetto del ViewModel
  • Convertire una lista di oggetti Model in una lista di oggetti ViewModel
  • Convertire un oggetto ViewModel in un oggetto del Model
  • Convertire una lista di oggetti ViewModel in una lista di oggetti Model
public interface IModelViewModelConverter<M, VM> {

	public M fromViewModel(VM vm);
	
	public List<M> fromViewModelList(List<VM> vmList);
	
	public VM toViewModel(M m);
	
	public List<VM> toViewModelList(List<M> mList);
}

L’interfaccia IModelViewModelConverter si presenterà quindi così:
80 - SpringBoot Angular example Model to View Model converter interface
Definita l’interfaccia generics di conversione tra Model e ViewModel, dobbiamo implementare la classe concreta per la conversione del nostro model User nel nostro DTO UserViewModel e viceversa.

Creiamo quindi la classe UserConverter che implementa l’interfaccia IModelViewModelConverter utilizzando come tipi proprio User e UserViewModel

In attesa di implementare il body dei vari metodi, la classe UserConverter si presenterà quindi così:

public class UserConverter implements IModelViewModelConverter<User, UserViewModel> {

	@Override
	public User fromViewModel(UserViewModel vm) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<User> fromViewModelList(List<UserViewModel> vmList) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public UserViewModel toViewModel(User m) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<UserViewModel> toViewModelList(List<User> mList) {
		// TODO Auto-generated method stub
		return null;
	}

}

81 - SpringBoot Angular example Model to View Model converter User implementation
Iniziamo ad implementare il metodo che ci serve, ovvero quello per la conversione di una lista di User in una lista di UserViewModel. Questo metodo, in realtà, non farà altro che eseguire ciclicamente su ogni oggetto della lista di User il metodo per la conversione del singolo oggetto.

Partiamo quindi da quest’ultimo, che non dovrà far altro che settare le variabili d’istanza dell’oggetto ViewModel a partire da quelle dell’oggetto del Model. Per ora, invochiamo esplicitamente i vari setter; in seguito introdurremo una libreria che ci permetterà di fare questa operazione in automatico, riducendo ancora una volta la necessità di scrivere boilerplate code.

Per il metodo sarà implementato come segue:

	@Override
	public UserViewModel toViewModel(User m) {
		UserViewModel uvm = new UserViewModel();
		
		uvm.setFirstname(m.getFirstname());
		uvm.setLastname(m.getLastname());
		uvm.setCountry(m.getCountry());
		uvm.setAge(m.getAge());
		
		return uvm;
	}

A partire da questo, implementiamo facilmente l’analogo metodo che lavora sulle liste di oggetti:

	@Override
	public List<UserViewModel> toViewModelList(List<User> mList) {
		
		List<UserViewModel> users = new ArrayList<>();
		for( User u : mList)
			users.add(this.toViewModel(u));
		
		return users;
	}

82 - SpringBoot Angular example Model to View Model converter implentation

Ora che abbiamo implementato i nostri converter possiamo tornare al Service e utilizzarli per soddisfare il secondo punto tra le operazioni in carico al metodo getAllUsers().

Per prima cosa, dobbiamo aggiungere un oggetto UserConverter all’interno del nostro UserService, delegandone sempre la gestione via Dependency Injection a Spring, tramite l’annotazione @Autowired.

Per poterlo fare però, dobbiamo prima fare un’ultima modifica alla classe e cioè annotarla con @Component, lo stereotype che indica che la classe rappresenta un bean gestito da Spring.

Modifichiamo quindi la definizione della classe come segue:

@Component
public class UserConverter implements IModelViewModelConverter<User, UserViewModel>

Purtroppo, non è sufficiente annotare l’interfaccia IModelViewModelConverter per fare ereditare l’annotazione @Component a UserConverter e alle eventuali altre implementazioni concrete, in quanto le annotazioni non si propagano lungo la gerarchia alle sottoclassi o alle implementazioni delle interfacce.

Per poter sfruttare l’ereditarietà dobbiamo definire noi stessi un’annotazione custom, a sua volta annotata con @Component, con cui annotare IModelViewModelConverter. Ci torneremo più avanti e lo faremo, così da vedere anche questo meccanismo, ma non ora.

Ora torniamo a noi e inseriamo la chiamata al metodo toViewModelList() del nostro UserConverter, passandogli come parametro la Lista di User recuperata dal database MongoDB tramite il repository e assegnando il risultato alla lista di ViewModel da ritornare.

Il codice della classe UserService diventa:

@Service
public class UserService {

	@Autowired
	UserRepository userRepo;
	
	@Autowired
	UserConverter userConv;
	
	public List<UserViewModel> getAllUsers() {
			
		List<User> userList = userRepo.findAll();
		List<UserViewModel> users = userConv.toViewModelList(userList);
		
		return users;
	}
}

83 - SpringBoot Angular example User Service retrieve and conversion

RICHIAMARE IL SERVICE DAL CONTROLLER

Ora che abbiamo implementato il Repository e il Service, non ci resta che richiamare quest’ultimo dal Controller REST che abbiamo implementato in precedenza, in modo che esso possa poi restituire i dati all’applicazione Angular di front-end per la loro visualizzazione in pagina tramite l’opportuno Component (Angular, non Spring).

Torniamo quindi nella classe UserController, dove dichiariamo un oggetto UserService in @Autowired ed eliminiamo la lista di oggetti User che avevamo precedentemente istanziato “a mano” direttamente nel codice.

Sostituiamo la creazione manuale degli oggetti User con la chiamata al metodo getAllUsers() del nostro UserService.

List<UserViewModel> userList = userService.getAllUsers();

Il contenuto della classe UserController diventa quindi il seguente:

@RestController
public class UserController {

	@Autowired
        UserService userService;
	
        @CrossOrigin(origins = "http://localhost:4200")
    	@RequestMapping(value = "/users", method = { RequestMethod.GET })
    	public List<UserViewModel> listAllUsers() {
    	
    		List<UserViewModel> userList = userService.getAllUsers();
    	
    		return userList;
    	}
}

A questo punto dobbiamo testare la nuova versione della nostra applicazione che continua a mostrare in pagina la lista degli utenti, recuperandoli però ora da un database MongoDB. Prima di eseguire l’applicazione però, dobbiamo alimentare il nostro database che al momento è ancora vuoto.

Non avendo ancora creato una pagina con un form per la sottomissione dei dati relativi ad un nuovo User né, tantomeno, un servizio di back-end per il suo inserimento a database, popoliamo per ora a mano il database MongoDB. Più avanti, creeremo anche la pagina e i servizi per l’inserimento di un nuovo utente.

Per ora, recuperiamo il JSON con la lista di utenti che avevamo ricevuto come risultato dalla chiamata di test precedente, quando il controller ci restituiva i dati “schiantati” al suo interno, e lo utilizziamo per inserire questi oggetti come documenti su MongoDB utilizzando il tool MongoChef (Studio 3T).

Il JSON restituito era il seguente:

[
	{
		firstname: "Davis",
		lastname: "Molinari",
		country: "Italy",
		age: 34
	},
	{
		firstname: "Lionel",
		lastname: "Messi",
		country: "Argentina",
		age: 30
	},
	{
		firstname: "Jason",
		lastname: "Bourne",
		country: "US",
		age: 30
	}
]

Apriamo MongoChef, e connettiamoci all’istanza di MongoDB che stiamo utilizzando tramite la connection configurata e salvata in precedenza. A questo punto dobbiamo creare il database e la collection in cui inserire i nostri oggetti User di test.

Vai alla parte successiva dell’articolo: Creare una web application con Spring Boot, MongoDB, Angular 4 e TypeScript e deployarla in cloud come Microsoft Azure Webapp – Parte 11

This entry was posted in $1$s. Bookmark the permalink.

2 thoughts on “Creare una web application con Spring Boot, MongoDB, Angular 4 e TypeScript e deployarla in cloud come Microsoft Azure Webapp – Parte 10

  1. Pingback: Creare una web application con Spring Boot, MongoDB, Angular 4 e TypeScript e deployarla in cloud come Microsoft Azure Webapp – Parte 11 | Dede Blog

  2. Pingback: Creare una web application con Spring Boot, MongoDB, Angular 4 e TypeScript e deployarla in cloud come Microsoft Azure Webapp – Parte 9 | Dede Blog

Leave a Reply

Your email address will not be published. Required fields are marked *