4. TP 1: Gestione di base di una busta paga
4.1. Introduction
Per mettere in pratica quanto visto in precedenza, proponiamo ora un esercizio che consiste nello scrivere un client Android per tablet, che consenta di simulare i calcoli delle buste paga dei dipendenti di un'associazione.
L'applicazione avrà un'architettura client/server:

- il server [1] è già disponibile;
- è necessario sviluppare il client Android [2].
4.2. Il database
4.2.1. Definizione
I dati statici necessari per generare la busta paga saranno inseriti in un database che d'ora in poi chiameremo dbpam. Questo database contiene le seguenti tabelle:
Struttura:
chiave primaria | |
numero di versione – aumenta ad ogni modifica della riga | |
numero di previdenza sociale del dipendente – univoco | |
nome del dipendente | |
il suo nome | |
il suo indirizzo | |
la sua città | |
il suo codice postale | |
chiave esterna sul campo [ID] della tabella [INDEMNITES] |
Il contenuto potrebbe essere il seguente:

Struttura:
chiave primaria | |
numero di versione – aumenta ad ogni modifica della riga | |
percentuale: contributo sociale generalizzato + contributo al rimborso del debito sociale | |
percentuale: contributo sociale generalizzato deducibile | |
percentuale: previdenza sociale, vedovanza, vecchiaia | |
percentuale: pensione integrativa + assicurazione contro la disoccupazione |
Il contenuto potrebbe essere il seguente:
![]()
Le aliquote dei contributi sociali sono indipendenti dal dipendente. La tabella precedente contiene una sola riga.
chiave primaria | |
numero di versione – aumenta ad ogni modifica della riga | |
indice di elaborazione – univoco | |
prezzo netto in euro per un'ora di guardia | |
indennità di vitto e alloggio in euro per giorno di servizio | |
indennità pasto in euro per giorno di assistenza | |
indennità per ferie retribuite. Si tratta di una percentuale da applicare allo stipendio base. |
Il contenuto potrebbe essere il seguente:

