Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:laborator05 [2015/11/19 23:45]
Andrei Roșu-Cojocaru
laboratoare:laborator05 [2015/11/25 20:00] (current)
Andrei Roșu-Cojocaru
Line 1280: Line 1280:
   * un utilizator tip **client**, care va formula o comandă după ce şi-a specificat un anumit coş de cumpărături ca urmare a consultării catalogului de produse; pe baza comenzii va fi emisă o factură (''​invoice_header''​),​ caracterizată printr-un număr de identificare (''​identification_number''​),​ data la care a fost emisă (''​issue_date''​),​ stare (''​state''​) și identificatorul utilizatorului către care va fi transmisă (''​user_id''​);​ aceasta conține la rândul ei mai multe înregistrări,​ corespunzătoare cărților care au fost cumpărate (''​invoice_line''​),​ definite de factura corespunzătoare (''​invoice_header_id''​),​ identificatorul formatului de prezentare al cărții (''​book_presentation_id''​) și cantitatea (''​quantity''​).   * un utilizator tip **client**, care va formula o comandă după ce şi-a specificat un anumit coş de cumpărături ca urmare a consultării catalogului de produse; pe baza comenzii va fi emisă o factură (''​invoice_header''​),​ caracterizată printr-un număr de identificare (''​identification_number''​),​ data la care a fost emisă (''​issue_date''​),​ stare (''​state''​) și identificatorul utilizatorului către care va fi transmisă (''​user_id''​);​ aceasta conține la rândul ei mai multe înregistrări,​ corespunzătoare cărților care au fost cumpărate (''​invoice_line''​),​ definite de factura corespunzătoare (''​invoice_header_id''​),​ identificatorul formatului de prezentare al cărții (''​book_presentation_id''​) și cantitatea (''​quantity''​).
  
-Pentru fiecare funcționalitate există o pagină dedicată, gestionată de câte o clasă Java Servlet: pagina de autentificare (''​LoginServlet''​) de unde, în funcţie de rolul utilizatorului se trece la pagina de tip administrator (''​AdministratorServlet''​) respectiv pagina de tip client (''​ClientServlet''​).+Pentru fiecare funcționalitate există o pagină dedicată, gestionată de câte o clasă Java Servlet ​și de o pagină .jsp: pagina de autentificare (''​LoginServlet''​ / ''​login.jsp''​) de unde, în funcţie de rolul utilizatorului se trece la pagina de tip administrator (''​AdministratorServlet''​ / ''​administrator.jsp''​) respectiv pagina de tip client (''​ClientServlet''​ / ''​client.jsp''​). Pentru fiecare pagină, cererea primită din navigator este preluată de clasa servlet corespunzătoare,​ unde sunt realizate procesările ce țin de logica aplicației,​ inclusiv accesarea informațiilor din baza de date. Prezentarea informațiilor astfel obținute este delegată către pagina .jsp, către care se transferă contextul. Datele care se doresc a fi vizualizate sunt transmise dinspre servlet către pagina JSP sub formă de atribute. În acest mod se construiește răspunsul care va fi trimis către navigator.
  
-{{ :​laboratoare:​laborator04:​bookstore_webapplication_structure.png?​nolink&​300 }}+{{ :​laboratoare:​laborator05:​bookstore_webapplication_structure.png?​nolink&​300 }}
  
 <​html>​ <​html>​