Si noti che le indennità possono variare da un'assistente all'infanzia all'altra. Esse sono infatti associate a una specifica assistente all'infanzia tramite il suo indice di retribuzione. Pertanto, la signora Marie Jouveinal, che ha un indice di retribuzione pari a 2 (tabella EMPLOYES), ha una retribuzione oraria di 2,1 euro (tabella INDEMNITES).
4.2.2. Generazione
Viene fornito lo script [dbpam_hibernate.sql] per la generazione del database:
![]() |
Creare il database [dbpam_hibernate] (è il nome del BD utilizzato dal server web / jSON) e assicurarsi che l'account root senza password possa accedervi. È possibile procedere come segue:
Avviare MySQL e poi [PhpMyAdmin]:
![]() | ![]() |
- [1-2]: importare lo script [dbpam_hibernate.sql], quindi eseguirlo;
4.2.3. Modellazione Java del database
Gli elementi delle tabelle [EMPLOYES], [INDEMNITES] e [COTISATIONS] sono modellati dalle seguenti classi:
[Employe]
package pam.entities;
import java.io.Serializable;
public class Employe implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private String SS;
private String nom;
private String prenom;
private String adresse;
private String ville;
private String codePostal;
private int idIndemnite;
private Indemnite indemnite;
public Employe() {
}
public Employe(String SS, String nom, String prenom, String adresse, String ville, String codePostal, Indemnite indemnite) {
...
}
// getter e setter
....
}
- righe 8-15: questi campi corrispondono alle colonne della tabella [EMPLOYES];
- riga 16: il campo [indemniteId] corrisponde alla colonna [INDEMNITE_ID], che è la chiave esterna della tabella [EMPLOYES];
- riga 17: l’indennità del dipendente. Questo campo non è sempre compilato:
- non lo è quando si richiede l'URL [/employes],
- è compilato quando si richiede l'URL [/salaire];
[Indemnite]
package pam.entities;
import java.io.Serializable;
public class Indemnite implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private int indice;
private double baseHeure;
private double entretienJour;
private double repasJour;
private double indemnitesCp;
public Indemnite() {
}
public Indemnite(int indice, double baseHeure, double entretienJour, double repasJour, double indemnitesCP) {
...
}
// getter e setter
....
}
- righe 8-14: i campi corrispondono alle colonne della tabella [INDEMNITES];
[Cotisation]
package pam.entities;
import java.io.Serializable;
public class Cotisation implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private double csgrds;
private double csgd;
private double secu;
private double retraite;
public Cotisation() {
}
public Cotisation(double csgrds, double csgd, double secu, double retraite) {
...
}
// getter e setter
...
}
- righe 8-13: i campi corrispondono alle colonne della tabella [COTISATIONS];
4.3. Installazione del server web / jSON
![]() |
4.3.1. Installazione
Il file binario Java del server web / jSON viene fornito:
![]() |
Per avviare il server web / jSON, procedere come segue:
- avviare il SGBD MySQL;
- assicurarsi che BD e [dbpam_hibernate] esistano;
- aprire una finestra DOS;
- accedete alla cartella del file jar;
- digitare il comando:
Ciò presuppone che il file binario [java.exe] si trovi nella cartella PATH del proprio computer. In caso contrario, digitare il percorso completo di [java.exe], ad esempio:
Vengono visualizzati i log:
- riga 16: viene individuato il file URL [/salaire/{SS}/{ht}/{jt}];
- riga 17: viene individuato URL [/employes];
4.3.2. I URL del servizio web/jSON
![]() |
Il servizio web / jSON è implementato da Spring MVC ed espone due URL:
@RequestMapping(value = "/employes", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
public EmployesResponse getEmployes() {
...
@RequestMapping(value = "/salaire/{SS}/{ht}/{jt}", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
public FeuilleSalaireResponse getFeuilleSalaire(@PathVariable("SS") String SS, @PathVariable("ht") double ht, @PathVariable("jt") int jt) {
Il servizio web accetta le seguenti due URL:
- riga 1: /employes: per ottenere l'elenco dei dipendenti;
- riga 4: /stipendio/SS/ht/jt: per ottenere la busta paga del dipendente n. [SS] che ha lavorato [ht] ore per [jt] giorni;
Ecco alcune schermate che lo dimostrano.
Si richiedono i dipendenti:

Si esegue il cut-off del database, si riavvia il server e si richiamano i dipendenti:

Si richiede uno stipendio:

Si richiede lo stipendio di una persona inesistente:

4.3.3. Le risposte jSON del servizio web/jSON
![]() |
![]() |
I URL del servizio web / jSON inviano risposte del tipo [Response<T>]:
package client.android.dao.service;
import java.util.List;
public class Response<T> {
// ----------------- proprietà
// stato dell'operazione
private int status;
// eventuali messaggi di stato
private List<String> messages;
// il corpo della risposta
private T body;
// costruttori
public Response() {
}
public Response(int status, List<String> messages, T body) {
this.status = status;
this.messages = messages;
this.body = body;
}
// getter e setter
...
}
- URL e [/employes] restituiscono un tipo Response<List<Employe>>;
- URL e [/salaire] restituiscono un tipo Response<FeuilleSalaire>;
La classe [FeuilleSalaire] è la seguente:
package pam.entities;
import java.io.Serializable;
public class FeuilleSalaire implements Serializable {
private static final long serialVersionUID = 1L;
// campi privati
private Employe employe;
private Cotisation cotisation;
private ElementsSalaire elementsSalaire;
// costruttori
public FeuilleSalaire() {
}
public FeuilleSalaire(Employe employe, Cotisation cotisation, ElementsSalaire elementsSalaire) {
...
}
// getter e setter
...
}
- riga 9: la classe [Employe] è stata presentata al paragrafo 4.2.3;
- riga 10: la classe [Cotisation] è stata presentata nel paragrafo 4.2.3;
La classe [ElementsSalaire] (riga 11) è la seguente:
package pam.entities;
import java.io.Serializable;
public class ElementsSalaire implements Serializable {
private static final long serialVersionUID = 1L;
// campi privati
private double salaireBase;
private double cotisationsSociales;
private double indemnitesEntretien;
private double indemnitesRepas;
private double salaireNet;
// costruttori
public ElementsSalaire() {
}
public ElementsSalaire(double salaireBase, double cotisationsSociales, double indemnitesEntretien, double indemnitesRepas, double salaireNet) {
...
}
// getter e setter
...
}
4.4. Test del client Android
![]() |
Ecco il file binario eseguibile del client Android completato:
![]() |
Con il mouse, trascinate il file binario [pam-client.apk] sopra indicato su un emulatore di tablet [GenyMotion]. Verrà quindi salvato ed eseguito. Avviate anche il server web / jSON, se non l'avete già fatto. Il client Android ha lo scopo di recuperare le informazioni restituite dal server web / jSON e di formattarle. Le diverse schermate del client Android sono le seguenti:
Per prima cosa è necessario connettersi al servizio web / jSON:

- in [1], si inserisce l’URL del servizio web / jSON. Con l'emulatore, inserite uno degli indirizzi IP o PC (ma non 127.0.0.1). Con un tablet, inserite l'indirizzo Wi-Fi del computer che ospita il server web / jSON e disattivate il firewall del server, se presente, poiché potrebbe bloccare le chiamate in entrata;
- su [2], ci si connette;
Si accede quindi alla pagina di simulazione:

- in [3], si seleziona un dipendente;
- in [4], si indica un numero di ore;
- in [5], si indica un numero di giorni;
- in [6], si avvia la simulazione;
La pagina di simulazione ottenuta è la seguente:

- in [7], la simulazione ottenuta;
- in [8], la si salva;

- in [9], l'elenco delle simulazioni;
- in [10], si rimuove una simulazione;

- in [11], non ci sono più simulazioni;
- in [12], si torna al modulo di simulazione;

- in [13], si torna al modulo;
- in [14], si torna alla pagina di configurazione;

- da [15], si torna al modulo di accesso iniziale.
4.5. Lavoro da svolgere
Lo scheletro dell’app Android presentato in precedenza vi viene fornito. È stato realizzato a partire dal progetto [client-android-skel] descritto al paragrafo 2.
![]() |
Il progetto è eseguibile e dispone già delle viste necessarie. È sufficiente aggiungere del codice affinché l’applicazione svolga le operazioni previste. La procedura da seguire è la seguente:
- eseguite la versione completa per comprendere il lavoro da svolgere;
- eseguire la versione ridotta e studiarne il codice. Esso rispetta i metodi di progettazione utilizzati nelle pagine precedenti;
- aggiungere il codice mancante;