Line 1291: Line 1291:
 </​center>​ </​center>​
 </​html>​ </​html>​
 +
 +Atributele care sunt transmise între clasele servlet și paginile .jsp sunt:
 +  - LoginServlet → login.jsp
 +    * ''​Constants.ERROR_ATTRIBUTE''​ - furnizează informații cu privire la rezultatul operației de autentificare a unui utilizator în cadrul aplicației web (succes, eșec);
 +  - AdministratorServlet → administrator.jsp
 +    * ''​Constants.DISPLAY''​ - identificatorul utilizatorului autentificat în cadrul aplicației web (format din prenume și nume);
 +    * ''​Constants.DATABASE_STRUCTURE''​ - structura bazei de date, formată din lista tuturor tabelelor;
 +    * ''​Constants.CURRENT_TABLE''​ - denumirea tabelei vizualizată la un moment dat de timp;
 +    * ''​Constants.ATTRIBUTES''​ - structura tabelei vizualizată la un moment dat de timp, conținând lista tuturor atributelor;​
 +    * ''​Constants.IDENTIFIER''​ - denumirea identificatorului în lista de atribute;
 +    * ''​Constants.IDENTIFIER_INDEX''​ - poziția identificatorului în lista de atribute;
 +    * ''​Constants.IDENTIFIER_NEXT_VALUE''​ - valoarea identificatorului unei înregistrări pentru adăugare;
 +    * ''​Constants.TABLE_CONTENT''​ - conținutul tabelei vizualizate la un moment dat de timp, conținând lista tuturor înregistrărilor,​ pentru fiecare înregistrare fiind reținute valorile tuturor atributelor;​
 +    * ''​Constants.IDENTIFIER_VALUE_OF_RECORD_TO_BE_UPDATED''​ - valoarea identificatorului unei înregistrări selectate pentru modificare sau ștergere, în situația în care aceasta a fost selectată;
 +  - ClientServlet → client.jsp
 +    * ''​Constants.DISPLAY''​ - identificatorul utilizatorului autentificat în cadrul aplicației web (format din prenume și nume);
 +    * ''​Constants.BOOKS''​ - lista cărților care vor fi vizualizate,​ împreună cu toate atributele, în funcție de criteriile de filtrare care au fost precizate;
 +    * ''​Constants.ERROR_MESSAGE''​ - mesaj de eroare legat de procesarea coșului de cumpărături;​
 +    * ''​Constants.SHOPPING_CART''​ - conținutul coșului de cumpărături (identificatorul formatului de prezentare și cantitatea solicitată);​
 +    * ''​Constants.FORMATS_FILTER''​ - lista cu criteriile de sortare în funcție de formatul de prezentare;
 +    * ''​Constants.LANGUAGES_FILTER''​ - lista cu criteriile de sortare în funcție de limbă;
 +    * ''​Constants.CATEGORIES_FILTER''​ - lista cu criteriile de sortare în funcție de categorie;
 +    * ''​Constants.CURRENT_RECORDS_PER_PAGE''​ - numărul maxim de înregistrări care poate fi vizualizat pe o pagină la un moment dat;
 +    * ''​Constants.CURRENT_PAGE''​ - pagina vizualizată la un moment dat;
 +    * ''​Constants.FILTER_CHANGE''​ - indică dacă informațiile au fost reîncărcate din baza de date datorită modificării criteriilor de filtrare;
 +    * ''​Constants.FORMATS_LIST''​ - lista cu toate formatele de prezentare disponibile;​
 +    * ''​Constants.LANGUAGES_LIST''​ - lista cu toate limbile disponibile;​
 +    * ''​Constants.CATEGORIES_LIST''​ - lista cu toate categoriile disponibile.
  
 {{ :​laboratoare:​laborator04:​bookstore_webapplication_loginservlet.png?​nolink&​300 }} {{ :​laboratoare:​laborator04:​bookstore_webapplication_loginservlet.png?​nolink&​300 }}
Line 1357: Line 1385:
 {{ :​laboratoare:​laborator04:​eclipse02.png?​nolink }} {{ :​laboratoare:​laborator04:​eclipse02.png?​nolink }}
  
-{{ :​laboratoare:​laborator04:​eclipse03.png?​nolink }}+{{ :​laboratoare:​laborator05:​eclipse03.png?​nolink }}
  
 ==== NetBeans ==== ==== NetBeans ====
  
-Să se creeze o referinţă către serverul HTTP Apache Tomcat care să fie adăugată la proiectul ​04-BookStore-JavaServlets. +Să se creeze o referinţă către serverul HTTP Apache Tomcat care să fie adăugată la proiectul ​05-BookStore-JSP. 
  
 Se accesează opţiunea //Deploy// din meniul contextual al proiectului (accesat cu right-click). Se accesează opţiunea //Deploy// din meniul contextual al proiectului (accesat cu right-click).
  
-{{ :​laboratoare:​laborator04:​netbeans.png?nolink }}+{{ :​laboratoare:​laborator04:​netbeans01.png?nolink }}
  
 Alternativ, se poate porni serverul Apache Tomcat și dezvolta aplicația web în contextul său și prin opțiunea //Run// (F6), care va lansa și browser-ul implicit în care va fi prezentată pagina principală a aplicației web. Alternativ, se poate porni serverul Apache Tomcat și dezvolta aplicația web în contextul său și prin opțiunea //Run// (F6), care va lansa și browser-ul implicit în care va fi prezentată pagina principală a aplicației web.
 +
 +===== =====
 +
 +În fișierul ''​catalina.properties''​ din directorul ''​conf''​ al serverului web Apache Tomcat 8.x, suprascrieți proprietatea ''​org.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING''​ astfel încât să se folosească o politică permisivă în privința caracterelor ''"''​ imbricate (aceasta va avea valoarea ''​false''​). O astfel de configurație este necesară pentru a putea fi accesate atribute ale contextului paginii JSP din cadrul unor scripleți.
 +
 +<file catalina.properties>​
 +# other properties
 +org.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING=false
 +</​file>​
 +
 +==== Eclipse ====
 +
 +Fișierul ''​catalina.properties''​ poate fi editat din mediul integrat de dezvoltare, în cazul în care sunt preluate informațiile din configurația de rulare specifică spațiului de lucru curent. În acest sens, în secțiunea //​Properties//​ asociată serverului Apache Tomcat 8.x (accesibilă prin intermediul meniului contextual, din panoul //​Servers//​),​ atributul //​Location//​ trebuie să refere metadatele din cadrul spațiului de lucru curent (având valoarea //​[workspace metadata]//​). În situația în care este precizată o altă valoare, se accesează butonul //Switch Location//.
 +
 +{{ :​laboratoare:​laborator04:​eclipse04.png?​nolink }}
 +
 +În panoul //Project Explorer//, în secțiunea //​Servers//,​ se editează fișierul ''​catalina.properties''​ corespunzător configurației de server Apache Tomcat 8.x pe care este rulată aplicația web.
 +
 +{{ :​laboratoare:​laborator04:​eclipse05.png?​nolink }}
 +
 +==== NetBeans ====
 +
 +Fișierul ''​catalina.properties''​ va fi editat manual, după ce se identifică locația la care este instalată instanța serverului Apache Tomcat 8.x pe care este rulată aplicația web. Aceasta poate fi determinată din secțiunea //Servers// corespunzătoare,​ în panoul //​Connection//,​ fiind referită prin atributul //Catalina Base//.
 +
 +{{ :​laboratoare:​laborator04:​netbeans02.png?​nolink }}
  
 ===== ===== ===== =====
Line 1384: Line 1437:
  
 <​spoiler|Indicații de Rezolvare>​ <​spoiler|Indicații de Rezolvare>​
-În clasa ''​ClientGraphicUserInterface''​ din pachetul ​''​ro.pub.cs.aipi.lab04.graphicuserinterface'',​ se afișează lista cu limbile în funcție de care se realizează filtrarea, pentru fiecare dintre acestea atașându-se un buton pentru eliminarea valorii respective.+În pagina ​''​client.jsp''​ (accesibilă în directorul ''​WebContent''​ din proiectul //​Eclipse//,​ respectiv în directorul ​''​web'' ​din proiectul //​NetBeans//​), se afișează lista cu limbile în funcție de care se realizează filtrarea, pentru fiecare dintre acestea atașându-se un buton pentru eliminarea valorii respective.
  
-Se iterează pe lista cu filtre în funcție de limbi (obiectul ​''​languagesFilter''​),​ iar pentru fiecare element:+Se iterează pe lista cu filtre în funcție de limbi (atributul ​''​languagesFilter'',​ transmis din ''​ClientServlet''​),​ iar pentru fiecare element:
   * se afișează șirul de caractere conținând limba;   * se afișează șirul de caractere conținând limba;
   * se afișează un element de tip [[http://​www.w3schools.com/​tags/​tag_input.asp|<​input>​]],​ având atributul ''​type''​ cu valoarea ''​image''​ și denumirea ''​delete_language:​ _{language_name}''​ (valori reținutr de constantele ''​DELETE_BUTTON_NAME''​ și ''​LANGUAGE''​ din interfața ''​Constants''​). Resursa grafică se regăsește în directorul ''​images'',​ în subdirectorul ''​user_interface'',​ având denumirea ''​delete.png''​ (se recomandă să se forțeze dimensiunea acesteia la 16x16, prin specificarea atributelor ''​width''​ și ''​height''​).   * se afișează un element de tip [[http://​www.w3schools.com/​tags/​tag_input.asp|<​input>​]],​ având atributul ''​type''​ cu valoarea ''​image''​ și denumirea ''​delete_language:​ _{language_name}''​ (valori reținutr de constantele ''​DELETE_BUTTON_NAME''​ și ''​LANGUAGE''​ din interfața ''​Constants''​). Resursa grafică se regăsește în directorul ''​images'',​ în subdirectorul ''​user_interface'',​ având denumirea ''​delete.png''​ (se recomandă să se forțeze dimensiunea acesteia la 16x16, prin specificarea atributelor ''​width''​ și ''​height''​).
Line 1392: Line 1445:
 Elementele vor fi incluse ca linii în cadrul unui tabel (''<​tr><​td>​...</​td></​tr>''​). Elementele vor fi incluse ca linii în cadrul unui tabel (''<​tr><​td>​...</​td></​tr>''​).
  
-În clasa ''​ClientServlet''​ din pachetul ''​ro.pub.cs.aipi.lab04.servlets'',​ se tratează acțiunile corespunzătoare evenimentelor de tip apăsare a butoanelor de tip ''​insert'',​ respectiv ''​delete''​ corespunzătoare filtrului în funcție de limba în care a fost selectată cartea.+Iterația pe elementele unei liste în cadrul unei pagini JSP se face folosind eticheta [[http://​www.tutorialspoint.com/​jsp/​jstl_core_foreach_tag.htm|<​c:​forEach>​]],​ obiectul care se dorește a fi parcurs fiind referit prin atributul ''​items''​. 
 + 
 +Valoarea unei constante din cadrul interfeței ''​ro.pub.cs.aipi.lab05.general.Constants''​ poate fi obținută prin evaluarea unei expresii, încadrată între elementele ''<​%= ... %>''​. 
 + 
 +În clasa ''​ClientServlet''​ din pachetul ''​ro.pub.cs.aipi.lab05.servlets'',​ se tratează acțiunile corespunzătoare evenimentelor de tip apăsare a butoanelor de tip ''​insert'',​ respectiv ''​delete''​ corespunzătoare filtrului în funcție de limba în care a fost selectată cartea.
   * pentru parametrii având denumirea de tipul ''​insert_language:​ ''​ (valori conținute de constantele ''​INSERT_BUTTON_NAME'',​ respectiv ''​LANGUAGE''​ din interfața ''​Constants''​),​ se obține denumirea limbii (ca valoare atașată parametrului,​ prin invocarea metodei ''​request.getParameter(parameter)''​),​ se verifică dacă aceasta nu este conținută în lista de limbi în funcție de care se face filtrarea și, în caz afirmativ, este adăugată la listă, marcându-se faptul că lista de filtre a fost modificată (parametrul ''​filterChange''​ de tip ''​boolean''​);​   * pentru parametrii având denumirea de tipul ''​insert_language:​ ''​ (valori conținute de constantele ''​INSERT_BUTTON_NAME'',​ respectiv ''​LANGUAGE''​ din interfața ''​Constants''​),​ se obține denumirea limbii (ca valoare atașată parametrului,​ prin invocarea metodei ''​request.getParameter(parameter)''​),​ se verifică dacă aceasta nu este conținută în lista de limbi în funcție de care se face filtrarea și, în caz afirmativ, este adăugată la listă, marcându-se faptul că lista de filtre a fost modificată (parametrul ''​filterChange''​ de tip ''​boolean''​);​
-  * pentru parametrii având denumirea de tipul ''​delete_language:​ _{language_name}''​ (valori conținute de constantele ''​DELETE_BUTTON_NAME'',​ respectiv ''​LANGUAGE''​ din interfața ''​Constants''​),​ se obține denumirea limbii (ca valoare atașată parametrului, ​prin invocarea metodei ''​request.getParameter(parameter)''​), se verifică dacă aceasta este conținută în lista de limbi în funcție de care se face filtrarea și, în caz afirmativ, este ștearsă din listă, marcându-se faptul că lista de filtre a fost modificată (parametrul ''​filterChange''​ de tip ''​boolean''​).+  * pentru parametrii având denumirea de tipul ''​delete_language:​ _{language_name}''​ (valori conținute de constantele ''​DELETE_BUTTON_NAME'',​ respectiv ''​LANGUAGE''​ din interfața ''​Constants''​),​ se obține denumirea limbii (prin parsarea denumirii parametrului), se verifică dacă aceasta este conținută în lista de limbi în funcție de care se face filtrarea și, în caz afirmativ, este ștearsă din listă, marcându-se faptul că lista de filtre a fost modificată (parametrul ''​filterChange''​ de tip ''​boolean''​).
  
 <note tip>Se poate utiliza ca model implementarea corespunzătoare filtrării în funcție de formatul de prezentare a cărții.</​note>​ <note tip>Se poate utiliza ca model implementarea corespunzătoare filtrării în funcție de formatul de prezentare a cărții.</​note>​
 </​spoiler>​ </​spoiler>​
  
-**8.** În pachetul ''​ro.pub.cs.aipi.lab04.servlets'',​ în clasa ''​ClientServlet''​ să se completeze metoda ''​doPost()''​ pentru a crea conţinutul coşului de cumpărături,​ ţinând cont de situaţia în care pentru un produs deja existent să se poate actualiza cantitatea, astfel: dacă un produs există deja în coşul de cumpărături,​ cantitatea respectivă va fi suprascrisă,​ iar dacă aceasta este 0, produsul va fi şters din coşul de cumpărături.+**8.** În pachetul ''​ro.pub.cs.aipi.lab05.servlets'',​ în clasa ''​ClientServlet''​ să se completeze metoda ''​doPost()''​ pentru a crea conţinutul coşului de cumpărături,​ ţinând cont de situaţia în care pentru un produs deja existent să se poate actualiza cantitatea, astfel: dacă un produs există deja în coşul de cumpărături,​ cantitatea respectivă va fi suprascrisă,​ iar dacă aceasta este 0, produsul va fi şters din coşul de cumpărături.
  
 <​spoiler|Indicații de Rezolvare>​ <​spoiler|Indicații de Rezolvare>​
 În cazul în care se apasă un buton atașat unui câmp text pentru precizarea unei cantități pentru un anumit format de prezentare a unei cărți, este necesar să se realizeze următoarele operații: În cazul în care se apasă un buton atașat unui câmp text pentru precizarea unei cantități pentru un anumit format de prezentare a unei cărți, este necesar să se realizeze următoarele operații:
-  * se identifică identificatorul formatului de prezentare a cărții și cantitatea corespunzătoare:​+  * se determină identificatorul formatului de prezentare a cărții și cantitatea corespunzătoare:​
  
 {{ :​laboratoare:​laborator04:​activitate_de_laborator_exercitiu08.png?​nolink&​700 }} {{ :​laboratoare:​laborator04:​activitate_de_laborator_exercitiu08.png?​nolink&​700 }}
  
-**a)** **butonul** are denumirea ''​insert_shoppingcart_book_presentation_id''​ unde ''​book_presentation_id''​ reprezintă identificatorul formatului de prezentare a cărții (de exemplu, ''​insert_shoppingcart_1''​ pentru formatul de identificare a cărții cu identificatorul 1); prin parsarea denumirii acestui parametru se obține identificatorul formatului de prezentare a cărții: <code java>+**a)** **butonul** are denumirea ''​insert_shoppingcart_{book_presentation_id}''​ unde ''​book_presentation_id''​ reprezintă identificatorul formatului de prezentare a cărții (de exemplu, ''​insert_shoppingcart_1''​ pentru formatul de identificare a cărții cu identificatorul 1); prin parsarea denumirii acestui parametru se obține identificatorul formatului de prezentare a cărții: <code java>
 if (parameter.startsWith(Constants.INSERT_BUTTON_NAME.toLowerCase() + "​_"​ + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "​_"​) && parameter.endsWith("​.x"​)) { if (parameter.startsWith(Constants.INSERT_BUTTON_NAME.toLowerCase() + "​_"​ + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "​_"​) && parameter.endsWith("​.x"​)) {
   String bookPresentationId = parameter.substring(parameter.lastIndexOf("​_"​) + 1, parameter.indexOf("​.x"​));​   String bookPresentationId = parameter.substring(parameter.lastIndexOf("​_"​) + 1, parameter.indexOf("​.x"​));​
Line 1413: Line 1470:
 </​code>​ </​code>​
 <note tip>​Pentru un element de tip ''<​input>''​ având atributul ''​type''​ cu valoarea ''​submit'',​ se transmit ca parametrii coordonatele la care se găsește mouse-ul în momentul în care se produce evenimentul de tip apăsare, acestea având aceeași denumire, sufixată de ''​.x'',​ respectiv ''​.y''​. Este important ca un singur parametru să fie procesat, în acest caz.</​note>​ <note tip>​Pentru un element de tip ''<​input>''​ având atributul ''​type''​ cu valoarea ''​submit'',​ se transmit ca parametrii coordonatele la care se găsește mouse-ul în momentul în care se produce evenimentul de tip apăsare, acestea având aceeași denumire, sufixată de ''​.x'',​ respectiv ''​.y''​. Este important ca un singur parametru să fie procesat, în acest caz.</​note>​
-**b)** **câmpul text** ce conține cantitatea corespunzătoare are denumirea ''​copies_shoppingcart_book_presentation_id''​ unde ''​book_presentation_id''​ reprezintă identificatorul formatului de prezentare a cărții (de exemplu, ''​copies_shoppingcart_1''​ pentru formatul de identificare a cărții cu identificatorul 1); valoarea corespunzătoare acestui parametru reprezintă cantitatea solicitată:​ <code java>+**b)** **câmpul text** ce conține cantitatea corespunzătoare are denumirea ''​copies_shoppingcart_{book_presentation_id}''​ unde ''​book_presentation_id''​ reprezintă identificatorul formatului de prezentare a cărții (de exemplu, ''​copies_shoppingcart_1''​ pentru formatul de identificare a cărții cu identificatorul 1); valoarea corespunzătoare acestui parametru reprezintă cantitatea solicitată:​ <code java>
 if (parameter.startsWith(Constants.INSERT_BUTTON_NAME.toLowerCase() + "​_"​ + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "​_"​) && parameter.endsWith("​.x"​)) { if (parameter.startsWith(Constants.INSERT_BUTTON_NAME.toLowerCase() + "​_"​ + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "​_"​) && parameter.endsWith("​.x"​)) {
   String quantity = request.getParameter(Constants.COPIES.toLowerCase() + "​_"​ + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "​_"​ + bookPresentationId);​   String quantity = request.getParameter(Constants.COPIES.toLowerCase() + "​_"​ + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "​_"​ + bookPresentationId);​
Line 1424: Line 1481:
       * în situația în care cantitatea este nulă, aceasta este ștearsă;       * în situația în care cantitatea este nulă, aceasta este ștearsă;
     * dacă nu se identifică un element având același identificator al formatului de prezentare a cărții, acesta este adăugată.     * dacă nu se identifică un element având același identificator al formatului de prezentare a cărții, acesta este adăugată.
 +
 +<note important>​
 +Obiectul ''​shoppingCart''​ astfel modificat trebuie să fie transmis prin intermediul sesiunii pentru a fi persistent, având în vedere faptul că protocolul HTTP nu reține și starea.
 +<code java>
 +session.setAttribute(Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()),​ shoppingCart);​
 +</​code>​
 +</​note>​
 </​spoiler>​ </​spoiler>​
  
-**9.** În pachetul ​''​ro.pub.cs.aipi.lab04.graphicuserinterface'',​ în clasa ''​ClientGraphicUserInterface'',​ să se completeze metoda ''​displayClientGraphicUserInterface()''​ astfel încât să se vizualizeze ​coţinutul coşului de cumpărături. Se va afişa numărul de exemplare comandate, titlul cărţii, formatul de prezentare și limba, precum şi suma pentru fiecare produs în parte, respectiv preţul total pentru întregul coş de cumpărături.+**9.** În pagina ​''​client.jsp'',​ să se implementeze funcționalitatea necesară pentru a se vizualiza ​coţinutul coşului de cumpărături. Se va afişa numărul de exemplare comandate, titlul cărţii, formatul de prezentare și limba, precum şi suma pentru fiecare produs în parte, respectiv preţul total pentru întregul coş de cumpărături.
  
 {{ :​laboratoare:​laborator04:​activitate_de_laborator_exercitiu09.png?​nolink }} {{ :​laboratoare:​laborator04:​activitate_de_laborator_exercitiu09.png?​nolink }}
  
 <​spoiler|Indicații de Rezolvare>​ <​spoiler|Indicații de Rezolvare>​
-Se iterează asupra conținutului coșului de cumpărături (obiectul ''​shoppingCart''​),​ determinându-se,​ pentru fiecare element, identificatorul formatului de prezentare (atributul) și cantitatea (valoarea).+Se verifică dacă lista corespunzătoare coșului de cumpărături,​ accesibilă în atributul ''​shoppingCart'',​ conține sau nu elemente. În acest scop se va folosi un element [[http://​www.tutorialspoint.com/​jsp/​jstl_core_choose_tag.htm|<​c:​choose>​]]:​ 
 +  * în cazul în care lista nu este vidă (condiția de verificare este ''<​c:​when test="​${not empty shoppingCart}">''​),​ se afișează conținutul coșului de cumpărături;​ 
 +  * în cazul în care lista este vidă (condiția de verificare este ''<​c:​otherwise>''​),​ se afișează mesajul conținut de constanta ''​EMPTY_CART'',​ definită în interfața ''​Constants''​. 
 + 
 +<​code>​ 
 +<​c:​choose>​ 
 +  <c:when test="​${not empty shoppingCart}">​ 
 +    <%-- display shopping cart content --%> 
 +  </​c:​when>​ 
 +  <​c:​otherwise>​ 
 +    <%-- display Constants.EMPTY_CART message --%> 
 +  </​c:​otherwise>​ 
 +</​c:​choose>​ 
 +</​code>​ 
 + 
 +Se iterează asupra conținutului coșului de cumpărături (obiectul ''​shoppingCart''​),​ determinându-se,​ pentru fiecare element, identificatorul formatului de prezentare (atributul) și cantitatea (valoarea). ​Pentru a crea un atribut și pentru a-l inițializa cu o anumită valoare, se poate folosi eticheta [[http://​www.tutorialspoint.com/​jsp/​jstl_core_set_tag.htm|<​c:​set>​]]. 
 + 
 +<​code>​ 
 +<​c:​forEach var="​shoppingCartContent"​ items="​${shoppingCart}">​ 
 +  <c:set var="​bookPresentationIdentifier"​ value="​${shoppingCartContent.attribute}"​ /> 
 +  <c:set var="​quantity"​ value="​${shoppingCartContent.value}"​ /> 
 +  <%-- do other processing --%> 
 +</​c:​forEach>​ 
 +</​code>​
  
 Prețul unitar pentru un format de prezentare poate fi obținut apelând metoda ''​getPrice()''​ din clasa ''​BookPresentationManager'',​ ce primește ca argument identificatorul formatului de prezentare respectiv. Prețul unitar pentru un format de prezentare poate fi obținut apelând metoda ''​getPrice()''​ din clasa ''​BookPresentationManager'',​ ce primește ca argument identificatorul formatului de prezentare respectiv.
Line 1437: Line 1524:
 Informațiile cu privire la un format de prezentare (titlul, formatul de prezentare și limba) pot fi obținute apelând metoda ''​getInformation()''​ din clasa ''​BookPresentationManager'',​ ce primește ca argument identificatorul formatului de prezentare respectiv. Acesta întoarce o listă de obiecte de tip șir de caractere. Informațiile cu privire la un format de prezentare (titlul, formatul de prezentare și limba) pot fi obținute apelând metoda ''​getInformation()''​ din clasa ''​BookPresentationManager'',​ ce primește ca argument identificatorul formatului de prezentare respectiv. Acesta întoarce o listă de obiecte de tip șir de caractere.
  
-Este necesar să se calculeze și prețul total al coșului de cumpărături.+Instanțierea unui obiect de tipul ''​BookPresentationManager'',​ necesar pentru invocarea metodelor ce furnizează informațiile ce se doresc a fi afișate, se face prin intermediul acțiunii [[http://​www.tutorialspoint.com/​jsp/​jsp_java_beans.htm|<​jsp:​useBean>​]]. 
 + 
 +<​code>​ 
 +<​jsp:​useBean id="​bookPresentationManager"​ class="​ro.pub.cs.aipi.lab05.businesslogic.BookPresentationManager"​ /> 
 +</​code>​ 
 + 
 +Apelul metodelor ''​getPrice()'',​ respectiv ''​getInformation()''​ va fi realizată în cadrul unei expresii (scriplet), din care trebuie accesată valoarea atributului ''​bookPresentationIdentifier''​ definit în contextul paginii JSP. În acest scop, va fi utilizată metoda [[https://​tomcat.apache.org/​tomcat-8.0-doc/​jspapi/​javax/​servlet/​jsp/​JspContext.html#​getAttribute%28java.lang.String%29|getAttribute()]] a obiectului implicit ''​pageContext''​ (de tipul [[https://​tomcat.apache.org/​tomcat-8.0-doc/​jspapi/​javax/​servlet/​jsp/​PageContext.html|PageContext]]). 
 + 
 +<​code>​ 
 +<c:set var="​currentBookPrice"​ scope="​request"​ value="<​%= bookPresentationManager.getPrice(Long.parseLong(pageContext.getAttribute("​bookPresentationIdentifier"​).toString())) %>" /> 
 +<c:set var="​currentBookInformation"​ scope="​request"​ value="<​%= bookPresentationManager.getInformation(Long.parseLong(pageContext.getAttribute("​bookPresentationIdentifier"​).toString())) %>" />   
 +</​code>​ 
 + 
 +Este necesar să se calculeze și prețul total al coșului de cumpărături, într-un atribut al paginii JSP, prin însumarea tuturor valorilor corespunzătoare volumelor care se doresc a fi achiziționate.
  
 Prezentarea se va face în cadrul unui tabel (element de tip [[http://​www.w3schools.com/​tags/​tag_table.asp|<​table>​]]),​ datele corespunzătoare unui obiect din coșul de cumpărături fiind incluse pe o linie a acestuia (''<​tr><​td>​...</​td></​tr>''​). Prezentarea se va face în cadrul unui tabel (element de tip [[http://​www.w3schools.com/​tags/​tag_table.asp|<​table>​]]),​ datele corespunzătoare unui obiect din coșul de cumpărături fiind incluse pe o linie a acestuia (''<​tr><​td>​...</​td></​tr>''​).
 </​spoiler>​ </​spoiler>​
  
-**10.** În pachetul ​''​ro.pub.cs.aipi.lab04.graphicuserinterface'', ​în clasa ''​ClientGraphicUserInterface''​ să se completeze metoda ''​displayClientGraphicUserInterface()''​ astfel încât ​să se adauge două butoane prin care se poate anula, respectiv finaliza o comandă, în condițiile în care există produse în coșul de cumpărături.+**10.** În pagina ​''​client.jsp'',​ să se adauge două butoane prin care se poate anula, respectiv finaliza o comandă, în condițiile în care există produse în coșul de cumpărături.
  
 <​spoiler|Indicații de Rezolvare>​ <​spoiler|Indicații de Rezolvare>​
Line 1449: Line 1549:
   * ''​shopping_cart_accept.png'';​   * ''​shopping_cart_accept.png'';​
  
-Butoanele vor fi incluse în cadrul unui element de tip [[http://​www.w3schools.com/​tags/​tag_input.asp|<​input>​]],​ având atributul ''​type''​ cu valoarea ''​image''​ și denumirile ''​cancelcommand'',​ respectiv ''​completecommand''​ (valori conținute de constantele ''​CANCEL_COMMAND''​ și ''​COMPLETE_COMMAND''​ din interfața ''​Constants'',​ pentru care se elimină spațiile și se folosesc numai minuscule). Locațiile la care se găsesc resursele ce vor fi afișate vor fi precizate în cadrul atributului ''​src''​.+Butoanele vor fi incluse în cadrul unui element de tip [[http://​www.w3schools.com/​tags/​tag_input.asp|<​input>​]],​ având atributul ''​type''​ cu valoarea ''​image''​ și denumirile ''​cancelcommand'',​ respectiv ''​completecommand''​ (valori conținute de constantele ''​CANCEL_COMMAND''​ și ''​COMPLETE_COMMAND''​ din interfața ''​Constants'',​ pentru care se elimină spațiile și se folosesc numai minuscule). Pentru a se obține aceste valori, vor fi utilizate funcțiile [[http://​www.tutorialspoint.com/​jsp/​jstl_function_tolowercase.htm|fn:​toLowerCase()]],​ respectiv [[http://​www.tutorialspoint.com/​jsp/​jstl_function_replace.htm|fn:​replace()]],​ după ce s-au obținut valorile corespunzătoare constantelor definite în interfața ''​Constants''​. Locațiile la care se găsesc resursele ce vor fi afișate vor fi precizate în cadrul atributului ''​src''​.
 </​spoiler>​ </​spoiler>​
  
-**11.** În pachetul ''​ro.pub.cs.aipi.lab07.servlets'',​ în clasa ''​ClientServlet'',​ metoda ''​doPost()'',​ să se implementeze operaţiile de anulare, respectiv finalizare a unei comenzi.+**11.** În pachetul ''​ro.pub.cs.aipi.lab04.servlets'',​ în clasa ''​ClientServlet'',​ metoda ''​doPost()'',​ să se implementeze operaţiile de anulare, respectiv finalizare a unei comenzi.
  
 <​spoiler|Indicații de Rezolvare>​ <​spoiler|Indicații de Rezolvare>​
Line 1465: Line 1565:
   * se iterează asupra conținutului coșului de cumpărături (obiectul ''​shoppingCart''​):​   * se iterează asupra conținutului coșului de cumpărături (obiectul ''​shoppingCart''​):​
     * se obține identificatorul formatului de prezentare a cărții (atributul),​ cantitatea (valoarea) și stocul corespunzător,​ așa cum este reținut în tabela ''​book_presentation''​ (prin apelul metodei ''​getStockpile()''​) din clasa ''​BookPresentationManager''​);​     * se obține identificatorul formatului de prezentare a cărții (atributul),​ cantitatea (valoarea) și stocul corespunzător,​ așa cum este reținut în tabela ''​book_presentation''​ (prin apelul metodei ''​getStockpile()''​) din clasa ''​BookPresentationManager''​);​
-    * se compară numărul de exemplare din coşul de cumpărături cu stocul existent şi în situația în care comanda poate fi satisfăcută,​ se actualizează stocul (se apelează metoda ''​update()''​ din clasa ''​BookPresentationManager''​ care primește ca parametri atât atributul cât și valoarea care trebuie să fie modificate);​ +    * se compară numărul de exemplare din coşul de cumpărături cu stocul existent şi în situația în care comanda poate fi satisfăcută,​ se actualizează stocul (se apelează metoda ''​update()''​ din clasa ''​BookPresentationManager''​ care primește ca parametri atât atributul cât și valoarea care trebuie să fie modificate);​ se adaugă o înregistrare în tabela ''​invoice_line'';​ se va folosi metoda ''​create()''​ din cadrul clasei ''​InvoiceLineManager''​ pentru care trebuie precizate valorile ce vor fi adăugate:
-    * se adaugă o înregistrare în tabela ''​invoice_line'';​ se va folosi metoda ''​create()''​ din cadrul clasei ''​InvoiceLineManager''​ pentru care trebuie precizate valorile ce vor fi adăugate:+
       * identificatorul facturii (câmpul ''​invoice_header_id''​),​ determinat anterior;       * identificatorul facturii (câmpul ''​invoice_header_id''​),​ determinat anterior;
       * identificatorul formatului de prezentare a cărții (câmpul ''​book_presentation_id''​);​       * identificatorul formatului de prezentare a cărții (câmpul ''​book_presentation_id''​);​
       * cantitatea (câmpul ''​quantity''​);​       * cantitatea (câmpul ''​quantity''​);​
 +    * altfel, se adaugă un mesaj de eroare care va fi afișat în cadrul paginii JSP;
   * se goleşte coşul de cumpărături.   * se goleşte coşul de cumpărături.
- 
-<note important>​ 
-În situația în care sunt realizate modificări la nivelul coșului de cumpărături (pe obiectul ''​shoppingCart''​),​ starea acestuia va trebui reținută în cadrul sesiunii, printr-un apel de tipul: <code java> 
-session.setAttribute(Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()),​ shoppingCart);​ 
-</​code>​ 
-</​note>​ 
 </​spoiler>​ </​spoiler>​
  
Line 1484: Line 1578:
  
 <​spoiler|Indicații de Rezolvare>​ <​spoiler|Indicații de Rezolvare>​
-În clasa ''​ClientGraphicUserInterface'',​ se afișează un element de tip [[http://​www.w3schools.com/​tags/​tag_input.asp|<​input>​]],​ având atributul ''​type''​ cu valoarea ''​image''​ și denumirea ''​signout''​ (valoare reținută de constanta ''​SIGNOUT''​ din interfața ''​Constants''​). Resursa grafică se regăsește în directorul ''​images'',​ în subdirectorul ''​user_interface'',​ având denumirea ''​signout.png''​. +În pagina ​''​client.jsp'',​ se afișează un element de tip [[http://​www.w3schools.com/​tags/​tag_input.asp|<​input>​]],​ având atributul ''​type''​ cu valoarea ''​image''​ și denumirea ''​signout''​ (valoare reținută de constanta ''​SIGNOUT''​ din interfața ''​Constants''​). Resursa grafică se regăsește în directorul ''​images'',​ în subdirectorul ''​user_interface'',​ având denumirea ''​signout.png''​.
  
 În clasa ''​ClientServlet'',​ în cazul în care a fost apăsat butonul pentru operația de deautentificare:​ În clasa ''​ClientServlet'',​ în cazul în care a fost apăsat butonul pentru operația de deautentificare:​
Line 1502: Line 1595:
 </​code>​ </​code>​
  
-<note tip>Se poate utiliza ca model implementarea din cadrul paginii de administrator (clasele ​''​AdministratorServlet''​ / ''​AdministratorGraphicUserInterface''​).</​note>​+<note tip>Se poate utiliza ca model implementarea din cadrul paginii de administrator (clasa ''​AdministratorServlet''​ / pagina ​''​administrator.jsp''​).</​note>​
 </​spoiler>​ </​spoiler>​
  
Line 1523: Line 1616:
 ===== Soluții ===== ===== Soluții =====
  
-TODO+[[https://​github.com/​aipi2015/​Laborator05/​tree/​master/​solutions/​eclipse/​05-BookStore-JSP|Proiect Eclipse]]\\  
 +[[https://​github.com/​aipi2015/​Laborator05/​tree/​master/​solutions/​netbeans/​05-BookStore-JSP|Proiect NetBeans]]
laboratoare/laborator05.1447969531.txt.gz · Last modified: 2015/11/19 23:45 by Andrei Roșu-Cojocaru
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0