Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
|
laboratoare:laborator05 [2015/08/29 18:05] Andrei Roșu-Cojocaru created |
laboratoare:laborator05 [2015/11/25 20:00] (current) Andrei Roșu-Cojocaru |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== Laborator 05 ====== | ====== Laborator 05 ====== | ||
| - | ====== Construirea unui serviciu web folosind tehnologia JAX-WS ====== | + | ====== Realizarea de aplicații web folosind JavaServer Pages ====== |
| ===== Obiective ==== | ===== Obiective ==== | ||
| - | * descrierea tipurilor de servicii web ce pot fi dezvoltate folosind limbajul de programare Java și identificarea oportunității folosirii acestora; | + | * descrierea funcționalității pe care o pune la dispoziție tehnologia JavaServer Pages și a avantajelor pe care le oferă în comparație cu alte tehnologii similare; |
| - | * înţelegerea arhitecturii pe care o oferă tehnologia JAX-WS pentru dezvoltarea unui serviciu web, precum şi mecanismul prin care sunt împachetate obiectele spre a fi transmise prin infrastructura de comunicaţie; | + | * înţelegerea mecanismului prin care este generat răspunsul la o cerere pentru o pagină Internet solicitată din browser, în cazul folosirii de pagini JSP; |
| - | * proiectarea unor structuri de date (clase) care să poată fi stocate sub formă de scheme XML; | + | * integrarea unei aplicații web ce folosește Java Servlets / JavaServer Pages în contextul serverului Apache Tomcat; |
| - | * dezvoltarea unui serviciu web folosind tehnologia JAX-WS care să pună la dispoziție mai multe funcționalități la distanță, asigurând totodată persistența informațiilor; | + | * implementarea operațiilor corespunzătoare ciclului de viață a unei pagini JSP; |
| - | * folosirea unui serviciu web dezvoltat prin tehnologia JAX-WS prin invocarea metodelor implementate; | + | * proiectarea unei aplicații web ce folosește Java Servlets / JavaServer Pages potrivit modelului arhitectural adecvat specificațiilor funcționale; |
| - | * utilizarea unui server de aplicații care să găzduiască serviciul web. | + | * folosirea elementelor componente din structura unei pagini JSP (directive, acțiuni, scripleți, expresii, declarații, obiecte implicite) pentru implementarea unor aspecte de logica aplicației ce nu pot fi delegate către Java Servlets; |
| + | * utilizarea unor biblioteci de etichete (predefinite - JSTL sau definite de utilizator) / API-uri (JavaMail / Java Activation Framework) / EL (Expression Language) pentru dezvoltarea unor funcționalități complexe; | ||
| ===== Cuvinte Cheie ==== | ===== Cuvinte Cheie ==== | ||
| - | serviciu web, JAX-WS, JAX-RS, XML, SOAP, WSDL, UDDI, HTTP, URI, MIME, AJAX, DWR, endpoint, SEI, JAXB, xjc, schemagen, XSD, GlassFish open-source server | + | JavaServer Pages, web application, html, xml, svg, wml, markup, Java Beans, Apache Tomcat 8.x, JSP life cycle, parse exception, jasper exception, client-server model, N-tier model, model-view-controller, directive, action, scriplet, expression, declaration, implicit objects, cookie, session, filter, file upload, resource invocation, email managing, expression language, instant evaluation, lazy evaluation, JavaServer Faces, JSTL, custom tags |
| - | ===== Materiale Ajutătoare ===== | + | ===== Materiale Ajutătoare ====== |
| - | {{ :laboratoare:laborator06:aipi2014-lab06-slides.pdf }} | + | TODO |
| - | {{ :laboratoare:laborator06:aipi2014-lab06-slides-3pp.pdf }} | + | ===== Tehnologia JavaServer Pages - aspecte generale ===== |
| - | ===== Tipuri de servicii web și implementarea lor folosind Java ====== | + | JavaServer Pages este o tehnologie pentru realizarea de aplicații Internet generate dinamic şi bazate pe HTML, XML sau alte tipuri de documente. A fost lansată pe piaţă de compania Sun Microsystems în anul 1999 ca răspuns la tehnologiile PHP şi ASP, demonstrând faptul că Java este un limbaj de programare suficient de robust pentru a răspunde la provocările web-ului. |
| - | Un serviciu web reprezintă o funcţionalitate implementată în cadrul unei aplicaţii, accesibilă printr-o reţea de calculatoare (cel mai frecvent prin Internet, folosind protocolul HTTP), oferind interoperabilitate între programe ce rulează pe platforme diferite. O caracteristică a serviciilor web este extensibilitatea şi descrierea funcţionalităţii într-un limbaj ce poate fi procesat automat, astfel încât să poată fi prelucrat cu uşurinţă. Asocierea (slab cuplată) a mai multor servicii web se urmăreşte pentru rezolvarea unor probleme complexe. Astfel, programe ca oferă funcţionalităţi de bază pot interacţiona pentru a oferi servicii sofisticate, cu valoare adăugată. Comunicaţia între entităţile implicate în procesul de implementare şi interogare a serviciilor web este realizată prin mesaje, ceea ce nu presupune cunoaşterea capabilităţilor de care dispun platformele pe care rulează acestea. De regulă, arhitectura după care sunt modelate serviciile web este cea de client-server. | + | <note>Dacă tehnologia JavaServer Pages este comparabilă cu PHP (cu excepţia eficienţei), mai ales de când limbajul a fost dezvoltat în direcţia orientării pe obiecte, în cazul celorlalte tehnologii, JSP prezintă o serie de avantaje. Faţă de ASP .NET, avantajul tehnologiei JSP rezultă din faptul că aceasta este construită peste limbajul de programare Java, mai puternic şi mai uşor de utilizat decât limbajele Microsoft, dispunând de o portabilitate mai mare atât în privinţa sistemelor de operare cât şi a serverelor de aplicaţii. JavaScript este util în generarea de cod HTML dinamic la nivelul clientului dar nu şi la nivelul serverului, mai ales când vine vorba de accesarea de resurse existente pe acesta. De asemenea, SSI (Server Side Includes) a fost proiectat pentru incluziuni destul de simple, nu pentru programe cu funcţionalităţi complexe. Utilizarea JSP este recomandată şi faţă de folosirea exclusivă a Java Servlets întrucât codul devine mult mai uşor de întreţinut, realizându-se totodată o delimitare netă între logica aplicaţiei şi nivelul de prezentare.</note> |
| - | Implementarea serviciilor web se poate face în mai multe moduri, distingându-se serviciile web de dimensiuni "mari" şi serviciile web fără stare (//eng.// RESTful web services). | + | Tehnologia JavaServer Pages e parte integrantă Java Enterprise Edition implementând de regulă intefaţa cu utilizatorul dintr-o aplicaţie web Java. |
| - | **Serviciile web de dimensiuni "mari"**, implementate în Java prin tehnologia JAX-WS, folosesc pentru comunicaţie mesaje XML care respectă standardul SOAP (Simple Object Access Protocol) – spre a descrie arhitectura şi formatul mesajelor. Operaţiile pe care le pun la dispoziţie serviciile pot fi procesate în mod automat, întrucât interfeţele (care le conţin) sunt descrise în limbajul WSDL (Web Services Description Language). Acesta este un limbaj bazat pe XML prin intermediul căruia sunt definite din punct de vedere sintactic interfețele ce includ funcționalitățile implementate de serviciul web. Atât standardul SOAP folosit pentru formatul mesajelor cât şi limbajul de definire a interfeţelor WSDL au fost adoptate pe scară largă. | + | O pagină JSP este un document text care cuprinde două tipuri de date: **statice** care pot fi descrise în orice format (HTML, XML, SVG, WML) – denumite şi elemente de adnotare (//eng.// markup) şi **dinamice**, care pot fi directive JSP şi scripleţi, adică blocuri de cod sursă Java (de obicei cuprinse între adnotările ''%%<%%%'' şi ''%%%>%%'') folosite pentru implementarea unor funcţionalităţi complexe, cum ar fi, de exemplu, comunicaţia cu o bază de date, reţinerea preferinţelor utilizatorilor, accesarea componentelor Java Beans, transferul controlului între pagini şi partajarea informaţiei între cereri, răspunsuri şi pagini. |
| - | Un serviciu web modelat după standardul SOAP trebuie să conţină următoarele elemente: | + | Funcţionalitatea pe care o pune la dispoziţie tehnologia JSP este aceeaşi cu a aplicaţiilor implementate folosind CGI (Common Gateway Interface), distingându-se de acestea prin performanţă îmbunătăţită (posibilitatea integrării de elemente dinamice în pagina HTML în loc să se folosească fişiere separate), compilarea înainte de plasarea în contextul serverului, posibilitatea accesării tuturor funcţionalităţilor oferite de interfeţele de programare Java (JDBC, JNDI, JAXP, EJB), utilizarea unui model care implică delegarea logicii aplicaţiei către Java Servlets. |
| - | * o interfaţă care descrie operaţiile pe care serviciul web le pune la dispoziţia utilizatorilor; se poate folosi WSDL pentru detalii cu privire la mesaje, operaţii, corespondenţe şi locaţia de la care se poate accesa serviciul web; | + | |
| - | <note tip>Mesajele SOAP pot fi procesate prin tehnologia JAX-WS și fără a se pune la dispoziția utilizatorilor specificația WSDL.</note> | + | <note>În cazul CGI/Perl este necesar ca serverul să încarce un interpretor şi un script de fiecare dată când o pagină este solicitată în browser.</note> |
| - | * arhitectura serviciului web trebuie să răspundă unor cerinţe complexe nonfuncţionale (spre exemplu: procesarea unor tranzacții, rezolvarea unor aspecte ce vizează securitatea, probleme de adresare, coordonare, încredere), stabilind o sintaxă pentru acestea; | + | Avantajele utilizării JavaServer Pages includ: |
| - | * atât procesarea cât şi invocarea operaţiilor trebuie să se facă asincron; există standarde care oferă suport pentru această infrastructură, cum ar fi WSRM (Web Services Reliable Messaging) sau API-uri ca JAX-WS. | + | * separarea logicii aplicaţiei de prezentare (întreţinerea este mai uşoară atât din partea programatorilor, cât şi a dezvoltatorilor web); logica aplicaţiei este folosită pentru a genera conţinutul dinamic şi poate fi realizată prin componente Java Beans, în timp ce interfaţa cu utilizatorul este formată prin etichete JSP; |
| + | * portabilitate (asigurată de limbajul de programare Java – aplicaţia web poate fi utilizată pe mai multe platforme cu arhitectură diferită fără a fi necesară modificarea lor); | ||
| + | * conţinutul dinamic care poate fi generat; | ||
| + | * se bazează pe tehnologia Java Servlets, astfel încât preia şi avantajele pe care le oferă aceasta; tehnologia JavaServer Pages reprezintă o abstractizare de nivel înalt a Java Servlets; totodată, în pagina JSP poate fi reutilizat codul care a fost dezvoltat într-un Java Servlet. | ||
| - | **Serviciile web fără stare** sunt adecvate unor scenarii de integrare ad-hoc, folosind standarde W3C sau IETF (ca HTTP, XML, URI, MIME) – deci o infrastructură mai accesibilă – ceea scade costul cu dezvoltarea, astfel că adoptarea lor impune mai puţine restricţii. Un test pentru a determina dacă un serviciu web este independent de stare constă în verificarea comportamentului acestuia în situația repornirii serverului care îl găzduiește. Sunt mai bine integrate cu HTTP decât serviciile bazate pe SOAP (nu mai sunt necesare mesaje în format XML sau descrieri ale serviciilor bazate pe WSDL). Serviciile web de tip REST-ful (//eng.// Representational State Transfer) includ informațiile cu privire funcționalitatea pe care o oferă în mesajele schimbate între client și server. | + | Deşi din punctul de vedere al programatorului un Java Servlet reprezintă o clasă Java (unde generarea elementelor de adnotare se face prin apelarea unor metode) iar o pagină JSP se aseamănă mai mult cu un document (unde conţinutul static este separat de conţinutul dinamic – generat de componente Java Beans sau etichete JSP), tehnologiile sunt echivalente. O pagină JSP este transformată într-un Java Servlet (care este compilat) responsabil de comunicaţia cu clientul şi de toate celelalte prelucrări. Modificările realizate asupra unei pagini JSP sunt detectate în mod automat, astfel încât atât procesul de transformare într-un Java Servlet cât şi procesul de compilare corespunzător sunt reluate atunci când se face o cerere pentru aceasta. |
| - | Situaţiile în care este utilă construirea unor servicii web fără stare este: | + | {{ :laboratoare:laborator05:01clientserverelationship.png?nolink&600 }} |
| - | * performanţa poate fi îmbunătăţită printr-o infrastructură de stocare (//eng.// caching system) atâta timp cât informaţiile oferite de serviciul web nu sunt generate în mod dinamic; | + | |
| - | <note tip>Implementarea infrastructurii de stocare trebuie să se facă ținând cont de limitările metodei HTTP GET, pentru cele mai multe dintre serverele de aplicații.</note> | + | Atunci când **1)** un client transmite (din browser) o cerere HTTP către server pentru o pagină .jsp, **2)** aceasta este transmisă mai departe motorului JSP care încarcă de pe disc resursa care a fost indicată prin intermediul URL-ului. Dacă pe server nu există un Java Servlet corespunzător celei mai recente versiuni a paginii respective, **3)** acesta este generat (prin instrucţiuni de tip ''println'' ce includ etichetele respective şi convertirea elementelor JSP în cod Java care implementează comportamentul dinamic al paginii) şi **4)** apoi compilat într-o clasă executabilă. Acest cod, căruia i se pasează cererea originală **5)** este rulat de motorul Java Servlet producând un rezultat în format HTML care este transmis serverului ca răspuns HTTP, acesta **6)** fiind pasat clientului care îl afişază în browser, ca şi când ar fi conţinut static. |
| - | * atât clientul cât şi serverul au o înţelegere (comună) cu privire la contextul şi conţinutul care este transmis în procesul de interacţiune dintre ele, întrucât nu există o interfaţă care să descrie (standardizat) informaţiile care sunt transmise; | + | {{ :laboratoare:laborator05:02JavaServletJSPgeneration.png?nolink&700 }} |
| - | <note>De regulă, producătorii de servicii web fără stare pun la dispoziţie şi unelte care descriu utilizatorilor interfaţa acestora în majoritatea limbajelor de programare folosite pe scară largă.</note> | + | ===== Integrarea JavaServer Pages cu serverul Apache Tomcat 8.x ===== |
| - | * lăţimea de bandă limitată este un aspect care trebuie luat în considerare întrucât serviciile web fără stare sunt mai frecvent folosite pentru dispozitive cum ar fi telefoane mobile sau PDA-uri; în această situaţie surplusul de informaţii conţinut de mesajele bazate pe XML (obiectele SOAP) limitează performanţa, implicând şi costuri mai ridicate; | + | În cazul unei aplicaţii web folosind tehnologia JSP, aceasta va fi plasată în directorul ''webapps''. |
| - | * integrarea cu diferite aplicaţii Internet se poate realiza cu uşurinţă folosind tehnologii precum JAX-RS sau AJAX (Asynchronous JavaScript with XML) ca şi utilitare ca DWR (Direct Web Remoting) spre a invoca serviciile dezvoltate; fiind expuse prin XML, serviciile web pot fi utilizate fără modificarea semnificativă a arhitecturii paginii Internet. | + | |
| - | Serviciile web de dimensiuni mari sunt folosite în probleme specifice aplicaţiilor integrate pentru întreprinderi, având cerinţe mai complexe în privinţa calităţii serviciilor, în timp ce serviciile web fără stare sunt folosite pentru probleme de interfaţare prin reţea. | + | Paginile ''.jsp'' se vor găsi în rădăcina directorului unde a fost dezvoltată aplicaţia web. Pagina care va fi afişată automat atunci când se solicită adresa: ''%%http://<server_IP>:<server_port>/<application_directory>/%%'' este ''index.jsp'' sau cea precizată prin elementul ''<welcome-file>'' din secţiunea ''<welcome-file-list>'' a fişierului de configurare ''web.xml''. Acesta va fi plasat în directorul ''WEB-INF'', specificându-se diferiţi parametrii ai aplicaţiei web (inclusiv despre clasele Java Servlet ce implementează logica aplicaţiei). De asemenea, în condiţiile în care sunt folosite metode din clase Java, acestea vor fi plasate într-un director ''WEB-INF/classes''. Este recomandat ca acestea să fie modularizate pe pachete pentru ca referirea lor să se poată realiza cu uşurinţă. Dacă se folosesc biblioteci speciale (în arhive ''.jar''), acestea trebuie incluse în ''WEB-INF/lib''. Astfel de biblioteci speciale pot fi "driver"-ul de conectare la baza de date precum şi biblioteca pentru accesarea funcţionalităţilor oferite de JSTL (JavaServer Pages Standard Tag Library). Deşi sursele aplicaţiei se pot găsi în orice fişier, este recomandat ca acestea să se găsească tot aici, într-un subdirector denumit ''src'' sau ''sources'', astfel încât să poată fi identificat cu uşurinţă, iar procesul de compilare al surselor şi de transfer al claselor (realizat înainte de operaţia de configurare – //eng.// deploy a aplicaţiei web) să nu implice un efort deosebit. |
| - | Tehnologia JAX-WS implementează cerinţe mai complexe referitoare la calitatea serviciilor (QoS – Quality of Service), frecvent întâlnite în aplicaţiile integrate pentru întreprinderi, oferind suport pentru mai multe protocoale care oferă standarde pentru securitate şi fiabilitate, asigurând interoperabilitatea între servere şi clienţi conforme cu aceste protocoale pentru servicii web. | + | Spre diferenţă de Java Servlets, nu este necesară realizarea configurării aplicaţiei web atunci când sunt realizate modificări asupra paginilor JSP, întrucât acestea sunt detectate automat, determinând generarea unor Java Servlets corespunzătoare atunci când paginile sunt accesate de către client. Repornirea serverului Apache Tomcat va fi necesară doar în cazul operării unor modificări pentru clasele Java ce sunt utilizate de aplicaţie, fiind necesară reîncărcarea lor (după ce compilarea lor este realizată de către programator). |
| - | Tehnologia JAX-RS facilitează procesul de dezvoltare a unor aplicaţii web conforme arhitecturii REST pentru a integra anumite proprietăţi în acestea precum: cuplarea slabă (dezvoltarea serverului se poate face fără afectarea clienţilor existenţi) sau scalabilitate, bazându-se pe o arhitectură simplă. Clienţii pot folosi o parte sau toate serviciile web puse la dispoziţie în timp ce serverul poate fi dezvoltat, integrându-le şi cu alte servicii web. | + | Clasele Java Servlet generate pentru fiecare aplicaţie pot fi vizualizate în ''%CATALINA_HOME%\work\Catalina\<server_IP>\<application_directory>\org\apache\jsp''. |
| - | ===== JAX-WS - aspecte generale ===== | + | Corespondentul unei pagini ''page.jsp'' va fi un Java Servlet ''page_jsp.java''. Tot aici vor fi plasate şi clasele obţinute prin compilarea acestor Java Servlets. Atât operaţia de transformare din pagină JSP în Java Servlet cât şi compilarea claselor Java Servlet generate este realizată automat de către serverul Apache Tomcat. |
| - | JAX-WS (Java API for XML Web Services) este o tehnologie Java folosită pentru dezvoltarea de servicii web şi de aplicaţii care le invocă, definit de JSR224, comunicaţia bazându-se pe XML. Utilizatorii pot dezvolta servicii web orientate pe mesaje sau pe apeluri la distanţă (RPC – Remote Procedure Call). | + | Datorită faptului că o cerere pentru o pagină JSP implică (în unele situaţii) transformarea într-un Java Servlet precum şi compilarea acestuia, vizualizarea acesteia se va face după o perioadă mai mare decât în situaţia când aceste prelucrări nu mai trebuie realizate. De asemenea, trebuie avută în vedere situaţia în care o astfel de operaţie eşuează, astfel încât în browser sunt afişate excepţiile generate în loc de conţinutul paginii solicitate. |
| - | O invocare a unui serviciu web este realizată prin protocolul SOAP, care este bazat pe XML. Specificaţia SOAP include structura antetelor, regulile de codificare şi convenţiile pentru reprezentarea invocărilor şi răspunsurilor serviciului web. Astfel, invocările şi răspunsurile sunt transmise ca mesaje SOAP prin protocolul HTTP. Deşi mesajele SOAP sunt complexe, acest fapt este ascuns prin API-ul JAX-WS. Pe server sunt definite operaţiile serviciului web în cadrul unei interfeţe precum şi implementarea lor. Un client crează un obiect delegat (obiect local reprezentând serviciul) şi invocă metodele puse la dispoziţie de serviciul web prin intermediul acestuia. Programatorul nu trebuie să genereze mesaje SOAP şi nici să le analizeze, întrucât sistemul de execuţie JAX-WS converteşte invocările şi răspunsurile în şi din mesaje SOAP. | + | Versiunea Apache Tomcat 8.0.28 suportă specificaţia JSP 2.3 şi EL 3.0. |
| - | Avantajele JAX-WS constau în independenţa de platformă a limbajului de programare Java şi în faptul că entităţile implicate în dezvoltarea şi accesarea serviciului web nu trebuie ruleze pe o platformă Java, întrucât sunt folosite tehnologii definite de W3C: HTTP, SOAP şi WSDL. WSDL specifică un format XML pentru descrierea unui serviciu ca un set de noduri din reţea care realizează anumite operaţii asupra mesajelor. | + | ===== Ciclul de viață al unei pagini JSP ===== |
| - | {{ :laboratoare:laborator06:figura01.png?nolink }} | + | O pagină JSP tratează cererile asemenea unui servlet. Acesta este motivul pentru care ciclul de viaţă (ca de altfel şi multe alte capabilităţi) al paginilor JSP (în special aspectele dinamice) este asemănător cu cel al tehnologiei Java Servlet. |
| - | ==== Exemplu ==== | + | În plus faţă de etapele caracteristice Java Servlets (creare, iniţializare, gestiune cereri şi răspunsuri, distrugere), mai există şi etapa de compilare. Atunci când o cerere este asociată unei pagini JSP, aceasta este tratată de un servlet special care verifică dacă servlet-ul asociat paginii JSP este mai vechi decât pagina în cauză, situaţie în care îl generează şi îl compilează. Astfel, un avantaj pe care îl au paginile JSP faţă de Java Servlets este că procesul de compilare este realizat automat. |
| - | În cele ce urmează, crearea unui serviciu web folosind tehnologia JAX-WS va fi ilustrată pe cazul particular al aplicaţii implementând funcţionalitatea unui serviciu de rezervare, al cărui comportament a fost descris pe larg în cadrul laboratorului anterior. | + | Odată ce pagina JSP a fost transformată şi compilată, servlet-ul corespunzător va urma ciclul de viaţă corespunzător (încărcarea claselor, instanţierea lor, apelul metodei ''init()'' pentru iniţializarea resurselor (partajate) şi încărcarea unor fişiere de configurare, execuţia (interacţiunea cu clientul şi realizarea procesărilor prin metoda ''service()''), precum şi apelul metodei ''destroy()'' dacă servlet-ul nu mai este necesar). Metodele (generate) se vor numi, în acest caz, ''_jspInit()'', ''_jspService()'', ''_jspDestroy()''. Metodele ''jspInit()'' şi ''jspDestroy()'' (apelate o singură dată în ciclul de viaţă al unei pagini JSP) pot fi suprascrise ca declaraţii JSP (cuprinse între ''%%<%!%%'' şi ''%%%>%%''). Nu se recomandă însă suprascrierea metodei ''_jspService()'' întrucât aceasta este generată în mod automat prin transformarea elementelor JSP în codul Java corespunzător, respectiv prin apelul metodei ''println()'' (a obiectului ''PrintWriter'' asociat) pentru generarea etichetelor. |
| - | ===== Proiectarea serviciului web ===== | + | <code java> |
| + | public void _jspInit() { | ||
| + | // ... | ||
| + | } | ||
| - | Un serviciu web dezvoltat cu JAX-WS este o clasă Java adnotată cu însemnarea ''@WebService'' din pachetul ''javax.jws.WebService'', aceasta fiind desemnată ca entitatea care deserveşte serviciul web respectiv (//eng.// endpoint). Aşadar, structura prin care este descris un serviciu web (SEI – Service Endpoint Interface / Implementation) este o intefaţă sau o clasă Java unde sunt declarate metodele pe care un client le poate invoca pentru un serviciu. | + | public void _jspDestroy() { |
| + | // ... | ||
| + | } | ||
| - | <note tip>Nu este obligatoriu să se definească o interfaţă (explicit) atunci când serviciul web este construit cu JAX-WS, întrucât funcţionalitatea sa este descrisă prin implementarea operaţiilor. Totuşi, folosind elementul ''endpointInterface'' în adnotarea ''@WebService'', se poate defini explicit interfaţa, definindu-se metodele la care utilizatorul are acces.</note> | + | public void _jspService (final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { |
| + | // ... | ||
| + | } | ||
| + | </code> | ||
| - | <file java Reservation.java> | + | {{ :laboratoare:laborator05:03JSPpagelifecycle.png?nolink&400 }} |
| - | import javax.jws.WebMethod; | + | |
| - | import javax.jws.WebParam; | + | |
| - | import javax.jws.WebService; | + | |
| - | @WebService(serviceName = "Reservation") | + | Toate aceste metode fac parte din interfaţa [[https://docs.oracle.com/javaee/7/api/javax/servlet/jsp/HttpJspPage.html|javax.servlet.HttpJspPage]]. |
| - | public class Reservation { | + | |
| - | public int numberOfSeats; | + | |
| - | public PersistentInterval timetable; | + | |
| - | public PersistentReservationData reservationData; | + | |
| - | + | ||
| - | public Reservation() { | + | |
| - | // ... | + | |
| - | } | + | |
| - | + | ||
| - | @WebMethod(operationName = "getTimeTable") | + | |
| - | public ArrayList<Interval> getTimeTable() { | + | |
| - | return persistentInterval2IntervalArrayList(timetable); | + | |
| - | } | + | |
| - | + | ||
| - | @WebMethod(operationName = "getAvailableSeats") | + | |
| - | public int getAvailableSeats(@WebParam(name = "interval") Interval interval) { | + | |
| - | int result = numberOfSeats; | + | |
| - | // ... | + | |
| - | return result; | + | |
| - | } | + | |
| - | + | ||
| - | @WebMethod(operationName = "makeReservation") | + | |
| - | public boolean makeReservation( | + | |
| - | @WebParam(name = "customerId") int customerId, | + | |
| - | @WebParam(name = "interval") Interval interval, | + | |
| - | @WebParam(name = "noOfSeatsRequired") int noOfSeatsRequired) { | + | |
| - | boolean result = false; | + | |
| - | // ... | + | |
| - | return result; | + | |
| - | } | + | |
| - | @WebMethod(operationName = "cancelReservation") | + | În cadrul procesului de compilare, motorul JSP verifică dacă este necesar să compileze pagina respectivă (în situaţia în care aceasta nu a fost niciodată compilată, sau eticheta de timp a servlet-ului corespunzător nu corespunde celei mai recente modificări), acestă operaţie fiind precedată de transformarea paginii, ce include şi parsarea acesteia. |
| - | public boolean cancelReservation( | + | |
| - | @WebParam(name = "customerId") int customerId, | + | |
| - | @WebParam(name = "interval") Interval interval) { | + | |
| - | boolean result = false; | + | |
| - | // ... | + | |
| - | return result; | + | |
| - | } | + | |
| - | } | + | |
| - | </file> | + | |
| - | Structurile (clasele, interfeţele) care definesc un serviciu web folosind tehnologia JAX-WS trebuie să îndeplinească mai multe condiţii: | + | Atât procesul de transformare şi cât şi procesul de compilare pot genera erori care sunt scoase în evidenţă doar atunci când pagina este accesată pentru prima dată: |
| - | * clasa care implementează serviciul web trebuie să fie adnotată cu însemnările ''javax.jws.WebService'' sau ''javax.jws.WebServiceProvider''; | + | * dacă eroarea apare în timpul transformării, serverul va întoarce excepţia ''ParseException'' iar clasa servlet va fi incompletă, astfel că ultima linie incompletă va fi un indicator către elementul JSP incorect; |
| - | * clasa care implementează serviciul web poate referi în mod explicit interfaţa care descrie acest serviciu web prin elementul ''endpointInterface'' al însemnării ''@WebService'', însă acest lucru nu este obligatoriu: dacă nu este întâlnit nici un element ''endpointInterface'' în însemnarea ''@WebService'', interfaţa care descrie serviciul web este definită implicit; | + | * dacă eroarea se produce atunci când pagina JSP este compilată (dacă avem o eroare de sintaxă în scriptlet), serverul va întoarce excepţia ''JasperException'' precum şi un mesaj care include numele servlet-ului asociat paginii JSP şi linia la care s-a constatat eroarea. |
| - | * metodele ce implementează funcţionalitatea serviciului web trebuie să fie publice şi nu trebuie să fie declarate ca fiind ''static'' sau ''final''; | + | |
| - | * metodele ce implementează funcţionalitatea serviciului web, ce sunt accesibile utilizatorilor trebuie să fie adnotate cu însemnarea ''javax.jws.WebMethod''; | + | |
| - | * metodele ce implementează funcţionalitatea serviciului web trebuie să aibă parametrii şi rezultate întoarse de tipuri compatibile cu JAXB; | + | |
| - | * clasa care implementează serviciul web nu trebuie să fie declarată ca fiind ''final'' şi nu trebuie să fie abstractă; | + | |
| - | * clasa care implementează serviciul web trebuie să implementeze un constructor public implicit; | + | |
| - | * clasa care implementează serviciul web nu trebuie să conţină metoda ''finalize()''; | + | |
| - | * clasa care implementează serviciul web poate folosi adnotaţiile ''javax.annotation.PostConstruct'' sau ''javax.annotation.PreDestroy'' pentru evenimente legate de ciclul de viaţă al serviciului web: | + | |
| - | * metoda ''@PreConstruct'' va fi invocată înainte ca structura care implementează serviciul web să răspundă la cereri din partea clienţilor; | + | |
| - | * metoda ''@PreDestroy'' va fi invocată înainte ca structura care defineşte serviciul web să fie îşi încheie activitatea. | + | |
| - | În exemplul de mai sus, clasa care implementează serviciul web, ''Reservation'', este adnotată ca fiind descriind operaţiile acestuia prin însemnarea ''@WebService(serviceName="Reservation")''. Clasa ''Reservation'' declară mai multe metode (''getTimetable()'', ''getAvailableSeats()'', ''makeReservation()'', ''cancelReservation()'', ''getReservation()''), fiecare fiind adnotate cu ''@WebMethod(operationName="")'' prin care acestea sunt făcute vizible către clienţi. Parametrii acestor metode accesibile la nivelul clienţilor trebuie să fie adnotate cu însemnarea ''@WebParam(name="")'', putându-se specifica un nume sugestiv pentru semnificaţia argumentelor. Totodată, este necesar ca implementarea să conţină şi un constructor implicit care va fi apelat atunci când un client face o invocare pentru o metodă asociată serviciului web respectiv. Pentru exemplul de faţă, este necesar ca în constructor să se construiască obiectul ''timetable''. Preluarea informaţiilor dintr-o sursă externă (fişier) pentru obţinerea acestui element trebuie să ţină cont de faptul că în urma operaţiei de dezvoltare (//eng.// deployment) a serviciului web, aplicaţia este plasată într-un context al serverului de aplicaţii care va pune la dispoziţie respectivul serviciu web, astfel încât amplasarea sursei externe trebuie să fie cunoscută ca locaţie (server web sau sistem de fişiere) în mod absolut şi nu relativ la adresa unde se găsesc clasele. | + | Atunci când se execută o pagină JSP pot apărea excepţii, acestea trebuind tratate separat, în cadrul unei pagini dedicate unei astfel de acţiuni: |
| - | Clasa ''javax.xml.ws.Endpoint'' pune la dispoziție mai multe metode statice prin intermediul cărora poate fi gestionat un serviciu web. Un astfel de obiect asociază o implementare a unui serviciu web, a cărui stare poate fi publicat sau nepublicat. Totodată, el încapsulează mai multe metadate, cum ar fi documentele WSDL și schemele XML, pe care le generează în funcție de adnotările din clasele ce conțin implementarea serviciului web, în cazul că acestea nu sunt furnizate explicit. | + | <code java> |
| + | <%@ page errorPage="errorpage.jsp" %> | ||
| + | </code> | ||
| - | Crearea și publicarea unui obiect de tip ''Endpoint'' se face prin metoda publică ''publish()'', care primește ca parametrii locația la care va fi disponibilă descrierea serviciului web (locația fișierului WSDL) precum și implementarea propriu-zisă a serviciului web: | + | Pentru ca excepţia (într-un obiect de tip [[http://docs.oracle.com/javaee/7/api/javax/servlet/jsp/JspException.html|javax.servlet.jsp.JspException]]) să fie disponibilă în cadrul paginii de eroare pentru a o trata, trebuie specificată, la începutul paginii de eroare, directiva: |
| <code java> | <code java> | ||
| - | public static Endpoint publish(String address, Object implementor) {} | + | <%@ page isErrorPage="true|false" %> |
| </code> | </code> | ||
| - | Un exemplu de utilizare a acestei metode poate fi: | + | În etapa de **iniţializare**, care se execută o singură dată (după crearea servletului asociat paginii JSP), este apelată metoda ''_jspInit()'' unde se realizează conexiunea la baza de date, sunt încărcate diferite resurse şi se fac alte operaţii ce ţin de configurarea aplicaţiei web. În general, aici sunt iniţializate obiectele pentru accesarea funcţionalităţilor puse la dispoziţie de diferite biblioteci (frecvent, Java Server Pages Standard Tag Library), însă programatorul are posibilitatea de a realiza propriile operaţii, prin suprascrierea metodei ''jspInit()'' care va fi inclusă în cadrul acestei funcţii. |
| + | |||
| + | Etapa de **execuţie** constă în generarea unui răspuns pentru fiecare cerere prin apelul metodei ''_jspService()''. Aceasta va trata fiecare dintre metodele HTTP prin care clientul comunică cu serverul (''GET'', ''POST'', ''PUT'', ''DELETE'', ''OPTIONS'', ''TRACE''). | ||
| + | |||
| + | În etapa de **distrugere**, corespunzătoare procesului de înlăturare a paginii JSP din container, este apelată metoda ''_jspDestroy()'' unde sunt eliberate resursele utilizate de aplicaţie, astfel încât acestea să fie procesate de modulul de gestiune a memoriei. În situaţia în care se doreşte eliberarea manuală a acelor resurse care au fost iniţializate (conexiunea la baza de date, diverse fişiere de configurare), poate fi suprascrisă metoda ''jspDestroy()'', conţinutul ei fiind copiat în cuprinsul funcţiei generate. | ||
| + | |||
| + | ===== Arhitectura unei aplicații Internet folosind JavaServer Pages ===== | ||
| + | |||
| + | Combinarea de cod Java cu etichete HTML oferă posibilitatea realizării de pagini cu conţinut dinamic, însă în cazul aplicaţiilor cu funcţionalitate complexă, procesul de întreţinere poate fi dificil, problema provenind în special din faptul că partea de logică a aplicaţiei (care este dezvoltată de programatori – implicând algoritmi şi interacţiune cu baza de date) nu este separată de partea de prezentare (realizată de regulă de dezvoltatori web – concentrându-se mai ales pe elemente de grafică). Arhitectura aplicaţiei JSP va reflecta raportul dintre aceste aspecte. | ||
| + | |||
| + | {{ :laboratoare:laborator05:04webapplicationarchitecture.png?nolink&800 }} | ||
| + | |||
| + | În modelul 1, logica aplicaţiei este implementată în clase Java (componente Java Beans) şi poate fi apelată din partea de prezentare realizată prin pagini JSP. Această soluţie este adecvată pentru cazul în care aplicaţia nu este foarte complexă, o problemă fiind constituită de faptul că toată comunicaţia cu clientul trebuie realizată din pagina JSP. O astfel de abordare se mai numeşte client-server, are avantajul simplităţii şi dezavantajul lipsei de scalabilitate. | ||
| + | |||
| + | În modelul 2 (denumit şi abordare pe N-niveluri datorită separării arhitecturii serverului pe mai multe niveluri), se respectă şablonul de proiectare Model View Controller unde servlet-ul se ocupă de cererea de la client, implementează logica aplicaţiei, realizând totodată şi instanţierea componentelor Java Beans. Pagina JSP obţine date de la componentele Java Beans şi transmite un răspuns către client, prelucrările fiind realizate în mod transparent. Acest tip de abordare e adoptat atunci când aplicaţia este mai complexă, caracterizându-se prin uşurinţa de întreţinere şi eficienţă. | ||
| + | |||
| + | Aşadar, în cadrul unei pagini JSP se utilizează o combinaţie între etichete HTML (sau XML) şi blocuri de cod sursă Java pentru generarea de elemente dinamice. Fiecare pagină JSP este compilată într-un servlet, acesta primind cererea şi transmiţând mai departe răspunsul. | ||
| + | |||
| + | O pagină JSP poate conţine etichete de prezentare (în limbajul HTML), etichete JSP standard şi etichete definite de utilizator. | ||
| + | |||
| + | JSP foloseşte ca etichete standard: | ||
| + | * directive; | ||
| + | * acţiuni; | ||
| + | * scripleţi: | ||
| + | * expresii; | ||
| + | * declaraţii. | ||
| + | |||
| + | {{ :laboratoare:laborator05:05JSPpagestructure.png?nolink&1024 }} | ||
| + | |||
| + | De asemenea, pot fi folosite **comentarii** care pot fi: | ||
| + | * comentarii JSP: acestea sunt ingorate de motorul JSP; <code java> | ||
| + | <%-- comentariu; --%> | ||
| + | </code> | ||
| + | * comentarii HTML: acestea sunt ignorate de browser; <code java> | ||
| + | <!-- comentariu --> | ||
| + | </code> | ||
| + | |||
| + | ==== Directive ==== | ||
| + | |||
| + | O **directivă** este o instrucţiune care indică informaţii generale despre pagina respectivă. Aceasta afectează întreaga structură a clasei servlet. Directiva oferă container-ului diverse informaţii cu privire la modul în care va gestiona anumite aspecte ale procesării paginii JSP. | ||
| <code java> | <code java> | ||
| - | Endpoint.publish("http://localhost:8080/reservation/Reservation", new Reservation()); | + | <%@ directive attribute="value" %> |
| </code> | </code> | ||
| - | <note tip>Metoda ''publish()'' nu este blocantă, astfel încât pot fi realizate și alte operații după crearea și publicarea unui serviciu web.</note> | + | Directivele pot avea un număr variabil de perechi atribut-valoare, acestea fiind separate prin virgulă. Spaţiile dintre ''%%<%@%%'' şi numele directivei, respectiv dintre ultima pereche atribut-valoare şi ''%%%>%%'' sunt opţionale. |
| + | Există trei tipuri de directive: | ||
| + | * ''%%<%@ page ... %>%%'' – defineşte atribute specifice paginii JSP, cum ar fi limbajul de programare pentru scripturi, pagina corespunzătoare erorilor şi cerinţe legate de stocarea temporară; | ||
| + | * ''%%<%@ include ... %>%%'' – include un fişier în cadrul etapei de transformare a paginii JSP în servletul corespunzător; | ||
| + | * ''%%<%@ taglib ... %>%%'' – defineşte o bibliotecă de etichete, conţinând acţiuni definite de utilizator, care vor fi utilizate în cadrul paginii. | ||
| - | <note tip>Opțional, metoda poate primi niște parametri de tip ''WebServiceFeature'' prin care se poate configura obiectul de tip ''Endpoint''.</note> | + | === Directiva page === |
| - | <note tip>În situația în care se folosește un sistem de gestiune a securității, este necesar ca aplicația să dețină permisiunea ''WebServicePermission("publishEndpoint")'', în caz contrar generându-se o excepție de tip ''SecurityException''.</note> | + | Directiva ''page'' este utilizată pentru a oferi containerului informaţii despre pagina JSP curentă. Cu toate că această directivă poate fi plasată oriunde în cadrul paginii, se recomandă ca ea să fie inclusă la început. |
| - | Un serviciu web care este publicat poate fi făcut indisponibil prin intermediul metodei ''Endpoint.stop()''. | + | Sintaxa acestei directive poate lua următoarele forme: |
| + | <code java> | ||
| + | <%@ page attribute="value" %> | ||
| + | </code> | ||
| - | ===== Utilizarea JAXB pentru conversia dintre clase Java și scheme XML ===== | + | <code java> |
| + | <jsp:directive.page attribute="value" /> | ||
| + | </code> | ||
| - | JAXB (Java Architecture for XML Binding) oferă o modalitate de conversie între aplicaţii dezvoltate în limbajul de programare Java şi scheme XML. Poate fi folosit independent sau împreună cu JAX-WS, oferind o modalitate de transmitere a mesajelor în cazul utilizării unor servicii web. Astfel, JAX-WS deleagă către JAXB maparea tipurilor din limbajul de programare Java (pentru parametri şi valori întoarse) cu definiţii XML. Dezvoltatorii serviciilor web nu trebuie să cunoască detaliile acestei corespondenţe, însă trebuie să cunoască faptul că nu orice clasă din limbajul de programare Java poate fi folosită drept parametru sau valoare întoarsă în JAX-WS, întrucât limbajul de programare Java oferă un set de tipuri de date mult mai bogat decât schemele XML. | + | Atributele suportate de directiva ''page'' sunt: |
| - | <columns 100% 50%> | + | | ''autoFlush'' | controlează comportamentul buffer-ului asociat servletului în cazul în care se umple (conţinutul său va fi golit automat – valoarea ''true'' (implicită) sau se generează o eroare – valoarea ''false''); se foloseşte de regulă în asociere cu atributul ''buffer'': <code java> |
| + | <%@ page buffer="8kb" autoFlush="true" %> | ||
| + | <%@ page autoFlush="false" %> | ||
| + | </code> | | ||
| + | | ''buffer'' | specifică un model pentru fluxul de ieşire: valoarea ''none'' indică faptul că răspunsul va fi transmis imediat clientului; alte valori specifică dimensiunea maximă (în octeţi) a buffer-ului, răspunsul fiind construit în această zonă tampon înainte de a fi transmis clientului <code java> | ||
| + | <%@ page buffer="none" %> | ||
| + | <%@ page buffer="8kb" %> | ||
| + | </code> | | ||
| + | | ''contentType'' | specifică schema de codificare a caracterelor pentru pagina JSP şi pentru răspunsul generat <code java> | ||
| + | <%@ page contentType="text/html" %> | ||
| + | <%@ page contentType="text/xml" %> | ||
| + | <%@ page contentType="application/msword" %> | ||
| + | <%@ page contentType="text/html:charset=ISO-8859-1" %> | ||
| + | </code> | | ||
| + | | ''errorPage'' | defineşte un URL către pagina care raportează excepţiile Java netratate, generate la rulare <code java> | ||
| + | <%@ page errorPage="errorpage.jsp"%> | ||
| + | </code> | | ||
| + | | ''isErrorPage'' | specifică dacă pagina JSP curentă este indicată de proprietatea ''errorPage'' a altei pagini JSP <code java> | ||
| + | <%@ page isErrorPage="false" %> | ||
| + | <%@ page isErrorPage="true" %> | ||
| + | </code> | | ||
| + | | ''extends'' | specifică o superclasă pe care servlet-ul generat trebuie să o extindă <code java> | ||
| + | <%@ page extends="myPackage.MyClass" %> | ||
| + | </code> | | ||
| + | | ''import'' | indică o listă de pachete sau de clase Java care vor fi utilizate în pagina JSP; în mod implicit, sunt importate automat ''java.lang.*'', ''javax.servlet.*'', ''javax.servlet.jsp.*'', ''javax.servlet.http.*''; dacă se doreşte importarea mai multor pachete sau clase (inclusiv definite de utilizator), acestea vor fi separate prin virgulă: <code java> | ||
| + | <%@ page import="java.sql.*, java.util.*, java.io.*" %> | ||
| + | </code> | | ||
| + | | ''info'' | defineşte un şir de caractere care poate fi accesat prin metoda ''getServletInfo()'' a servlet-ului asociat <code java> | ||
| + | <%@ page info="Some info on my JSP Page" %> | ||
| + | </code> | | ||
| + | | ''isELIgnored'' | specifică dacă expresiile EL (Expression Languge) din pagina JSP de forma ''${...}'' vor fi evaluate (valoarea ''true'', implicită) sau vor fi tratate ca text static <code java> | ||
| + | <%@ page isELIgnored="true" %> | ||
| + | <%@ page isELIgnored="false" %> | ||
| + | </code> | | ||
| + | | ''isScriptingEnabled'' | determină dacă script-urile (scripleţi, expresii non-EL şi declaraţii) sunt permise pentru a fi utilizate (valoarea ''true'' – implicită) sau nu (valoarea ''false'') <code java> | ||
| + | <%@ page isScriptingEnabled="true" %> | ||
| + | <%@ page isScriptingEnabled="false" %> | ||
| + | </code> | | ||
| + | | ''isThreadSafe'' | defineşte modelul firului de execuţie pentru servlet-ul generat; implicit, paginile JSP sunt socotite ca fiind sigure (valoarea ''true'') pentru a fi folosite într-un context concurent, iar în caz contrar (valoarea ''false''), container-ul se asigură ca pagina să fie accesată de un singur client la un moment dat <code java> | ||
| + | <%@ page isThreadSafe="true" %> | ||
| + | <%@ page isThreadSafe="false" %> | ||
| + | </code> | | ||
| + | | ''language'' | defineşte limbajul de programare utilizat în pagina JSP <code java> | ||
| + | <%@ page language="java" %> | ||
| + | <%@ page language="javascript" %> | ||
| + | </code> | | ||
| + | | ''session'' | specifică dacă pagina JSP participă (valoarea ''true'') sau nu (valoarea ''false'') la sesiuni HTTP, adică dacă poate accesa sau nu obiectul implicit ''session'' şi metodele asociate acestuia <code java> | ||
| + | <%@ page session="true" %> | ||
| + | <%@ page session="false" %> | ||
| + | </code> | | ||
| - | Conversia scheme XML – limbajul Java | + | === Directiva include === |
| - | ^ tip schemă XML ^ tip Java ^ | + | Directiva ''include'' este folosită pentru a include resursa specificată în fişierul curent, în cadrul etapei de transformare a paginii JSP în servlet. Practic, se concatenează conţinutul acestor fişiere externe, la locaţia unde a fost specificată (oriunde în pagina JSP): |
| - | | ''xsd:string'' | ''java.lang.String'' | | + | |
| - | | ''xsd:integer'' | ''java.math.BigInteger'' | | + | |
| - | | ''xsd:int'' | ''int'' | | + | |
| - | | ''xsd:long'' | ''long'' | | + | |
| - | | ''xsd:short'' | ''short'' | | + | |
| - | | ''xsd:decimal'' | ''java.math.BigDecimal'' | | + | |
| - | | ''xsd:float'' | ''float'' | | + | |
| - | | ''xsd:double'' | ''double'' | | + | |
| - | | ''xsd:boolean'' | ''boolean'' | | + | |
| - | | ''xsd:byte'' | ''byte'' | | + | |
| - | | ''xsd:QName'' | ''javax.xml.namespace.QName'' | | + | |
| - | | ''xsd:dateTime'' | ''javax.xml.datatype.XMLGregorianCalendar'' | | + | |
| - | | ''xsd:base64Binary'' | ''byte[]'' | | + | |
| - | | ''xsd:hexBinary'' | ''byte[]'' | | + | |
| - | | ''xsd:unsignedInt'' | ''long'' | | + | |
| - | | ''xsd:unsignedShort'' | ''int'' | | + | |
| - | | ''xsd:unsignedByte'' | ''short'' | | + | |
| - | | ''xsd:time'' | ''javax.xml.datatype.XMLGregorianCalendar'' | | + | |
| - | | ''xsd:date'' | ''javax.xml.datatype.XMLGregorianCalendar'' | | + | |
| - | | ''xsd:g'' | ''javax.xml.datatype.XMLGregorianCalendar'' | | + | |
| - | | ''xsd:anySimpleType'' | ''java.lang.Object'' | | + | |
| - | | ''xsd:anySimpleType'' | ''java.lang.String'' | | + | |
| - | | ''xsd:duration'' | ''javax.xml.datatype.Duration'' | | + | |
| - | | ''xsd:NOTATION'' | ''javax.xml.namespace.QName'' | | + | |
| - | <newcolumn> | + | <code java> |
| + | <%@ include file="myJSPPage.jsp" %> | ||
| + | </code> | ||
| - | Conversia limbajul Java – scheme XML | + | <code java> |
| + | <jsp:directive.include file="myJSPPage.jsp" /> | ||
| + | </code> | ||
| - | ^ tip Java ^ tip schemă XML ^ | + | Se consideră că resursa specificată este indicată prin calea sa relativă, astfel încât atunci când ea lipseşte, se consideră că fişierul se găseşte în acelaşi director cu pagina JSP din care este invocat. |
| - | | ''java.lang.String'' | ''xs:string'' | | + | |
| - | | ''java.math.BigInteger'' | ''xs:integer'' | | + | |
| - | | ''java.math.BigDecimal'' | ''xs:decimal'' | | + | |
| - | | ''java.util.Calendar'' | ''xs:dateTime'' | | + | |
| - | | ''java.util.Date'' | ''xs:dateTime'' | | + | |
| - | | ''javax.xml.namespace.QName'' | ''xs:QName'' | | + | |
| - | | ''java.net.URI xs:string'' | ''xs:string'' | | + | |
| - | | ''javax.xml.datatype.XMLGregorianCalendar'' | ''xs:anySimpleType'' | | + | |
| - | | ''javax.xml.datatype.Duration'' | ''xs:duration'' | | + | |
| - | | ''java.lang.Object'' | ''xs:anyType'' | | + | |
| - | | ''java.awt.Image'' | ''xs:base64Binary'' | | + | |
| - | | ''javax.activation.DataHandler'' | ''xs:base64Binary'' | | + | |
| - | | ''javax.xml.transform.Source'' | ''xs:base64Binary'' | | + | |
| - | | ''java.util.UUID'' | ''xs:string'' | | + | |
| - | </columns> | + | O astfel de funcţionalitate este folosită mai ales pentru includerea de resurse comune pentru toate paginile Internet cum ar fi: header, footer sau meniuri ale aplicaţiei web. |
| - | JAXB defineşte un set de adnotări astfel încât pentru clase definite de utilizator să se poată realiza conversia la un document XML: | + | === Directiva taglib === |
| - | ^ Adnotare ^ Descriere ^ | + | Directiva ''taglib'' permite definirea de către utilizator a unor etichete JSP care implementează o anumită funcţionalitate, acestea fiind grupate în cadrul unor biblioteci. Se specifică pentru fiecare set de etichete locaţia la care se află biblioteca respectivă (atributul ''uri''), identificând un mecanism (atributul ''prefix'') prin care acestea vor fi identificate în cadrul paginii JSP: |
| - | | ''@XmlRootElement(namespace="...")'' | defineşte elementul rădăcină din cadrul schemei XML | | + | |
| - | | ''@XmlElement'' | face conversia între o proprietate JavaBeans sau un câmp al unei clase şi un atribut XML | | + | |
| - | | ''@XmlAccesorType(XMLAccessType.PACKAGE|FIELD)'' | este aplicat unui pachet sau unei clase Java, specificând daca proprietăţile JavaBeans sau atributele vor fi serializate | | + | |
| - | | ''@XmlType(propOrder={"atr<sub>1</sub>","atr<sub>2</sub>",...,"atr<sub>n</sub>"})'' | permite stabilirea structurii documentului XML prin indicarea ordinii în care atributele clasei vor fi copiate | | + | |
| - | JAXB pune la dispoziţie un utilitar pentru compilarea unei scheme XML într-o clasă Java – denumit ''xjc'' –, un utilitar de generare a unei scheme XML dintr-o clasă Java – denumit ''schemagen'' şi un cadru general de rulare. Astfel, se poate porni de la o definiţie a unei scheme XML (XSD – XML Schema Definition), creându-se obiecte JavaBeans corespunzătoare (folosind compilatorul pentru scheme XML ''xjc'') sau se poate porni de la obiecte JavaBeans creându-se definiţiile unei scheme XML corespunzătoare (folosind utilitarul ''schemagen''). | + | <code java> |
| + | <%@ taglib uri="uri" prefix="prefixOfTag" %> | ||
| + | </code> | ||
| - | <note tip>Atât ''xjc'' cât şi ''schemagen'' fac parte din distribuţia Java, începând cu versiunea 6.</note> | + | <code java> |
| + | <jsp:directive.taglib uri="uri" prefix="prefixOfTag" /> | ||
| + | </code> | ||
| - | După stabilirea corespondenţei dintre schema XML şi clasele Java, conversia între ele este realizată în mod automat prin intermediul JAXB. Informaţiile reţinute în cadrul documentelor XML pot fi accesate fără a fi necesară înţelegerea structurii lor. Clasele Java rezultate pot fi folosite pentru accesarea serviciului web dezvoltat. Adnotările conţin toate datele necesare pentru ca JAXB să realizeze conversia dintr-un format într-altul, astfel încât obiectele să poată fi transmise prin infrastructura de comunicaţie. JAXB asigură împachetarea obiectelor Java spre documente XML şi despachetarea documentelor XML în instanţe ale claselor Java. Totodată, JAXB poate oferi validarea documentelor XML conform schemei generate, astfel încât acestea respectă constrângerile care au fost stabilite. | + | Pot fi folosite biblioteci standard (care implementează controlul fluxului într-un program, care pun la dispoziţie mecanisme pentru gestiunea informaţiilor dintr-o bază de date sau care implementează diferite metode uzitate mai frecvent în cadrul oricărei aplicaţii) sau se pot crea biblioteci definite de utilizator: |
| - | Prin urmare, JAXB reprezintă tehnologia standard utilizată pentru conversia datelor în cadrul serviciilor web de dimensiuni "mari" implementate prin JAX-WS. Totuşi, JAXB poate fi folosit şi independent de JAX-WS, atunci când se doreşte gestiunea conversiei dintre documente XML şi obiecte Java în cadrul unor aplicaţii informatice. | + | <code java> |
| + | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> | ||
| + | <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> | ||
| + | <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> | ||
| + | <%@ taglib prefix="my" uri="http://www.mysite.com/mylibrary" %> | ||
| + | </code> | ||
| - | {{ :laboratoare:laborator06:figura02.png?nolink }} | + | Utilizarea unei astfel de etichete se face cu ''<prefixName:tagName ...>'' unde ''prefixName'' este valoarea specificată pentru atributul ''prefix'' de la definirea bibliotecii respective, iar ''tagName'' numele unei etichete implementate. |
| - | JAXB este folosit în implementarea serviciilor web prin tehnologia JAX-WS pentru a asigura transportul obiectelor Java (parametrii sau valori întoarse ale metodelor), utilizând un format universal (XML) – independent de platformă, dar şi pentru a asigura un mecanism de persistenţă (prin documente XML), fără a face apel la JPA (Java Persistance API), adecvat stabilirii unei corespondenţe între clase Java şi baze de date relaţionale. Deşi este mai rudimentar, această soluţie este folosită atunci când starea obiectelor trebuie să fie reţinută, iar dimensiunea acestora nu este foarte voluminoasă. | + | ==== Acțiuni ==== |
| - | În cazul exemplului de mai sus, este necesar ca obiectele cu tipul Interval să fie transportate prin infrastructura de comunicaţie, motiv pentru care definiţia clasei trebuie să indice acest lucru: | + | O **acţiune** este un marcaj care specifică comportamentul motorului Java Servlets de la nivelul serverului web, în momentul compilării marcajele fiind înlocuite cu codul sursă Java corespunzător acţiunii. |
| - | <columns 100% 50%> | + | Sintaxa unei acţiuni este: |
| - | <file java Interval.java> | + | <code java> |
| - | import javax.xml.bind.annotation.XmlAccessType; | + | <jsp:actionName attribute="value" /> |
| - | import javax.xml.bind.annotation.XmlAccessorType; | + | </code> |
| - | import javax.xml.bind.annotation.XmlType; | + | |
| - | @XmlAccessorType(XmlAccessType.FIELD) | + | Atributele comune tututor tipurilor de acţiuni sunt: |
| - | @XmlType(name="Interval") | + | * ''id'': identifică în mod unic acţiunea respectivă permiţând ca aceasta să poată fi referită în cadrul paginii JSP; dacă acţiunea este folosită pentru crearea unei instanţe a unui obiect, prin intermediul identificatorului aceasta poate fi utilizată pe tot parcursul obiectului implicit ''PageContext''; |
| - | public class Interval { | + | * ''scope'': defineşte ciclul de viaţă al acţiunii, adică vizibilitatea elementului concretizată în posibilitatea de utilizare a identificatorului acestuia; valorile pe care le poate sunt: ''page'', ''request'', ''session'' şi ''application''. |
| - | // ... | + | |
| - | } | + | |
| - | </file> | + | |
| - | <newcolumn> | + | O acţiune este de fapt o funcţie predefinită, tipurile de acţiuni implementate de API-ul JSP fiind: |
| - | <file java ReservationData.java> | + | | ''<jsp:attribute>'' | defineşte atributul unui element XML definit dinamic | |
| - | import javax.xml.bind.annotation.XmlAccessType; | + | | ''<jsp:body>'' | defineşte corpul unui element XML definit dinamic | |
| - | import javax.xml.bind.annotation.XmlAccessorType; | + | | ''<jsp:element>'' | defineşte elemente XML în mod dinamic | |
| - | import javax.xml.bind.annotation.XmlType; | + | | Prin acţiunile ''<jsp:attribute>'', ''<jsp:body>'' şi ''<jsp:element>'' elementele XML pot fi generate în momentul rulării, ca răspuns la o cerere şi nu atunci când sunt compilate sursele. <code java> |
| + | <jsp:element name="xmlElement"> | ||
| + | <jsp:attribute name="xmlAttribute"> | ||
| + | Attribute Value | ||
| + | </jsp:attribute> | ||
| + | <jsp:body> | ||
| + | Body for XML element | ||
| + | </jsp:body> | ||
| + | </jsp:element> | ||
| + | </code> → <code java> | ||
| + | <xmlElement xmlAttribute="Attribute Value"> | ||
| + | Body for XML element | ||
| + | </xmlElement> | ||
| + | </code> || | ||
| + | | ''<jsp:useBean>'' | găsirea sau instanţierea unei componente Java Bean; se caută dacă este vizibil vreun obiect având identificatorul specificat şi în cazul în care acesta nu este găsit, se încearcă instanţierea clasei indicate; ulterior, se pot folosi acţiunile ''setProperty'' şi ''getProperty'' pentru a stabili şi pentru a obţine proprietăţile componentei JavaBean\\ \\ Atributele asociate acţiunii ''useBean'' sunt:\\ • ''class'' – desemnează numele componentei Java Bean, incluzând şi pachetul în care se găseşte aceasta;\\ • ''type'' – indică tipul variabilei ce va reda obiectul în cauză\\ • ''beanName'' – specifică numele componentei Java Bean, aşa cum este indicat de metoda ''instantiate()'' a clasei ''java.beans.Beans''. <code java> | ||
| + | <jsp:useBean id="myObject" class="myPackage.myClass" /> | ||
| + | </code> | | ||
| + | | ''<jsp:getProperty>'' | obţinerea valorii proprietăţii unei componente pe care o converteşte apoi la tipul şir de caractere şi apoi o integrează în fluxul de ieşire\\ \\ Atributele obligatorii asociate acţiunii ''getProperty'' sunt:\\ • ''name'' – desemnează componenta Java Bean a cărei proprietate va fi stabilită; trebuie să aibă aceeaşi valoare cu a identificatorului precizat în acţiunea ''useBean'';\\ • ''property'' – indică proprietatea care se doreşte a fi stabilită; <code java> | ||
| + | <jsp:useBean id="myObject" class="myPackage.myClass" /> | ||
| + | ... | ||
| + | <jsp:getProperty name="myObject" property="myProperty"/> | ||
| + | </code> | | ||
| + | | ''<jsp:setProperty>'' | stabilirea valorii proprietăţii unei componente Java Bean; anterior utilizării acestei proprietăţi, componenta Java Bean referită trebuie să fi fost definită; poate fi utilizată în cadrul acţiunii ''useBean'' (situaţie în care se execută numai dacă a fost instanţiat un obiect nou) sau independent de ea (caz în care se execută atât atunci când a fost găsit un element cu numele respectiv atunci când a fost instanţiat un obiect nou)\\ \\ Atributele asociate acţiunii ''setProperty'' sunt:\\ • ''name'' – desemnează componenta Java Bean a cărei proprietate va fi stabilită; trebuie să aibă aceeaşi valoare cu a identificatorului precizat în acţiunea ''useBean'';\\ • ''property'' – indică proprietatea care se doreşte a fi stabilită; valoarea specifică faptul că parametrii cererii ale căror nume se potrivesc cu numele proprietăţilor componentei Java Beans vor fi transmişi către metodele setter respective;\\ • ''value'' – specifică valoarea care se doreşte asignată proprietăţii în cauză; dacă valoarea parametrului e ''null'' sau parametrul nu există, acţiunea este ignorată;\\ • ''param'' – numele parametrului cererii a cărei valoare trebuie să o primească proprietatea; nu se poate folosi concomitent cu ''value'' (dar cei doi parametrii pot fi omişi); <code java> | ||
| + | <jsp:useBean id="myObject" class="myPackage.myClass"> | ||
| + | <jsp:setProperty name="myObject" property="myProperty" value="myValue" ... /> | ||
| + | </jsp:useBean> | ||
| + | <jsp:useBean id="myObject" class="myPackage.myClass" /> | ||
| + | ... | ||
| + | <jsp:setProperty name="myObject" property="myProperty" value="myValue" ... /> | ||
| + | </code> | | ||
| + | | ''<jsp:forward>'' | pagina JSP curentă îşi încheie activitatea, cererea fiind transmisă către o altă resursă (pagină statică, pagină JSP sau un Java Servlet)\\ \\ Atributul asociat acţiunii forward este ''page'', prin care se indică un URL relativ al resursei spre care se doreşte a se realiza redirectarea. <code java> | ||
| + | <jsp:forward page="myJSPPage.jsp" /> | ||
| + | </code> | | ||
| + | | ''<jsp:include>'' | includerea resursei specificate în momentul când pagina JSP este solicitată (spre diferenţă de directiva cu acelaşi nume, în care includerea avea loc în cadrul procesului de transformare în servlet-ul asociat)\\ \\ Atributele asociate acţiunii ''include'' sunt:\\ • ''page'' – un URL (relativ) spre pagina ce se doreşte inclusă;\\ • ''flush'' – determină dacă buffer-ul resursei va fi golit înainte de operaţia de includere. <code java> | ||
| + | <jsp:include page="myJSPPage.jsp" flush="true" /> | ||
| + | </code> | | ||
| + | | ''<jsp:plugin>'' | generarea codului specific browser-ului (o etichetă ''<OBJECT>'' sau ''<EMBED>'') pentru o componentă Java (applet sau clasă Java Bean); dacă plugin-ul necesar nu este prezent, acesta este descărcat şi apoi se poate executa componenta Java; parametrii sunt transmişi prin acţiunea ''<jsp:param>'', în caz de producere a unei erori, se poate specifica un şir de caractere care să fie afişat prin acţiunea ''<jsp:fallback>'' <code java> | ||
| + | <jsp:plugin type="applet" codebase="mydir" code="MyClass.class" width="100" height="100"> | ||
| + | <jsp:param name="paramname" value="paramvalue" /> | ||
| + | <jsp:fallback> | ||
| + | Unable to load Java Plugin | ||
| + | </jsp:fallback> | ||
| + | </jsp:plugin> | ||
| + | </code> | | ||
| + | | ''<jsp:text>'' | transcrierea unui text folosind un anumit format în pagini şi documente JSP; corpul acţiunii nu poate conţine alte elemente în afară de text şi expresii EL <code java> | ||
| + | <jsp:text>My text template</jsp:text> | ||
| + | </code> | | ||
| - | @XmlAccessorType(XmlAccessType.FIELD) | + | ==== Scripleți ==== |
| - | @XmlType(name="ReservationData") | + | |
| - | public class ReservationData { | + | |
| - | // ... | + | |
| - | } | + | |
| - | </file> | + | |
| - | </columns> | + | Un scriplet conţine cod sursă Java (declaraţii de variabile şi metode, expresii) care va fi plasat în metoda de tip ''service()'' ce se va genera în servlet-ul paginii JSP respective. |
| - | Prin folosirea adnotării ''@XmlAccessorType'', se indică faptul că toate atributele clasei vor fi serializate, motiv pentru care nu mai este necesară implementarea interfeţei ''java.io.Serializable''. Serializarea este realizată prin intermediul unor documente XML, tipul de date (specificat prin adnotarea ''@XmlType'') fiind ''Interval'' / ''ReservationData''. Se asigură totodată faptul că descrierea în limbaj WSDL va cuprinde definiţiile metodelor din această clasă, astfel încât ele vor putea fi folosite corespunzător în cadrul aplicaţiilor ce accesează funcţionalitatea oferită de serviciul web, fiind cuprinse în clasele generate la nivelul clientului. | + | <code java> |
| + | <% Java code fragment %> | ||
| + | </code> | ||
| - | De asemenea, e necesară asigurarea persistenţei pentru obiectele de tipul ''ArrayList<Interval>'' / ''ArrayList<ReservationData>'': ''timetable'' / ''reservationData''. Prin JAXB, starea acestor obiecte poate fi reţinută prin intermediul unor documente XML pe server, specificându-se un mecanism de transformare. Astfel, se vor defini clasele ''PersistentInterval'' / ''PersistentReservationData'', conţinând două atribute ''ArrayList<GregorianCalendar>'', respectiv două atribute ''ArrayList<Integer>'' şi ''ArrayList<GregorianCalendar>'' (pentru care este cunoscut mecanismul de transformare în document XML), adnotările în cadrul acestei clase (''@XmlRootElement'', ''@XmlElement'') indicând modul cum informaţiile din obiecte vor fi transpuse în documentul XML. Trebuie definite metode setter / getter corespunzătoare pentru accesarea informaţiilor necesare. | + | <code java> |
| + | <jsp:scriptlet> | ||
| + | Java code fragment | ||
| + | </jsp:scriptlet> | ||
| + | </code> | ||
| - | <file java PersistentInterval.java> | + | Acest cod va fi executat pe server atunci când se realizează o cerere pentru pagina JSP care conţine scriplet-ul, iar rezultatul va fi plasat în răspunsul care este transmis clientului. |
| - | @XmlRootElement | + | |
| - | public class PersistentInterval { | + | |
| - | private int numberOfSeats; | + | De regulă, utilizarea scripleţilor este de evitat în paginile JSP întrucât separarea dintre logica aplicaţiei şi prezentare nu mai este atât de evidentă, codul fiind şi mai dificil de întreţinut. Recursul la această tehnologie se face numai pentru a beneficia de facilităţile pe care le pune la dispoziţie limbajul de programare Java şi numai în situaţia în care un comportament similar nu poate fi obţinut prin folosirea EL (Expression Language) împreună cu metodele din bibliotecile JavaServer Pages Standard Tag Library. |
| - | private ArrayList<GregorianCalendar> startingIntervals; | + | |
| - | private ArrayList<GregorianCalendar> endingIntervals; | + | |
| - | @XmlElement | + | === Expresii === |
| - | public int getNumberOfSeats() { | + | |
| - | return numberOfSeats; | + | |
| - | } | + | |
| - | @XmlElement | + | O expresie este un scriplet, cuprins între ''%%<%=%%'' şi ''%%%>%%'', evaluat în momentul în care este rulat servlet-ul şi convertit la tipul ''String'', fiind inserat în pagina JSP acolo unde este apelat, putând fi inclusă oriunde, fie că se găseşte sau nu în cadrul unei etichete HTML. Ea poate conţine orice expresie care este validă conform specificaţiei Java, însă nu este încheiată prin '';'', ca de obicei. |
| - | public ArrayList<GregorianCalendar> getStartingIntervals() { | + | |
| - | return startingIntervals; | + | |
| - | } | + | |
| - | + | ||
| - | @XmlElement | + | |
| - | public ArrayList<GregorianCalendar> getEndingIntervals() { | + | |
| - | return endingIntervals; | + | |
| - | } | + | |
| - | } | + | |
| - | </file> | + | |
| - | <file java PersistentReservationData.java> | + | <code java> |
| - | @XmlRootElement | + | <%= expression %> |
| - | public class PersistentReservationData { | + | </code> |
| - | + | ||
| - | private ArrayList<Integer> customerIds; | + | |
| - | private ArrayList<GregorianCalendar> startingIntervals; | + | |
| - | private ArrayList<GregorianCalendar> endingIntervals; | + | |
| - | private ArrayList<Integer> numberOfSeats; | + | |
| - | + | ||
| - | @XmlElement | + | |
| - | public ArrayList<Integer> getCustomerIds() { | + | |
| - | return customerIds; | + | |
| - | } | + | |
| - | @XmlElement | + | <code java> |
| - | public ArrayList<GregorianCalendar> getStartingIntervals() { | + | <jsp:expression> |
| - | return startingIntervals; | + | expression |
| - | } | + | </jsp:expression> |
| + | </code> | ||
| - | @XmlElement | + | === Declarații === |
| - | public ArrayList<GregorianCalendar> getEndingIntervals() { | + | |
| - | return endingIntervals; | + | |
| - | } | + | |
| - | @XmlElement | + | O **declaraţie** permite precizarea de variabile sau de metode, similar cu modul în care s-ar face într-o clasă, domeniul de vizibilitate fiind pe tot parcursul paginii respective. În servlet-ul corespunzător paginii JSP, declaraţiile vor fi incluse astfel încât să poată fi accesate din toate metodele acesteia. |
| - | public ArrayList<Integer> getNumberOfSeats() { | + | |
| - | return numberOfSeats; | + | <code java> |
| + | <%! declaration; [declaration; ]+ %> | ||
| + | </code> | ||
| + | |||
| + | <code java> | ||
| + | <jsp:declaration> | ||
| + | declaration; | ||
| + | [declaration; ]+ | ||
| + | </jsp:declaration> | ||
| + | </code> | ||
| + | |||
| + | ==== Obiecte Implicite ==== | ||
| + | |||
| + | În JSP pot fi referite **obiecte implicite**, disponibile la nivelul fiecărei pagini, putând fi utilizate fără a fi declarate în prealabil. Obiectele implicite mai sunt numite şi variabile predefinite. | ||
| + | |||
| + | ^ Obiect Implicit ^ Tip ^ Descriere ^ | ||
| + | | ''request'' | subclasă a [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html|javax.servlet.ServletRequest]] | cererea care a invocat pagina JSP | | ||
| + | | ''response'' | subclasă a [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletResponse.html|javax.servlet.ServletResponse]] | răspunsul pe care îl generează pagina JSP | | ||
| + | | ''out'' | [[http://docs.oracle.com/javaee/7/api/javax/servlet/jsp/JspWriter.html|javax.servlet.jsp.JspWriter]] | obiect care scrie în fluxul de ieşire | | ||
| + | | ''session'' | [[https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html|javax.servlet.http.HttpSession]] | obiect sesiune asociat cererii care a invocat pagina JSP | | ||
| + | | ''application'' | [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletContext.html|javax.servlet.ServletContext]] | context pagină JSP | | ||
| + | | ''config'' | [[https://docs.oracle.com/javaee/7/api/javax/servlet/ServletConfig.html|javax.servlet.ServletConfig]] | informaţii de configurare referitoare la servlet | | ||
| + | | ''pageContext'' | [[http://docs.oracle.com/javaee/7/api/javax/servlet/jsp/PageContext.html|javax.servlet.jsp.PageContext]] | contextul paginii JSP | | ||
| + | | ''page'' | [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html|java.lang.Object]] | referinţă către pagina JSP prin care poate fi accesat servlet-ul asociat | | ||
| + | | ''exception'' | [[https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html|java.lang.Throwable]] | acces la detalii cu privire la eroare, în paginile de tratare a excepţiei | | ||
| + | |||
| + | Astfel de obiecte vor fi disponibile **doar** în cadrul metodei ''_jspService()'', astfel încât referirea acestora în cadrul unei declaraţii JSP nu are sens. | ||
| + | |||
| + | Este important ca programatorii să cunoască denumirile acestor obiecte implicite precum şi domeniul lor de vizibilitate, astfel încât să le poată accesa funcţionalitatea în acelaşi mod în care ar fi făcut-o în cadrul clasei Java Servlet corespunzătoare, în care acesteau erau declarate fie ca parametrii ai metodelor respective, fie se putea obţine o instanţă a lor pornind de la obiectele cerere şi răspuns. Prin acestea, tehnologiile Java Servlet şi JavaServer Pages sunt echivalente, oferind aceeaşi funcţionalitate şi aceeaşi uşurinţă în utilizare. | ||
| + | |||
| + | === Obiectul implicit request === | ||
| + | |||
| + | Un obiect ''request'' este creat de fiecare dată când un client solicită o pagină JSP, acesta oferind metode spre a obţine informaţii din antetele HTTP (''Accept'', ''Accept-Charset'', ''Accept-Encoding'', ''Accept-Language'', ''Authorization'', ''Cache-Control'', ''Connection'', ''Content-Length'', ''Cookie'', ''Host'', ''If-Modified-Since'', ''If-Unmodified-Since'', ''Referer'', ''User-Agent''). Fiind derivat din ''javax.servlet.http.HttpServletRequest'', metodele pe care le pune la dispoziţia programatorilor acest obiect sunt aceleaşi ca în cazul utilizării ca parametru al metodei ''service()'' din cadrul Java Servlets. | ||
| + | |||
| + | Astfel, cele mai frecvent folosite metode sunt: | ||
| + | * ''Object getAttribute(String)'' – întoarce valoarea obiectului identificat prin numele său (transmis ca parametru) – convertit la ''Object'' sau ''null'' dacă obiectul solicitat nu există; | ||
| + | * ''Enumeration getAttributeNames()'' – întoarce o enumerare conţinând numele tuturor atributelor disponibile în cadrul cererii; | ||
| + | * ''String getAuthType()'' – întoarce numele mecanismului de autentificare utilizat pentru securizarea servlet-ului sau ''null'' dacă nu se foloseşte un astfel de mecanism; | ||
| + | * ''String getCharacterEncoding()'' – întoarce denumirea schemei de codificare utilizată pentru corpul cererii; | ||
| + | * ''int getContentLength()'' – întoarce dimensiunea (în octeţi) a corpului cererii disponibilă în fluxul de intrare, sau -1 dacă această valoare nu e cunoscută; | ||
| + | * ''String getContentType()'' – întoarce tipul MIME al corpului cererii sau null dacă tipul nu este cunoscut; | ||
| + | * ''String getContextPath()'' – întoarce porţiunea din URI-ul cererii care indică contextul acesteia; | ||
| + | * ''Cookie[] getCookies()'' – întoarce toate obiectele ''Cookie'' care au fost transmise de client împreună cu cererea sa; | ||
| + | * ''String getHeader(String)'' – întoarce valoarea antetului specificat din cadrul cererii sub formă de şir de caractere; | ||
| + | * ''Enumeration getHeaderNames()'' – întoarce o enumerare ce cuprinde numele tuturor antetelor conţinute de cerere; | ||
| + | * ''int getIntHeader(String)'' – întoarce valoarea antetului specificat din cadrul cererii sub formă de întreg; | ||
| + | * ''ServletInputStream getInputStream()'' – întoarce corpul cererii (ca date binare) folosind un ''ServletInputStream''; | ||
| + | * ''Locale getLocale()'' – întoarce localizarea preferată a conţinutului, în funcţie de valoarea conţinută de antetul ''Accept-Language''; | ||
| + | * ''String getMethod()'' – întoarce numele metodei HTTP prin care a fost transmisă cererea (''GET'', ''POST'', ''PUT'', ''OPTIONS'', ''TRACE'', ''DELETE''); | ||
| + | * ''String getParameter(String)'' – întoarce valoarea parametrului specificat (prin nume) în cadrul cererii ca şir de caractere sau ''null'' dacă nu există; | ||
| + | * ''Enumeration getParameterNames()'' – întoarce o enumerare incluzând denumirile tuturor parametrilor din cadrul cererii; | ||
| + | * ''String[] getParameterValues(String)'' – întoarce un vector de obiecte de tip şir de caractere conţinând toate valoarile pe care le deţine parametrul identificat (prin nume) în cadrul cererii sau null dacă nu există; | ||
| + | * ''String getPathInfo()'' – întoarce informaţii suplimentare referitoare la cale asociate cu URL-ul transmis împreună cu cererea; | ||
| + | * ''String getProtocol()'' – întoarce numele şi versiunea protocolului prin care a fost transmisă cererea; | ||
| + | * ''String getQueryString()'' – întoarce un şir de caractere reprezentând interogarea cuprinsă în URL după cale; | ||
| + | * ''String getRemoteAddr()'' – întoarce adresa IP (Internet Protocol) a clientului care a transmis cererea; | ||
| + | * ''String getRemoteHost()'' – întoarce numele complet al maşinii de pe care clientul a transmis cererea; | ||
| + | * ''String getRemoteUser()'' – întoarce numele utilizatorului autentificat care a transmis cererea sau ''null'' dacă utilizatorul nu este autentificat; | ||
| + | * ''String getRequestURI()'' – întoarce partea din URL-ul asociat cererii începând de la numele protocolului până la şirul ce reprezintă interogarea din cadrul cererii HTTP; | ||
| + | * ''String getRequestedSessionId()'' – întoarce identificatorul sesiunii specificat de client în cerere; | ||
| + | * ''int getServerPort()'' – întoarce portul pe care a fost primită cererea; | ||
| + | * ''String getServletPath()'' – întoarce partea din URL-ul asociat cererii care invocă pagina JSP; | ||
| + | * ''HttpSession getSession([boolean])'' – întoarce sesiunea asociată cererii sau, dacă aceasta nu există (iar parametrul metodei, în caz că este utilizat, are valoarea ''true''), asociază cererii o sesiune nouă; | ||
| + | * ''boolean isSecure()'' – indică dacă cererea a fost transmisă folosind un canal sigur (cum este HTTPS). | ||
| + | |||
| + | O listă cu antetele HTTP transmise prin intermediul cererii poate fi obţinută astfel: | ||
| + | <code java> | ||
| + | ... | ||
| + | <table> | ||
| + | <tr><th>Header Name</th><th>Header Value</th></tr> | ||
| + | <% | ||
| + | Enumeration headers = request.getHeaderNames(); | ||
| + | while (headers.hasMoreElements()) { | ||
| + | String headerName = (String)headers.nextElement(); | ||
| + | String headerValue = request.getHeader(headerName); | ||
| + | %> | ||
| + | <tr><td><%= headerName %></td><td><%= headerValue %></td></tr> | ||
| + | <% | ||
| } | } | ||
| - | } | + | %> |
| - | </file> | + | </table> |
| + | ... | ||
| + | </code> | ||
| - | Astfel un obiect de tipul ''ArrayList<Interval>'' / ''ArrayList<ReservationData>'' pentru care nu era cunoscut modul de transformare în document XML este împărţit în obiecte de tipul ''ArrayList<GregorianCalendar>'', funcţionalitatea acestora fiind asemănătoare. Deşi modalitatea de transformare este cunoscută pentru clasa ''Interval'', trebuie specificat mecanismul de transformare pentru tipul de date ''ArrayList<Interval>'', astfel încât operaţiile de împachetare şi despachetare să fie realizate pentru obiecte de acest fel. Pentru uşurinţa accesului la datele conţinute în obiect, au fost definite două atribute corespunzătoare celor din clasa ''Interval''. Similar pentru ''ReservationData'' / ''ArrayList<ReservationData>''. | + | === Obiectul implicit response === |
| - | De remarcat faptul că adnotarea ''@XmlElement'' va fi indicată pentru metoda getter asociată atributului respectiv şi nu pentru atributul în sine. | + | Un obiect ''response'' este de asemenea creat de fiecare dată de către server, conţinând: |
| + | * starea (numele protocolului și versiunea acestuia, codul reprezentând starea și un mesaj de dimensiuni mici care reprezintă o descriere a stării); | ||
| + | * antetele HTTP (''Allow'', ''Cache-Control'', ''Connection'', ''Content-Disposition'', ''Content-Encoding'', ''Content-Language'', ''Content-Length'', ''Content-Type'', ''Expires'', ''Last-Modified'', ''Location'', ''Refresh'', ''Retry-After'', ''Set-Cookie''); | ||
| + | * documentul reprezentând pagina Internet care va fi afişată în browser. | ||
| - | <note tip>Adnotarea ''@XmlElement'' se precizează pentru metodele getter întrucât acestea sunt publice, spre diferenţă de atributele în sine care au modul de acces privat. Într-o distribuţie anterioară a JAX-WS, adnotarea ''@XmlAttribute'' se definea pentru atributele clasei.</note> | + | Fiind derivat din ''javax.servlet.http.HttpServletResponse'', metodele pe care le pune la dispoziţia programatorilor acest obiect sunt aceleaşi ca în cazul utilizării ca parametru al metodei ''service()'' din cadrul Java Servlets. |
| - | Operaţiile asupra obiectelor ''timetable'' şi ''reservationData'' vor implica încărcarea, respectiv descărcarea lor din fişierele care le reţin starea. | + | Astfel, cele mai frecvent folosite metode sunt: |
| + | |||
| + | * ''void addCookie(Cookie)'' – adaugă la răspuns obiectul ''Cookie'' specificat; | ||
| + | * ''void addDateHeader(String, long)'' – adaugă la răspuns un antet reprezentând o dată calendaristică, având numele şi valoarea specificate ca parametrii ai metodei; | ||
| + | * ''void addHeader(String, String)'' – adaugă la răspuns un antet având numele şi valoarea (şir de caractere) specificate ca parametrii ai metodei; | ||
| + | * ''void addIntHeader(String, int)'' – adaugă la răspuns un antet având numele şi valoarea (număr întreg) specificate ca parametrii ai metodei; | ||
| + | * ''boolean containsHeader(String)'' – verifică dacă un antet (indicat prin nume, dat ca parametru) a fost specificat în cadrul răspunsului; | ||
| + | * ''String encodeRedirectURL(String)'' – codifică URL-ul specificat ca parametru pentru a fi utilizat de metoda ''sendRedirect'' sau dacă nu este necesară codificarea, îl lasă neschimbat; | ||
| + | * ''String encodeURL(String)'' – codifică URL-ul specificat ca parametru (incluzând identificatorul sesiunii în cadrul său) sau dacă nu este necesară codificarea, îl lasă neschimbat; | ||
| + | * ''void flushBuffer()'' – forţează afişarea conţinutului zonei de memorie tampon în browser; | ||
| + | * ''boolean isCommitted()'' – verifică dacă răspunsul a fost transmis către client; | ||
| + | * ''void reset()'' – elimină toate informaţiile din zona de memorie tampon, inclusiv coduri de statut şi antete; | ||
| + | * ''void resetBuffer()''– elimină conţinutul zonei de memorie tampon, menţinând însă codurile de statut şi antetele intacte; | ||
| + | * ''void sendError(int[, String])'' – transmite un răspuns către client reprezentând o eroare indicată prin codul său (şi eventual printr-un mesaj) eliminând şi conţinutul zonei de memorie tampon; | ||
| + | * ''void sendRedirect(String)'' – transmite clientului un răspuns temporar de redirectare către o locaţie indicată prin URL-ul dat ca parametru; | ||
| + | * ''void setBufferSize(int)'' – stabileşte dimensiunea preferată (în octeţi) pentru zona de memorie ce reţine conţinutul răspunsului; | ||
| + | * ''void setCharacterEncoding(String)'' – stabileşte mecanismul de codificare a caracterelor (setul de caractere ''MIME'') corespunzând răspunsul transmis către client; | ||
| + | * ''void setContentLength(int)'' – stabileşte dimensiunea conţinutului transmis către client ca răspuns (pentru protocolul HTTP se stabilește valoarea pe care o are antetul ''Content-Length''); | ||
| + | * ''void setContentType(String)'' – stabileşte tipul de conţinut corespunzător răspunsului transmis către client, dacă această operaţie nu s-a produs deja; | ||
| + | * ''void setDateHeader(String, long)'' – stabileşte un antet reprezentând o dată calendaristică având numele şi valoarea specificate ca parametrii ai metodei; | ||
| + | * ''void setHeader(String, String)'' – stabileşte un antet cu numele şi valoarea (şir de caractere) specificate ca parametrii ai metodei; | ||
| + | * ''void setIntHeader(String, int)'' – stabileşte un antet cu numele şi valoarea (număr întreg) specificate ca parametrii ai metodei; | ||
| + | * ''void setLocale(Locale)'' – stabileşte localizarea răspunsului, dacă acesta nu a fost transmis către client; | ||
| + | * ''void setStatus(int)'' – stabileşte codul de stare pentru răspuns. | ||
| + | |||
| + | Stabilirea unor valori corespunzătoare antetelor HTTP din răspuns poate fi realizat astfel: | ||
| <code java> | <code java> | ||
| - | JAXBContext contextPersistentInterval; | + | ... |
| - | JAXBContext contextPersistentReservationData; | + | <% |
| + | response.setDateHeader("Last-Modified",System.currentTimeMillis()); | ||
| + | response.setHeader("Content-Type","text/html"); | ||
| + | response.setIntHeader("Refresh", 60); | ||
| + | %> | ||
| + | ... | ||
| + | </code> | ||
| - | public Reservation() { | + | În exemplu, se stabileşte valoarea antetului ''Last-Modified'' ca fiind momentul curent, tipul conţinutului pe care îl are transmis către client (indicat de antetul ''Content-Type'') ca fiind un document HTML, forţând reîncărcarea paginii în mod automat (prin antetul ''Refresh'') la fiecare 60 de secunde. |
| - | try { | + | |
| - | contextPersistentInterval = JAXBContext.newInstance(PersistentInterval.class); | + | === Obiectul implicit out === |
| - | contextPersistentReservationData = JAXBContext.newInstance(PersistentReservationData.class); | + | |
| - | } | + | Obiectul ''out'' este echivalentul obiectului ''PrintWriter'' din Java Servlets, fiind utilizat la afişarea conţinutului dinamic în cadrul paginii JSP, atunci când aceasta nu se poate face prin intermediul unor etichete HTML (eventual combinate cu expresii JSP). |
| - | catch (Exception exception) { | + | |
| - | System.out.println("An exception has occurred: "+exception.getMessage()); | + | <note tip>Spre diferenţă de obiectul ''PrintWriter'', un obiect ''JspWriter'' va genera excepţii de tipul ''java.io.IOException''. De asemenea, pune la dispoziţia utilizatorilor metode suplimentare pentru gestiunea zonei de memorie tampon.</note> |
| - | if (Constants.DEBUG) | + | |
| - | exception.printStackTrace(); | + | Iniţial, obiectul este instanţiat diferit în funcţie de activarea mecanismului de utilizare a unei zone de memorie tampon (aşa cum este specificat de atributul ''buffered'' al directivei ''page''). Metodele ''print'' şi ''println'' pot fi utilizate spre a afişa conţinutul unor obiecte cu tipurile ''boolean'', ''char'', ''String'', ''int'', ''long'', ''float'', ''double'', ''Object'' şi altele. De asemenea, metoda ''flush()'' este folosită pentru a transmite conţinutul zonei de memorie tampon către client, golind conţinutul fluxului de ieşire. |
| - | } | + | |
| - | + | === Obiectul implicit session === | |
| - | if (new File("timetable.xml").exists()) { | + | |
| - | timetable = unpackPersistentInterval("timetable.xml"); | + | Obiectul ''session'' este creat în mod automat (nu mai este necesară iniţializarea sau obţinerea dintr-un obiect de tip ''request'' prin metoda ''getSession()'') pentru fiecare client ce accesează pagina în cauză. Dezactivarea acestui tip de comportament poate fi realizată doar prin intermediul atributului cu acelaşi nume din directiva ''page''. |
| - | numberOfSeats = timetable.getNumberOfSeats(); | + | |
| - | } else { | + | Metodele pe care le pune la dispoziţie acest obiect sunt cele specificate de interfaţa ''javax.servlet.http.HttpSession'': |
| - | timetable = new PersistentInterval(); | + | * ''Object getAttribute(String)'' – întoarce obiectul care este asociat numelui transmis ca parametru al metodei în cadrul sesiunii sau ''null'' dacă nu există nici un obiect asociat; |
| - | packPersistentInterval(timetable, "timetable.xml"); | + | * ''Enumeration getAtrributeNames()'' – întoarce o enumerare ce conţine denumirile tuturor obiectelor asociate sesiunii; |
| - | } | + | * ''long getCreationTime()'' – întoarce momentul la care a fost creată sesiunea, exprimată în milisecunde raportate la data 1 ianuarie 1970 (GMT); |
| - | + | * ''String getId()'' – întoarce un şir de caractere care identifică în mod unic sesiunea; | |
| - | if (new File("reservationData.xml").exists()) { | + | * ''long getLastAccessedTime()'' – întoarce momentul la care clientul a transmis ultima dată o cerere asociată sesiunii, exprimată în milisecunde raportate la data 1 ianuarie 1970 (GMT); |
| - | reservationData = | + | * ''int getMaxInactiveInterval()'' – întoarce perioada de timp maximă, exprimată în secunde, în care containerul servletului va menţine sesiunea, între diferite accesări provenite de la clienţi; |
| - | unpackPersistentReservationData("reservationData.xml"); | + | * ''void invalidate()'' – invalidează sesiunea, eliminând orice asociere a unui obiect la aceasta; |
| - | } else { | + | * ''boolean isNew()'' – stabileşte dacă clientul nu are cunoştinţă de sesiune sau dacă alege să nu participe la aceasta; |
| - | reservationData = new PersistentReservationData(); | + | * ''void removeAttribute(String)'' – elimină asocierea obiectului identificat prin numele transmis ca parametru al metodei la sesiune; |
| - | packPersistentReservationData(reservationData,"reservationData.xml"); | + | * ''void setAttribute(String, Object)'' – asociază la sesiune un obiect ale cărui nume şi valoare sunt specificate ca parametrii ai metodei; |
| - | } | + | * ''void setMaxInactiveInterval(int)'' – stabileşte perioada de timp maximă, exprimată în secunde, care se poate scurge între diferite accesări provenite de la clienţi până când sesiunea va fi invalidată de containerul servletului; valoarea poate fi specificată şi în fişierul de configurare ''web.xml'': <code xml> |
| - | } | + | <session-config> |
| + | <session-timeout>60</session-timeout> | ||
| + | </session-config> | ||
| + | </code> Această valoare va suprascrie valoarea implicită specificată de serverul Apache Tomcat 8.x, care este de 30 de minute. În fişierul de configurare ''web.xml'' timpul de expirare va fi specificat, spre diferenţă de metoda ''setMaxInactiveInterval()'' nu în secunde, ci în minute. | ||
| + | |||
| + | În afară de sesiuni, pentru gestiunea comunicaţiei dintre client şi server, pot fi utilizate **cookie-uri**, fişiere text reţinute pe maşina client (dacă aceasta permite stocarea lor) şi citite de server pentru a identifica în mod unic conexiunea respectivă. Acestea sunt transmise de regulă prin antete HTTP, câmpul ''Set-Cookie'' reţinând perechi de tipul cheie-valoare pentru atributele ''name'', ''expires'', ''path'' şi ''domain''. De fiecare dată când clientul va accesa o pagină care corespunde cu valorile reţinute de atributele ''path'' şi ''domain'', în cazul în care nu a fost depăşită perioada specificată de atributul ''expires'', cookie-ul va fi inclus în antetele HTTP transmise către server. | ||
| + | |||
| + | Metodele pe care le pune la dispoziţie clasa ''Cookie'' sunt: | ||
| + | * ''String getComment()'' – întoarce comentariul care descrie scopul obiectului cookie sau ''null'' dacă nu există nici un comentariu asociat; | ||
| + | * ''String getDomain()'' – returnează domeniul pentru care se aplică obiectul cookie; | ||
| + | * ''int getMaxAge()'' – pune la dispoziţie durata de viaţă (exprimată în secunde) pentru obiectul cookie; valoarea -1 exprimă faptul că obiectul cookie va persista până când se va părăsi browserul; | ||
| + | * ''String getName()'' – obţine denumirea obiectului cookie; danumirea unui obiect cookie nu mai poate fi modificată după crearea sa; | ||
| + | * ''String getPath()'' – reflectă calea pentru care se aplică obiectul cookie; | ||
| + | * ''String getValue()'' – redă valoarea asociată obiectului cookie; | ||
| + | * ''void setComment(String)'' – fixează un comentariu care indică scopul obiectului cookie, acesta fiind util în situaţia în care browserul îl afişează utilizatorului pentru a lua o decizie în privinţa sa; | ||
| + | * ''void setDomain(String)'' – indică domeniul pentru care se aplică obiectul cookie; | ||
| + | * ''void setMaxAge(int)'' – stabileşte timpul (exprimat în secunde) care ar trebui să se scurgă înainte de expirarea obiectului cookie; în cazul în care atributul nu este precizat, obiectul cookie va exista doar pe parcursul sesiunii curente; | ||
| + | * ''void setPath(String)'' – setează calea pentru care se aplică obiectul cookie; dacă acest atribut nu este specificat, obiectul cookie este transmis pentru toate URL-urile care se găsesc în acelaşi director sau subdirector cu pagina curentă; | ||
| + | * ''void setSecure(boolean)'' – determină dacă obiectul cookie ar trebui transmis numai prin legături criptate; | ||
| + | * ''void setValue(String)'' – precizează valoarea asociată cu obiectul cookie. | ||
| + | |||
| + | Utilizarea unui obiect ''Cookie'' presupune crearea sa, precizarea duratei (maxime) de viaţă şi transmiterea sa în cadrul obiectului ''response'' la client prin metoda ''addCookie()''. | ||
| + | |||
| + | Crearea unui obiect de tip Cookie implică specificarea unei denumiri şi a valorii asociate. Nici denumirea şi nici valoarea asociată nu trebuie să conţină în cadrul lor caracterele ''['', '']'', ''('', '')'', ''='', '','', ''"'', ''/'', ''?'', ''@'', '':'', '';''. | ||
| + | |||
| + | Totodată, ştergerea presupune stabilirea duratei (maxime) de viaţă nule înainte de a fi inclus în antetele HTTP către browserul ce se ocupă cu reţinerea sa. | ||
| + | |||
| + | === Obiectul implicit application === | ||
| + | |||
| + | Obiectul ''application'' este de fapt un wrapper pentru obiectul ''ServletContext'' al servletului asociat paginii JSP, fiind o reprezentare a acesteia pe parcursul întregului său ciclu de viaţă, fiind iniţializat în metoda ''_jspInit()'' şi distrus în metoda ''_jspDestroy()''. Este folosit împreună cu metodele ''getAttribute(String)'' şi ''setAttribute(String, Object)'' atunci când se doreşte ca proprietăţile respective să aibă un domeniu de vizibilitate corespunzător întregii aplicaţii, adică tuturor paginilor care o alcătuiesc. O funcţionalitate ce se pretează folosirii acestui obiect este determinarea numărului de accesări al aplicaţiei respective. Într-o astfel de situaţie, pentru a se evita situaţia pierderii datelor în cazul repornirii aplicaţiei (serverului web care o găzduieşte), trebuie asigurată şi persistenţa acestora prin stocarea lor într-o bază de date. | ||
| + | |||
| + | === Obiectul implicit config === | ||
| + | |||
| + | Obiectul ''config'' este şi el un wrapper pentru obiectul ''ServletConfig'', permiţând programatorilor să acceseze parametrii de iniţializare ai motorului Java Servlet sau JSP, obţinuţi prin metodele ''getInitParameter(String)'', respectiv ''getInitParameterNames()''. Numele servletului asociat, aşa cum este specificat prin elementul ''<servlet-name>'' din fişierul de configurare ''web.xml'', poate fi accesat prin metoda ''getServletName()''. | ||
| + | |||
| + | === Obiectum implicit pageContext === | ||
| + | |||
| + | Obiectul ''pageContext'' este folosit ca o reprezentare a întregii pagini JSP, având scopul de a accesa informaţia cu privire la aceasta, evitând majoritatea detaliilor cu privire la implementare. Acest obiect reţine referinţe către obiectele ''request'' şi ''response'', iar obiectele ''config'', ''session'' şi ''out'' pot fi obţinute prin atribute ale sale. De asemenea, el conţine şi informaţii cu privire la directivele transmise paginii JSP. În cadrul său sunt definite mai multe câmpuri, printre care şi domeniile de vizibilitate ''PAGE_SCOPE'', ''REQUEST_SCOPE'', ''SESSION_SCOPE'', ''APPLICATION_SCOPE''. Implementează mai multe metode, majoritatea fiind moştenite din clasa ''javax.servlet.jsp.JspContext''. Se pot realiza operaţii pe atribute (stabilire, obţinere sau ştergere) de fiecare dată specificându-se şi domeniul său de vizibilitate. | ||
| + | |||
| + | === Obiectul implicit page === | ||
| + | |||
| + | Obiectul ''page'' este o referinţă către instanţa paginii JSP curente, în fapt un sinonim pentru obiectul ''this''. | ||
| + | |||
| + | === Obiectul implicit exception === | ||
| + | |||
| + | Obiectul ''exception'' este un wrapper ce conţine excepţia generată de către pagina anterioară, fiind folosit pentru a construi un răspuns adecvat la eroarea în cauză. Acesta este disponibil numai în paginile JSP de eroare, indicate prin atributul ''errorPage'' al directivei ''page'' spre a fi invocate în momentul în care se produc anumite erori. | ||
| + | |||
| + | O excepţie poate fi: | ||
| + | * verificată (o eroare de utilizator care nu poate fi prevăzută de programator, generată în momentul compilării); | ||
| + | * generată la rulare (ignorată la momentul compilării, dar care ar fi putut fi evitată prin anumite mecanisme de prevenţie); | ||
| + | * eroare, în privinţa căreia nu se poate face mare lucru, depăşind posibilităţile de intervenţie atât din partea utilizatorului cât şi din partea programatorului. | ||
| + | |||
| + | Fiind un obiect de tip ''java.lang.Throwable'', pentru un astfel de obiect pot fi apelate metodele: | ||
| + | * ''String getMessage()'' – oferă un mesaj detaliat cu privire la excepţia care s-a produs; acest mesaj detaliat cu privire la excepţia care s-a produs poate fi iniţializat în constructorul obiectului ''Throwable''. | ||
| + | * ''Throwable getCause()'' – întoarce cauza excepţiei; | ||
| + | * ''String toString()'' – întoarce numele clasei concatenat cu mesajul detaliat referitor la excepţia care s-a produs; | ||
| + | * ''void printStackTrace()'' – afişează rezultatul metodei ''toString()'' împreună cu stiva de erori la fluxul de ieşire pentru erori ''System.err''; | ||
| + | * ''StackTraceElement[] getStackTrace()'' – întoarce un vector conţinând fiecare element al stivei de erori; elementul de pe poziţia 0 reprezintă vârful stivei de erori, iar ultimul element reprezintă baza stivei de erori (metoda de la apelul căreia a pornit eroarea); | ||
| + | * ''Throwable filllnStackTrace()'' – completează stiva de erori a obiectului ''Throwable'' cu stiva de erori curentă. | ||
| + | |||
| + | Aceste metode pot fi obţinute şi prin intermediul obiectului ''pageContext'' care dispune de atributele ''exception'' (prin intermediul căruia poate fi vizualizată şi stiva de erori – atributul ''stackTrace'') şi ''errorData'' (ce oferă acces la calea relativă a paginii JSP care a generat eroarea – atributul URI şi codul de statut corespunzător excepţiei – atributul ''statusCode''). | ||
| + | |||
| + | Alternativ, în cadrul unui scriplet se poate folosi un bloc ''try { ... } catch'', tratarea erorii realizându-se în cadrul aceleiaşi pagini JSP. Totuşi, o astfel de abordare trebuie evitată, recurgându-se la ea numai în situaţia în care se vrea ca recuperarea din eroare să se realizeze cât mai rapid. | ||
| + | |||
| + | ==== Filtre ==== | ||
| + | |||
| + | Filtrele sunt folosite pentru a intercepta cererile de la un client înainte ca acestea să acceseze anumite resurse sau pentru a gestiona răspunsurile generate de server înainte ca acestea să fie transmise înapoi. Funcţionalitatea unui filtru trebuie specificată în metoda ''doFilter()'', care va fi suprascrisă de către orice clasă ce implementează interfaţa ''javax.servlet.Filter'': | ||
| + | |||
| + | <code java> | ||
| + | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, javax.servlet.ServletException | ||
| </code> | </code> | ||
| - | Contextul JAXB referitor la persistenţă va fi iniţializat cu tipul de date pentru care se doreşte conversia. Obiectele ''timetable'' şi ''reservationData'' sunt încărcate din fişier în constructor (în condiţiile în care fişierul corespunzator există, altfel aceste obiecte sunt create împreună cu fişierele care le reţin starea), descărcarea stării în fişier urmând a fi realizată în cadrul operaţiilor ''makeReservation()'' şi ''cancelReservation()'', care acţionează asupra lor. | + | Pot fi implementate filtre pentru autentificare, filtre pentru compresia datelor, filtre de criptare filtre care declanşează evenimente de acces a unor resurse, filtre de conversie a imaginilor, filtre pentru jurnalizare şi auditare, lanţuri de filtre MIME-TYPE, filtre pentru parsare şi filtre XSLT care transformă conţinutul XML. |
| - | Pentru aceasta, se vor implementa mecanismele corespunzătoare de împachetare şi despachetare puse la dispoziţie de contextul JAXB. | + | În afară de această metodă, mai trebuie implementate şi metodele ''init()'' şi ''destroy()''. |
| + | |||
| + | Asocierea dintre un filtru şi un Java Servlet sau pagină JSP precum şi ordinea execuţiei acestora este determinată din fişierul de configurare ''web.xml'' în care elementul ''<filter>'' indică numele filtrului, clasa asociată precum şi parametrii folosiţi la iniţializarea acestuia, iar elementul ''<filter-mapping>'' specifică asocierile (şi ordinea) dintre un filtru şi clasele Java Servlet respectiv paginile JSP. Ordinea în care sunt executate filtrele pentru un Java Servlet respectiv pagină JSP este aceeaşi cu cea în care acestea sunt mapate în fişierul de configurare ''web.xml''. Dacă se doreşte ca un filtru să fie asociat la mai multe resurse, se poate folosi masca ''%%/*%%'' în cadrul elementului ''<url-pattern>''. | ||
| + | |||
| + | ==== Încărcarea unui fișier pe server ==== | ||
| + | |||
| + | Încărcarea unui fişier pe server (la locaţia specificată de parametrul ''file-upload'' din fişierul de configurare ''web.xml'') se face prin intermediul unui formular care specifică ca tip de criptare (''enctype'') ''multipart/form-data'' în care controlul pentru intrare (''input'') este de tip (''type'') ''file'': | ||
| + | |||
| + | <code xml> | ||
| + | <context-param> | ||
| + | <param-name>file-upload</param-name> | ||
| + | <param-value> | ||
| + | My Upload Location | ||
| + | </param-value> | ||
| + | </context-param> | ||
| + | </code> | ||
| + | |||
| + | <code html> | ||
| + | <form action="myJSPPage.jsp" method="POST" enctype="multipart/form-data"> | ||
| + | <input type="file" name="file" size="100" /> | ||
| + | <br /> | ||
| + | <input type="submit" value="Upload File" /> | ||
| + | </form> | ||
| + | </code> | ||
| + | |||
| + | Pentru procesarea în cadrul paginii JSP a încărcării fişierului pe server, poate fi folosită [[http://commons.apache.org/proper/commons-fileupload/|biblioteca commons-fileupload]] dezvoltată de Apache ce oferă posibilitatea încărcării mai multor fişiere simultan, implementând metode pentru obţinerea diferitelor proprietăţi ale resursei respective (cale absolută, denumire, dimensiune) precum şi funcţionalităţi precum citirea din memorie şi scrierea pe disc. | ||
| + | |||
| + | ==== Invocarea altor resurse ==== | ||
| + | |||
| + | Frecvent, invocarea altor resurse se referă la redirectare, realizată atunci când documentul s-a mutat la o altă adresă sau atunci când se doreşte echilibrarea încărcării. În acest sens se foloseşte metoda ''sendRedirect()'' apelată pe obiectul ''response()'', care primeşte ca parametru URL-ul resursei către care se doreşte a se realiza redirectarea. Alternativ, acest comportament se poate obţine prin stabilirea unor valori pentru antetele HTTP: | ||
| <code java> | <code java> | ||
| - | public final void packPersistentInterval(PersistentInterval object, String file) { | + | response.setIntHeader("Status", response.SC_MOVED_TEMPORARILY); |
| - | try { | + | response.setHeader("Location", myLocation); |
| - | Marshaller conversion = contextPersistentInterval.createMarshaller(); | + | |
| - | conversion.marshal(object, new FileOutputStream(file)); | + | |
| - | } | + | |
| - | catch (Exception exception) { | + | |
| - | System.out.println("An exception has occurred: "+exception.printStackTrace()); | + | |
| - | if (Constants.DEBUG) | + | |
| - | exception.printStackTrace(); | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | public final void packPersistentReservationData(PersistentReservationData object, String file) { | + | |
| - | try { | + | |
| - | Marshaller conversion = contextPersistentReservationData.createMarshaller(); | + | |
| - | conversion.marshal(object, new FileOutputStream(file)); | + | |
| - | } | + | |
| - | catch (Exception exception) { | + | |
| - | System.out.println("An exception has occurred: "+exception.printStackTrace()); | + | |
| - | if (Constants.DEBUG) | + | |
| - | exception.printStackTrace(); | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | public final PersistentInterval unpackPersistentInterval(String file) { | + | |
| - | try { | + | |
| - | Unmarshaller conversion = contextPersistentInterval.createUnmarshaller(); | + | |
| - | return (PersistentInterval)conversion.unmarshal(new FileInputStream(file)); | + | |
| - | } | + | |
| - | catch (Exception exception) { | + | |
| - | System.out.println("An exception has occurred: "+exception.printStackTrace()); | + | |
| - | if (Constants.DEBUG) | + | |
| - | exception.printStackTrace(); | + | |
| - | } | + | |
| - | return null; | + | |
| - | } | + | |
| - | + | ||
| - | public final PersistentReservationData unpackPersistentReservationData(String file) { | + | |
| - | try { | + | |
| - | Unmarshaller conversion = contextPersistentReservationData.createUnmarshaller(); | + | |
| - | return (PersistentReservationData)conversion.unmarshal(new FileInputStream(file)); | + | |
| - | } | + | |
| - | catch (Exception exception) { | + | |
| - | System.out.println("An exception has occurred: "+exception.printStackTrace()); | + | |
| - | if (Constants.DEBUG) | + | |
| - | exception.printStackTrace(); | + | |
| - | } | + | |
| - | return null; | + | |
| - | } | + | |
| </code> | </code> | ||
| - | ===== Interogarea unui serviciu web ===== | + | ==== Operații cu obiecte de tip dată calendaristică === |
| - | Pe baza fişierului WSDL care descrie serviciul web sunt generate clasele ce permit invocarea funcţionalităţii puse la dispoziţie de acesta. Pentru generarea unui serviciu web se foloseşte comanda ''wsgen'', în timp ce pentru importarea unui serviciu web (spre a putea fi invocat) se foloseşte comanda ''wsimport''. | + | În cadrul aplicaţiilor web, se lucrează destul de des cu obiecte de tipul dată calendaristică, integrarea lor în cadrul tehnologiei Java Servlets sau JSP făcându-se prin obiecte de tip ''java.util.Date'', ce pot fi create fie prin intermediul unui constructor vid (caz în care obiectul va conţine data curentă) sau al unui constructor ce primeşte un parametru de tip ''long'', ce indică durata, exprimată în milisecunde, care s-a scurs de la 1 ianuarie 1970 (GMT). Operaţiile pe care le suportă un astfel de obiect sunt ''after(Date)'', ''before(Date)'', ''clone()'', ''compareTo(Date[|Object])'', ''equals(Object)'', ''getTime()'', ''hasCode()'', ''setTime(long)'', ''toString()''. Formatarea unui astfel de obiect se poate realiza folosind clasa ''SimpleDateFormat'' în care anumite caractere codifică atributele obiectului ''Date''. |
| - | <note tip>Utilitarele ''wsgen'', respectiv ''wsimport'' sunt incluse în distribuţia standard Java, începând cu versiunea 6.</note> | + | ==== Funcționalitate de tip poștă electronică ==== |
| - | <code bash> | + | De asemenea, se întâlneşte frecvent necesitatea de a transmite mesaje folosind poşta electronică, o astfel de funcţionalitate putând fi integrată prin [[https://java.net/projects/javamail/pages/Home|API-ul JavaMail]] şi [[http://www.oracle.com/technetwork/java/javamail/index-135046.html|framework-ul Java Activation Framework (JAF)]]. |
| - | wsgen [options] <SEI> | + | |
| + | Un obiect ''Session'' necesar construirii unui mesaj ce poate fi transmis prin poşta electronică va fi construit dintr-o serie de proprietăţi între care obligatorie este ''mail.smtp.host''. În situaţia în care serverul de poştă electronică necesită autentificare, vor fi precizate şi atributele ''mail.user'' / ''mail.password''. Obiectul reprezentând mesajul propriu-zis va avea tipul ''MimeMessage'', precizarea câmpurilor corespunzătoare (''From:'', ''To:'', ''Subject:'' şi ''Text:'') realizându-se prin metodele: | ||
| + | * ''void setFrom(InternetAddress)'' – parametrul metodei construindu-se pornind de la adresa de poştă electronică a destinatarului; | ||
| + | * ''void addRecipients(Message.RecipientType, Address[])'', unde | ||
| + | * tipul poate avea valorile: | ||
| + | * ''Message.RecipientType.TO''; | ||
| + | * ''Message.RecipientType.CC'' (CarbonCopy); | ||
| + | * ''Message.RecipientType.BCC'' (Blind Carbon Copy). | ||
| + | * vectorul de adrese se creează folosind constructorul ''InternetAddress'' căruia i se transmite ca parametru adresa de poştă electronică a expeditorului. | ||
| + | * ''void setSubject(String)'' – se stabileşte subiectul mesajului; | ||
| + | * ''void setText(String)'' – se precizează corpul mesajului; | ||
| + | * ''void setContent(String, String)'' – se precizează corpul mesajului, având atât conţinutul, cât şi formatul precizate ca parametri; în acest mod se pot transmite documente care au alt format în afară de ''plain-text'', de exemplu HTML / XML. În acest caz, dimensiunea pe care o poate avea corpul mesajului nu este limitată decât de serverul de poştă electronică. | ||
| + | |||
| + | Transmiterea propriu-zisă a mesajului se face prin metoda statică ''send()'' definită în clasa ''Transport'', aceasta generând o excepţie ''MessagingException'' dacă mesajul nu a putut fi transmis din diverse motive. | ||
| + | |||
| + | De asemenea, pot fi incluse ataşamente prin construirea unui obiect MimeMultiPart la care se adaugă (folosind metoda ''addBodyPart()'') fragmente ale ataşamentului respectiv, de tipul ''MimeBodyPart''. Un astfel de obiect suportă metodele ''setText(String)'' pentru a indica o corpul mesajului, respectiv ''setDataHandler(DataHandler)'' şi ''setFileName(String)'' pentru a specifica fişierul care conţine ataşamentul. Indicarea conţinutului ca fiind un obiect de tipul MimeMultiPart se face tot prin metoda ''setContent()''. | ||
| + | |||
| + | Un obiect de tip ''DataHandler'' se obţine dintr-un obiect ''FileDataSource'', care la rândul său este construit pornind de la denumirea fişierului în cauză, la care se adaugă şi calea către el, relativă sau absolută. În situaţia în care nu se specifică nici o cale, fişierul va fi căutat în acelaşi director în care este plasată clasa Java Servlet sau pagina JSP care încearcă transmiterea sa prin intermediul poştei electronice. | ||
| + | |||
| + | Informaţiile cu privire la destinatar, expeditor, subiect şi conţinut pot fi incluse într-un formular, apoi preluate din obiectul ''request'' astfel încât transmiterea mesajului să se facă pe baza acestora. | ||
| + | |||
| + | <code java> | ||
| + | <%@ page import="javax.mail.*", "javax.mail.internet.*", "javax.activation.*" %> | ||
| + | ... | ||
| + | <% | ||
| + | Properties properties = System.getProperties(); | ||
| + | properties.setProperty("mail.smtp.host","localhost"); | ||
| + | properties.setProperty("mail.user",myUser); | ||
| + | properties.setProperty("mail.password",myPassword); | ||
| + | Session mailSession = Session.getDefaultInstance(properties); | ||
| + | try { | ||
| + | MimeMessage mailMimeMessage = new MimeMessage(maiSession); | ||
| + | mailMimeMessage.setFrom(new InternetAddress(from)); | ||
| + | mailMimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); | ||
| + | mailMimeMessage.setSubject("My Subject"); | ||
| + | Multipart mailMultipart = new MimeMultipart(); | ||
| + | BodyPart mailBodyPart; | ||
| + | mailBodyPart = new MimeBodyPart(); | ||
| + | mailBodyPart.setText("My Mail Body"); | ||
| + | mailMultipart.addBodyPart(mailBodyPart); | ||
| + | mailBodyPart = new MimeBodyPart(); | ||
| + | String filename = "myFileName.myExtension"; | ||
| + | mailBodyPart.setDataHandler(new DataHandler(new FileDataSource(filename))); | ||
| + | mailBodyPart.setFileName(filename); | ||
| + | mailMultiPart.addBodyPart(mailBodyPart); | ||
| + | mailMimeMessage.setContent(mailMultiPart); | ||
| + | Transport.send(mailMimeMessage); | ||
| + | } catch (MessagingException exception) { | ||
| + | System.out.println("An exception has occurred: "+exception.getMessage(); | ||
| + | if (Constants.DEBUG) { | ||
| + | exception.printStackTrace(); | ||
| + | } | ||
| + | } | ||
| + | %> | ||
| </code> | </code> | ||
| - | unde | + | ===== Utilizarea EL (Expression Language) în pagini JSP ===== |
| - | * ''options'' | + | |
| - | ^ opțiune ^ semnificație ^ | + | EL (Expression Language) pune la dispoziţia utilizatorilor un mecanism prin care nivelul de prezentare poate comunica cu nivelul de logică al aplicaţiei (mai ales componente Java Beans), implementând operaţii aritmetice şi logice folosind tipuri de date întregi, reale, şiruri de caractere, valori adevărat / fals şi ''null''. |
| - | | ''-classpath <path>'' | precizează locația la care pot fi găsite clasele de intrare și extensiile | | + | |
| - | | ''-cp <path>'' | indică locația la care pot fi găsite clasele de intrare și extensiile | | + | |
| - | | ''-d <directory>'' | indică locația la care vor fi plasate fișierele de ieșire | | + | |
| - | | ''-encoding <encoding>'' | specifică mecanismul de codificare al caracterelor folosit de fișierele ce conțin codul sursă | | + | |
| - | | ''-extension'' | permite utilizarea unor extensii ale producătorului (funcționalitate care nu este cuprinsă în specificație), de exemplu ''-Xnocompile'' nu compilează clasele Java generate; totuși, utilizarea de extensii poate determina ca aplicația obțiinută să nu fie portabilă / să nu poată interacționa cu alte implementări | | + | |
| - | | ''-help'' | afișează informațiile de ajutor | | + | |
| - | | ''-J<javacOption>'' | transmite opțiunea către compilatorul ''javac'' | | + | |
| - | | ''-keep'' | determină păstrarea fișierelor generate | | + | |
| - | | ''-r <directory>'' | indică locația la care vor fi plasate resursele (de exemplu, WSDL-urile) | | + | |
| - | | ''-s <directory>'' | specifică locația la care va fi plasat codul sursă generat | | + | |
| - | | ''-verbose'' | afișeză mesaje cu privire la operațiile realizate la momentul curent | | + | |
| - | | ''-version'' | afișează informațiile legate de versiunea utilitarului | | + | |
| - | | ''-fullversion'' | afișează informațiile complete legate de versiunea utilitarului | | + | |
| - | | ''-wsdl[:protocol]'' | generează un fișier WSDL\\ ''protocol'' este opțional și poate avea valorile\\ ✔ ''soap1.1'' (implicit)\\ ✔ ''Xsoap1.2'' (nonstandard) - poate fi folosit numai împreună cu opțiunea ''-extension'' | | + | |
| - | | ''-inlineSchemas'' | include schemele XML în fișierul WSDL generat (poate fi folosit numai împreună cu opțiunea ''-wsdl'') | | + | |
| - | | ''-servicename <name>'' | specifică denumirea serviciului care va fi folosit în fișierul WSDL generat (poate fi folosit numai împreună cu opțiunea ''-wsdl'') | | + | |
| - | | ''-portname <name>'' | specifică denumirea portului care va fi folosit în fișierul WSDL generat (poate fi folosit numai împreună cu opțiunea ''-wsdl'') | | + | |
| - | | ''-x <file>'' | indică un descriptor XML ce conține metadate despre un serviciu web extern | | + | |
| - | * ''SEI'' - reprezintă clasa Java conținând implementarea serviciului web | + | Tehnologia Java Server Pages foloseşte Expression Language pentru: |
| + | * evaluarea imediată şi leneşă a expresiilor prin realizarea de operaţii aritmetice şi logice în mod dinamic; | ||
| + | * posibilitatea de a stabili şi de a obţine informaţii (având structuri de date variate), în special proprietăţi ale componentelor Java Beans, pe baza interacţiunii cu utilizatorul; | ||
| + | * folosirea de obiecte implicite; | ||
| + | * abilitatea de a invoca metode (publice şi statice). | ||
| - | <note tip>În cazul în care clasa Java ce conține implementarea serviciului web face parte dintr-un pachet, el trebuie precizat complet la denumirea acesteia.</note> | + | În Expression Language pot fi folosite următoarele tipuri de expresii: |
| + | * **expresii cu evaluare imediată** (a căror valoare este stabilită instant de către tehnologia împreună cu care este utilizată, în cazul de faţă Java Server Pages) şi **expresii cu evaluare leneşă** (a căror valoare poate fi evaluată ulterior de către tehnologia împreună cu care este utilizată); | ||
| + | * **expresii valoare** (ce referă date) şi **expresii metodă** (ce invocă metode); | ||
| + | * **expresii rvalue** (care pot doar să citească date dintr-un obiect extern) şi **expresii lvalue** (care pot atât să citească cât şi să scrie date din / într-un obiect extern). | ||
| - | Exemplu: <code bash> | + | Expresiile cu evaluare imediată, desemnate prin sintaxa ''${expression}'', sunt calculate înainte ca pagina Internet să fie afişată. Aceste expresii pot fi folosite numai ca valori ale unei etichete care acceptă expresii evaluate în momentul rulării şi sunt întotdeauna expresii de tip rvalue. |
| - | wsgen -cp . ro.pub.cs.aipi.lab06.reservation.Reservation -wsdl -servicename {http://localhost:8080/ReservationService}Reservation | + | |
| + | <code java> | ||
| + | <input type="submit" name="${inputName}" value="${inputValue}"> | ||
| </code> | </code> | ||
| - | <code bash> | + | Pentru expresiile cu evaluare leneşă, pentru care se foloseşte sintaxa ''#{expression}'', valoarea poate fi determinată mai târziu, prin mecanisme ce ţin de tehnologia împreună cu care e folosită Expression Language, pe parcursul ciclului de viaţă al paginii Internet. Aceste expresii pot fi expresii valoare utilizate atât pentru a citi cât şi pentru a scrie informaţii dar şi expresii metodă. |
| - | wsimport [options] <WSDL_URI> | + | |
| + | <code java> | ||
| + | <table><tr><td>#{inputName}</td><td>#{inputValue}</td></tr></table> | ||
| </code> | </code> | ||
| - | unde | + | <note>De regulă, expresiile cu evaluare leneşă sunt folosite mai des împreună cu JavaServer Faces pentru că această tehnologie are un ciclu de viaţă împărţit în mai multe faze, astfel încât determinarea valorii unei expresii nu se poate realiza decât la un anumit moment, după tratarea evenimentelor cu privire la componente şi validarea datelor.</note> |
| - | * ''options'' | + | |
| - | ^ opțiune ^ semnificație ^ | + | Expresiile de tip valoare pot fi clasificate în expresii rvalue şi lvalue după cum dispun sau nu de posibilitatea de a scrie informaţii. Expresiile cu evaluare imediată sunt întotdeauna expresii rvalue, în timp ce expresiile cu evaluare leneşă sunt de regulă expresii lvalue. |
| - | | ''-b <path>'' | indică fișierele de asociere jaxws/jaxb sau scheme suplimentare (fiecare cale trebuie să fie prefixată de opțiunea ''-b'') | | + | |
| - | | ''-B<jaxbOption>'' | transmite opțiunea către compilatorul de scheme JAXB | | + | |
| - | | ''-catalog <file>'' | precizează fișierul ce conține catalogul pentru rezolvarea referințelor către entități externe (sunt suportate formatele ''TR9401'', ''XCatalog'', ''Oasis XML'') | | + | |
| - | | ''-classpath <path>'' | precizează locația la care pot fi găsite clasele de intrare și extensiile | | + | |
| - | | ''-cp <path>'' | indică locația la care pot fi găsite clasele de intrare și extensiile | | + | |
| - | | ''-d <directory>'' | indică locația la care vor fi plasate fișierele de ieșire | | + | |
| - | | ''-encoding <encoding>'' | specifică mecanismul de codificare al caracterelor folosit de fișierele ce conțin codul sursă | | + | |
| - | | ''-extension'' | permite utilizarea unor extensii ale producătorului (funcționalitate care nu este cuprinsă în specificație); totuși, utilizarea de extensii poate determina ca aplicația obțiinută să nu fie portabilă / să nu poată interacționa cu alte implementări | | + | |
| - | | ''-help'' | afișează informațiile de ajutor | | + | |
| - | | ''-httpproxy:<proxy>'' | stabilește un proxy HTTP, având formatul ''[user[:password]@]proxyHost:proxyPort'', unde ''proxyPort'' are valoarea implicită 8080 | | + | |
| - | | ''-J<javacOption>'' | transmite opțiunea către compilatorul ''javac'' | | + | |
| - | | ''-keep'' | determină păstrarea fișierelor generate | | + | |
| - | | ''-p <pkg>'' | indică pachetul în care va fi generat codul sursă | | + | |
| - | | ''-quiet'' | oprește afișarea mesajelor cu privire la operațiile realizate la momentul curent | | + | |
| - | | ''-s <directory>'' | specifică locația la care va fi plasat codul sursă generat | | + | |
| - | | ''-target <version>'' | generează codul sursă în funcție de versiunea specificației JAXWS indicată\\ ✔ 2.0\\ ✔ 2.1\\ ✔ 2.2 (implicit) | | + | |
| - | | ''-verbose'' | afișeză mesaje cu privire la operațiile realizate la momentul curent | | + | |
| - | | ''-version'' | afișează informațiile legate de versiunea utilitarului | | + | |
| - | | ''-fullversion'' | afișează informațiile complete legate de versiunea utilitarului | | + | |
| - | | ''-wsdllocation <location>'' | specifică valoarea locației de unde va fi preluat fișierul WSDL conținând specificația serviciului web (parametrul ''@WebServiceClient.wsdlLocation'') | | + | |
| - | | ''-clientjar <jarfile>'' | creează o arhivă .jar conținând codul sursă generat împreună cu metadatele WSDL necesare pentru invocarea serviciului web | | + | |
| - | | ''-generateJWS'' | stabilește generarea unui fișier ce conține implementarea JWS | | + | |
| - | | ''-implDestDir <directory>'' | indică locația la care vor fi generate fișierele ce conțin implementarea JWS | | + | |
| - | | ''-implServiceName <name>'' | precizează denumirea locală a serviciului pentru implementarea JWS | | + | |
| - | | ''-implPortName <name>'' | precizează portul local al serviciului pentru implemnentarea JWS | | + | |
| - | iar extensiile suportate sunt: | + | Expresia ''${entitybean.attribute}'' obţine valoarea unui atribut din cadrul unei componente Java Bean, evaluându-l instant şi transmiţând mai departe rezultatul obţinut. |
| - | | ''-XadditionalHeaders'' | asociează antetele care nu sunt legate de mesaje de cerere sau de răspuns la parametrii ai unor metode | | + | Expresia ''#{entitybean.attribute}'' poate avea acelaşi comportament ca expresia de mai sus, însă eticheta în cadrul căreia este folosită poate decide evaluarea sa la un moment de timp ulterior. Mai mult, atunci când pagina Internet este solicitată, expresia va fi de tipul rvalue (obţinând valoarea atributului), în timp ce în cadrul etapei postback ea poate fi de tipul lvalue (putând stabili valoarea atributului). |
| - | | ''-Xauthfile'' | specifică fișierul care conține informațiile de autorizare în formatul ''http://username:password@hostname/servicename?wsdl'' | | + | |
| - | | ''-Xdebug'' | afișează informațiile pentru depanarea codului | | + | |
| - | | ''-Xno-addressing-databinding'' | activează asocierea tipurilor W3C EndpointReferenceType către clase din limbajul de programare Java | | + | |
| - | | ''-Xnocompile'' | determină ca fișierele Java generate să nu fie compilate | | + | |
| - | | ''-XdisableAuthenticator'' | dezactivează mecanismul de autentificare folosit de JAX-WS RI, ignorând opțiunea ''-Xauthfile'', dacă este precizată | | + | |
| - | | ''-XdisableSSLHostnameVerification'' | dezactivează verificarea mașinilor cu privire la configurația SSL la transferul fișierelor WSDL | | + | |
| - | * ''WSDL_URI'' - reprezintă locația fișierului WSDL care conține descrierea serviciului web | + | Toate expresiile pot referi următoarele tipuri de obiecte, împreună cu atributele lor: componente Java Beans, colecţii, structuri de date Java de tip enumerare, obiecte implicite. Pentru a le utiliza, se foloseşte o expresie în care variabila este reprezentată de denumirea obiectului: |
| - | Exemplu: <code bash> | + | <code java> |
| - | wsimport -s . http://localhost:8080/ReservationService/Reservation?wsdl | + | ${myObject} |
| + | #{myObject} | ||
| </code> | </code> | ||
| - | Astfel, pentru fiecare metodă implementată de serviciul web (definită ca operation în secţiunea binding a fişierului WSDL) sunt generate clasele ''Operation'' şi ''OperationResponse'', responsabile cu transmiterea cererilor și răspunsurilor prin infrastructura de comunicație: | + | <note tip>În cazul structurilor de date Java de tip enumerare, elementele pot fi referite folosind tipul ''String''. Pentru tipul de dată ''public enum EnumType {attribute<sub>1</sub>, atrribute<sub>2</sub>, ..., attribute<sub>n</sub>}'', dacă este întâlnit un şir de caractere având valoarea ''${"atrribute<sub>k</sub>"}'', acesta va fi convertit automat la tipul ''EnumType.atrribute<sub>k</sub>''.</note> |
| - | * clasa ''Operation'' oferă metode pentru transferul parametrilor metodelor accesibile la distanță; | + | |
| - | * clasa ''OperationResponse'' oferă metode pentru transferul valorilor întoarse ale metodelor accesibile la distanță. | + | |
| - | De asemenea, este furnizată și o fabrică de obiecte (''ObjectFactory'') pentru crearea unor instanțe ale acestor clase. | + | Container-ul paginii Internet evaluează variabila ce apare în expresie căutându-i valoarea ce este oferită de ''PageContext.findAttribute("myObject")'', domeniile de vizibilitate investigate fiind ''page'', ''request'', ''session'' şi ''application''. Dacă obiectul nu este găsit, se returnează o valoare ''null''. Pot fi utilizare motoare EL particularizate pentru a se modifica modul în care sunt evaluate expresiile. |
| - | Totodată, sunt generate şi clasele corespunzătoare obiectelor transmise ca parametrii sau rezultate întoarse, în care tipul atributelor este însă transformat astfel încât să poată fi transmise prin infrastructura de comunicaţie. | + | Pentru a referi proprietăţile unei componente Java Bean sau a instanţei unei enumerări, elementele unei colecţii sau atributele unui obiect implicit pot fi folosite notaţiile ''.'' sau ''[]'', care sunt echivalente. Pentru şirurile de caractere se pot folosi atât apostroafe, cât şi ghilimele. |
| - | <note>Spre exemplu, în cazul claselor ''Interval'' / ''ReservationData'', obiectele de tip ''GregorianCalendar'' sunt convertite în mod automat la tipul de date echivalent ''XMLGregorianCalendar''. | + | Următoarele expresii sunt echivalente: |
| - | Transformările suferite de un astfel de obiect la transferul său de la server, prin infrastructura de comunicație și până la client sunt: ''GregorianCalendar'' → ''xs:dateTime'' → ''XMLGregorianCalendar''. | + | <code java> |
| + | ${myObject.myAttribute} | ||
| + | </code> | ||
| - | Transformările suferite de un astfel de obiect la transferul său de la clinet, prin infrastructura de comunicație și până la server sunt: ''XMLGregorianCalendar'' → ''xs:anySimpleType'' → ''java.lang.Object'' → ''GregorianCalendar''.</note> | + | <code java> |
| + | ${myObject['myAttribute']} | ||
| + | </code> | ||
| - | Invocările metodelor implementate în cadrul serviciului web se fac printr-un obiect local care funcţionează ca un delegat pentru serviciul la distanţă. Acesta este obţinut ca port al unei alte clase generate pe baza serviciului web în care sunt definite metodele, având denumirea sufixată de ''_Service''. | + | <code java> |
| + | ${myObject["myAttribute"]} | ||
| + | </code> | ||
| - | <note>În literatura de specialitate, se foloseşte denumirea de port pentru obiectul delegat corespunzător serviciului web la distanţă, ce conţine interfaţa (SEI – Service Endpoint Interface) definită de acesta.</note> | + | Expresii similare pot fi formate şi pentru asigurarea evaluării leneşe. |
| - | <file java Client.java> | + | De asemenea, pot fi folosite şi combinaţii ale operatorilor ''.'' şi ''[]'' în cadrul aceleiaşi expresii. |
| - | public class Client { | + | |
| - | @WebServiceRef(wsdlLocation = "META-INF/wsdl/localhost_8080/ReservationService/Reservation.wsdl") | + | <note important>În cazul componentelor JavaBeans, un atribut ''myAttribute'' poate fi referit în cadrul unei expresii EL doar în situaţia în care este implementată o metodă getter de acces la acesta, având numele ''getMyAttribute()''.</note> |
| - | private static Reservation_Service service; | + | |
| - | public static void main(String[] args) { | + | Pentru accesarea elementelor unui vector sau al unei liste, trebuie folosite valori literale (fără apostroafe sau ghilimele) ce pot fi convertite la un întreg sau notaţia ''[]'' ce primeşte de asemenea un întreg, în timp ce pentru un obiect de tip ''Map'' accesarea implică folosirea unei chei de tip şir de caractere: |
| - | service = new reservation.Reservation_Service(); | + | |
| - | reservation.Reservation port = service.getReservationPort(); | + | |
| - | + | ||
| - | List<Interval> timetable = port.getTimeTable(); | + | |
| - | for (Interval timetableEntry:timetable) { | + | |
| - | System.out.println ("interval in timetable: "+timetableEntry.getStartingTime().toXMLFormat()+"->"+timetableEntry.getEndingTime().toXMLFormat()); | + | |
| - | } | + | |
| - | } | + | |
| - | } | + | |
| - | </file> | + | |
| - | Prin adnotarea ''@WsdlServiceRef'' se indică fișierul WSDL care conține descrierea serviciului web referit, acesta trebuind să existe la locația specificată de parametrul ''wsdlLocation''. | + | <code java> |
| + | // array or list: firstComponent can be narrowed to 0 | ||
| + | ${myObject.myAttribute[0]} | ||
| + | ${myObject.myAttribute[firstComponent]} | ||
| + | </code> | ||
| - | <note tip>Locația specificată de parametrul ''wsdlLocation'' poate referi și un fișier WSDL existent pe un server web, de exemplu: http://localhost:8080/ReservationService/Reservation?wsdl.</note> | + | <code java> |
| + | // map | ||
| + | ${myObject.myAttribute["firstComponent"]} | ||
| + | </code> | ||
| + | |||
| + | În Expression Language pot fi folosite următoarele tipuri de date: | ||
| + | * ''Boolean'': poate avea valorile ''true'' sau ''false''; | ||
| + | * numere întregi, numere reale: utilizate la fel ca în Java; | ||
| + | * ''String'' (şir de caractere), referite cu apostroafe sau ghilimele, ''\'' fiind folosit pe post de caracter escape (''"'' → ''\"'', ''''' → ''\''', ''\'' → ''\\''); | ||
| + | * ''null''. | ||
| - | Pe baza acestei descrieri, vor fi generate în mod automat clasele responsabile cu transportul parametrilor și valorilor întoarse ale metodelor accesibile la distanță. | + | Expresiile de tip valoare pot fi utilizate în text static sau în etichete (standard sau definite de utilizator) care acceptă o expresie. Unele etichete acceptă doar expresii de tip rvalue în timp ce alte expresii pot accepta şi expresii de tip lvalue. |
| - | În situația în care există mai multe servicii web care pun la dispoziție aceeași funcționalitate (aceleași metode accesibile la distanță), dar cu implementări diferite, există posibilitatea **invocării dinamice** (în momentul execuției), serviciul fiind obținut pe baza metodei statice ''create()'' din cadrul clasei ''Service'', primind ca parametrii denumirea sa și locația la care este disponibil documentul WSDL ce îi descrie funcționalitatea: | + | Valoarea unei expresii în text static este evaluată şi ulterior inclusă în pagina Internet: |
| <code java> | <code java> | ||
| - | public static Service create(URL wsdlDocumentLocation, QName serviceName) throws javax.xml.ws.WebServiceException {} | + | <my:tag>my text1 ${expression} my text2</my:tag> |
| </code> | </code> | ||
| - | Un exemplu de instanțiere a unui astfel de serviciu ar putea fi: | + | Atributul valoare al unei etichete poate fi iniţializat folosind o expresie rvalue sau lvalue astfel: |
| + | * folosind o singură expresie; expresiile sunt evaluate şi rezultatul convertit la tipul atributului respectiv: <code java> | ||
| + | <my:tag value="${expression}" /> | ||
| + | <my:tag value="#{expression}" /> | ||
| + | </code> | ||
| + | * folosind una sau mai multe expresii, separate sau înconjurate de text; se numesc **expresii compuse** şi sunt evaluate de la stânga la dreapta, fiecare expresie fiind convertită la tipul ''String'' şi concatenată cu alte texte, şirul de caractere rezultat fiind convertit la tipul atributului respectiv: <code java> | ||
| + | <my:tag value="my text1 ${expression1} my text2 ${expression2}" /> | ||
| + | <my:tag value="my text1 #{expression1} my text2 #{expression2}" /> | ||
| + | </code> În EL 3.0 operatorul ''+'' e folosit pentru concatenarea şirurilor de caractere. | ||
| + | * folosind doar text; se numesc **expresii literale** şi valoarea ''String'' a atributului este converită la tipul atributului respectiv <code java> | ||
| + | <my:tag value="my text" /> | ||
| + | </code> | ||
| + | |||
| + | Toate expresiile utilizate pentru a stabili valori sunt evaluate în contextul unui tip de date aşteptat. Dacă rezultatul obţinut în urma evaluării expresiei nu corespunde exact tipului de date aşteptat, se va realiza o conversie de tip. | ||
| + | |||
| + | Expresiile de tip metodă permit invocarea unei metode implementate în cadrul unei componente Java Bean, care întoarce un rezultat. De regulă, acestea sunt folosite pentru a realiza anumite procesări asociate cu controlul din contextul căruia sunt apelate, fiind invocate în momentul în care este generat un eveniment în cadrul acelui control. Întrucât o metodă poate fi invocată pe parcursul diferitelor etape ale ciclului de viaţă, expresiile de tip metodă trebuie să fie întotdeauna cu evaluare leneşă. | ||
| <code java> | <code java> | ||
| - | try { | + | <my:tag id="myTagId" action="#{myObject.myValue}" /> |
| - | URL wsdlDocumentLocation = new URL("http://localhost:8080/reservation/Reservation?wsdl"); | + | <my:tag id="myTagId" action="#{myObject['myValue']}" /> |
| - | QName serviceName = new QName("http://reservation.lab06.aipi.cs.pub.ro/Reservation", "Reservation"); | + | |
| - | Service service = Service.create(wsdlDocumentLocation, serviceName); | + | |
| - | } catch (MalformedURLException malformedURLException) { | + | |
| - | System.out.println("An exception had occurred: "+malformedURLException.getMessage()); | + | |
| - | if (Constants.DEBUG) | + | |
| - | malformedURLException.printStackTrace(); | + | |
| - | } | + | |
| </code> | </code> | ||
| - | Ulterior, funcționalitatea îi poate fi invocată prin intermediul metodei ''getPort()'' a obiectului de tip ''Service'', care primește ca parametru clasa pe care o reprezintă (la care va fi convertit): | + | Expresiile de tip metodă trebuie folosite întotdeauna numai în cadrul unei etichete, fie folosind o singură expresie care este evaluată şi transmisă modulului de gestiune a etichetei, putând fi invocată mai târziu sau folosind doar text. La execuţia metodei asociată expresiei în cauză, se întoarce un rezultat de tip ''String'' care este convertit la tipul aşteptat, aşa cum este definit de descriptorul bibliotecii de etichete. |
| + | |||
| + | Expresiile de tip metodă pot fi utilizate pentru a invoca funcţii care primesc un set de parametrii (0 sau mai mulţi, separaţi prin virgulă). Se pot folosi atât operatorul ''.'' cât şi ''[]'', comportamentul acestora fiind similar: | ||
| <code java> | <code java> | ||
| - | public <T> T getPort(Class<T> serviceEndpointInterface) throws javax.xml.ws.WebServiceException {} | + | myObject["myMethod"](myparameters) |
| + | myObject.myMethod(myParameters) | ||
| </code> | </code> | ||
| - | Un exemplu de obținere a unui port pentru care pot fi invocate ulterior serviciile pot fi: | + | În Expression Language pot fi folosite şi expresii lambda, acestea fiind expresii de tip valoare ce primesc parametrii. Utilizarea acestora este comparabilă cu cazul limbajului de programare Java, cu excepţia faptului că şi corpul expresiei lambda este tot o expresie EL. O expresie lambda foloseşte operatorul ''->'', identificatorii din stânga expresiei fiind parametrii lambda, în dreapta expresiei aflându-se o expresie EL. De obicei, se folosesc parantezele ''()'' pentru a include parametrii lambda, acestea putând fi omise dacă există un singur parametru. |
| + | |||
| + | O expresie lambda are un comportament asemănător cu al unei funcţii, aceasta putând fi apelată imediat sau valoarea ei poate fi asociată unei variabile ce va fi utilizată ulterior pentru invocarea metodei respective primind parametrii care vor fi disponibili la momentul respectiv. | ||
| + | |||
| + | O expresie lambda poate fi transmisă ca argument al unei metode, fiind executată în cadrul metodei respective sau poate fi inclusă la rândul ei, în altă expresie lamda. | ||
| <code java> | <code java> | ||
| - | Reservation port = service.getPort(Reservation.class); | + | () -> null |
| + | (x,y) -> (x+y)/2 | ||
| + | ((x,y) -> Math.sqrt(x*y))(4,9) | ||
| + | distance = (x1,y1,x2,y2) -> Math.sqrt(Math.sqr(x1-x2)+Math.sqr(y1-y2)); | ||
| + | distance(1,1,2,2) | ||
| </code> | </code> | ||
| - | ===== Studiu de Caz: Dezvoltarea unui serviciu web folosind mediul de dezvoltare NetBeans 8.0.1 și serverul de aplicații GlassFish 4.1 ===== | + | O expresie literală este evaluată la textul expresiei, care are tipul ''String'', fiind utilizată atunci când este necesară folosirea sintaxei rezervate ''${}'' sau ''#{}''. Dacă se doreşte folosirea şirului de caractere ''${expression}'' se pot folosi alternativele ''${'${'}expression'' sau ''\${expression}'' (idem şi pentru expresii ''#{}''). O expresie literală nu foloseşte delimitatorii ''${}'' sau ''#{}''. |
| - | ==== Dezvoltarea serverului ==== | + | Expresiile literale pot fi cu evaluare imediată sau cu evaluare leneşă şi pot fi atât expresii de tip valoare cât şi expresii de tip metodă. Momentul la care este evaluată o expresie depinde de contextul în care aceasta este utilizată. |
| + | |||
| + | În EL sunt suportate operaţii pe colecţii cum ar fi: | ||
| + | * mulţimi <code> | ||
| + | {1, 2, ..., n} | ||
| + | </code> | ||
| + | * liste – acestea pot conţine elemente având tipuri diferite <code> | ||
| + | {1, two, "3", ...} | ||
| + | </code> | ||
| + | * obiecte de tip map <code> | ||
| + | {"one":1, "two":2, ..., "n":n} | ||
| + | </code> | ||
| - | Se creează un proiect de tip Java Web → Web Application. | + | Prin Expression Language, se permite crearea dinamică a acestora, exploatarea lor implicând utilizarea unor obiecte de tip flux, respectiv benzi de asamblare (//eng.// pipeline). Astfel, metodele vor fi apelate pe fluxul de elemente obţinut din colecţia respectivă folosind metoda ''stream()''. Întrucât unele metode întorc tot un flux de elemente, acestea pot fi înlănţuite împreună în cadrul unei benzi de asamblare . Operaţiile realizate pe fluxul de elemente nu modifică colecţia originală. |
| - | {{ :laboratoare:laborator06:netbeans01.png?nolink&600 }} | + | <note>Metoda ''stream()'' obţine un obiect ''Stream'' pornind de la un obiect ''java.util.Collection'' sau un vector Java.</note> |
| - | În situația în care Java Enterprise Edition nu este inițializată pentru NetBeans, această operație este realizată în acest moment, putând dura, după caz, o perioadă de timp mai mare. | + | <note>O bandă de asamblare constă dintr-o sursă (obiect de tip ''Stream''), orice număr de operaţii intermediare care întorc un flux (spre exemplu, ''filter()'' şi ''map()'') şi o operaţie terminală care nu întoarce un flux (spre exemplu, ''toList()'').</note> |
| - | {{ :laboratoare:laborator06:netbeans02.png?nolink&600 }} | + | <code java> |
| + | collection.stream().filter(a->a.attribute1=='value1') | ||
| + | .map(a->a.attribute2) | ||
| + | .sorted() | ||
| + | .toList() | ||
| + | </code> | ||
| - | Pentru aplicația web se precizează o denumire, precum și locația unde va fi amplasat proiectul corespunzător. | + | Operaţiile suportate de fluxul de elemente sunt: ''allMatch()'', ''anyMatch()'', ''average()'', ''count()'', ''distinct()'', ''filter()'', ''findFirst()'', ''flatMap()'', ''forEach()'', ''iterator()'', ''limit()'', ''map()'', ''max()'', ''min()'', ''noneMatch()'', ''peek()'', ''reduce()'', ''sorted()'', ''substream()'', ''sum()'', ''toArray()'', ''toList()''. |
| - | {{ :laboratoare:laborator06:netbeans03.png?nolink&600 }} | + | În afară de operatorii ''.'' şi ''[]'', Expression Language pune la dispoziţia programatorilor şi alţi operatori, ce pot fi folosiţi doar în expresii de tip rvalue: |
| - | Este indicat tipul de server de aplicații care va fi utilizat (GlassFish Server 4.1), versiunea Java Enterprise Edition (în cazul de față Java EE 7 Web), precum și contextul din care va putea fi accesat serviciul web (''/ReservationService''). | + | ^ Categorie Operator ^ Operator ^ Precedenţă ^ Observaţii ^ |
| + | | | ''.'' ''[]'' | 1 | | | ||
| + | | | ''()'' | | folosit pentru a schimba precedenţa operatorilor | | ||
| + | | aritmetici | ''-'' (unar) | 2 | | | ||
| + | | logici | ''not'' ''!'' | 2 | | | ||
| + | | empty | ''empty'' | 2 | utilizat pentru a verifica dacă o valoare este ''null'' sau vidă | | ||
| + | | aritmetici | ''*'' ''/'' ''div'' ''%'' ''mod'' | 3 | | | ||
| + | | ::: | ''+'' ''-'' (binar) | 4 | | | ||
| + | | concatenare şiruri de caractere | ''+='' | 5 | | | ||
| + | | relaţionali | ''%%<>%%'' ''%%<%%'' ''%%<=%%'' ''%%>%%'' ''%%>=%%'' ''lt'' ''le'' ''gt'' ''ge'' | 6 | comparaţia se poate face cu alte valori sau literali | | ||
| + | | ::: | ''=='' ''!='' ''eq'' ''ne'' | 7 | | | ||
| + | | logici | ''&&'' ''and'' | 8 | | | ||
| + | | ::: | ''||'' ''or'' | 9 | | | ||
| + | | condiţionali | ''?'' '':'' | 10 | ''X ? Y : Z'' | | ||
| + | | lambda | ''->'' | 11 | | | ||
| + | | atribuire | ''='' | 12 | | | ||
| + | | | '';'' | 13 | | | ||
| - | {{ :laboratoare:laborator06:netbeans04.png?nolink&600 }} | + | În Expression Language există şi termeni rezervaţi, care nu pot fi utilizaţi ca identificatori: ''and'', ''or'', ''not'', ''eq'', ''ne'', ''lt'', ''gt'', ''le'', ''ge'', ''true'', ''false'', ''null'', ''instanceof'', ''empty'', ''div'', ''mod''. |
| - | Pot fi specificate și alte tehnologii cu care să fie integrat serviciul web (Spring Web MVC, Java Server Faces, Struts, Hibernate). | + | Există posibilitatea ca expresiile EL să nu fie evaluate în cazul în care atributul ''isELIgnored'' al directivei ''page'' are valoarea ''true'' (implicit, valoarea sa este ''false'', deci în mod obişnuit, expresiile EL vor fi evaluate într-o pagină JSP). |
| - | {{ :laboratoare:laborator06:netbeans05.png?nolink&600 }} | + | ===== Utilizarea JSTL (JavaServer Pages Standard Tag Library) pentru implementarea unor funcţionalităţi complexe ===== |
| - | Proiectul va conține o resursă de tip //Web Service...//, accesibilă din meniul contextual prin selectarea opțiunii //New//. | + | JSTL (JavaServer Pages Standard Tag Library) este o colecţie de etichete JSP, care implementează funcţionalitatea de bază specifică pentru numeroase aplicaţii JSP. |
| - | {{ :laboratoare:laborator06:netbeans06.png?nolink }} | + | Etichetele JSTL pot fi clasificate, în funcţie de comportamentul pe care îl oferă utilizatorilor în mai multe grupuri: |
| + | - etichete JSTL de bază; | ||
| + | - etichete JSTL pentru formatare; | ||
| + | - etichete JSTL destinate gestiunii informaţiilor dintr-o bază de date SQL; | ||
| + | - etichete JSTL pentru gestiunea documentelor XML; | ||
| + | - funcţii JSTL. | ||
| - | Pentru serviciul web trebuie completate atribute precum: | + | Pentru ca aceste funcţionalităţi să fie accesibile în pagina JSP a unei aplicaţii web, biblioteca JSTL trebuie plasată în directorul ''WEB-INF\lib'' corespunzător acesteia. |
| - | * denumirea; | + | |
| - | * proiectul din care face parte; | + | |
| - | * localizarea; | + | |
| - | * pachetul în care este inclus codul sursă corespunzător implementării; | + | |
| - | * modul de creare al serviciului web: | + | |
| - | * de la zero; | + | |
| - | * pornind de la o componentă de tip Session Bean (pentru care se indică locația); | + | |
| - | * posibilitatea de a implementa un comportament de componentă Java Beans de tip sesiune fără stare. | + | |
| - | {{ :laboratoare:laborator06:netbeans07.png?nolink&600 }} | + | ==== Etichete JSTL de bază ==== |
| - | După implementarea funcţionalităţii puse la dispoziţie, aceasta poate fi vizualizată din modul //Design//. | + | **Etichetele JSTL de bază** sunt cele mai frecvent utilizate, implementând funcţionalitate legată de controlul fluxului. |
| - | Sunt indicate aici numele şi tipul parametrilor acceptaţi de metodele serviciului web, tipul rezultatului întors, excepţiile care pot fi generate precum şi o descriere a funcţionalităţii respective. | + | Pentru a putea referi aceste etichete, trebuie specificată locaţia de unde acestea pot fi încărcate. |
| - | Modulul permite gestiunea operațiilor pe care serviciul web le pune la dispoziția utilizatorilor (adăugare, modificare, ștergere) precum și controlul unor atribute ce țin de calitatea serviciului: | + | <code java> |
| - | * optimizarea transferului datelor binare; | + | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> |
| - | * fiabilitatea transmiterii mesajelor; | + | </code> |
| - | * securitate. | + | |
| - | {{ :laboratoare:laborator06:netbeans08.png?nolink&800 }} | + | Cele mai frecvent utilizate etichete JSTL de bază sunt: |
| - | În momentul în care este lansat în execuţie serviciul web (opţiunea //Deploy// din meniul contextual corespunzător proiectului), este pornit şi serverul de aplicaţii GlassFish. | + | | ''<c:out>'' | evaluează valoarea unei expresii pe care o afişează\\ Atributele asociate etichetei sunt:\\ • ''value'' (obligatoriu) – informaţia care trebuie evaluată;\\ • ''default'' – informaţie asociată în cazul în care evaluarea eşuează;\\ • ''escapeXml'' – utilizată pentru a ignora caractere XML speciale. <code java> |
| + | <c:out value="${myObject.myAttribute}" /> | ||
| + | </code> | | ||
| + | | ''<c:set>'' | asociază rezultatul evaluării unei expresii la o variabilă, disponibilă pentru un anumit domeniu de vizibilitate.\\ \\ Atributele asociate etichetei sunt:\\ • ''value'' – informaţia care trebuie evaluată şi asociată obiectului;\\ • ''target'' – denumirea obiectului a cărui proprietate trebuie stabilită;\\ • ''property'' – proprietate a obiectului ''target'' a cărui valoare va fi stabilită la valoarea indicată (trebuie specificat dacă se foloseşte ''target'');\\ • ''var'' – denumirea variabilei care va stoca informaţia;\\ • ''scope'' – scopul variabilei care va stoca informaţia. <code java> | ||
| + | <c:set value="${expression}" target="myObject" property="myAttribute" scope="page" /> | ||
| + | <c:set value="${expression}" var="myVariabile" scope="application" /> | ||
| + | </code> | | ||
| + | | ''<c:remove>'' | disociază o variabilă de contextul unui anumit domeniu de vizibilitate\\ \\ Atributele asociate etichetei sunt:\\ • ''var'' (obligatoriu) – denumirea variabilei care va fi eliminată;\\ • ''scope'' – scopul variabilei care va fi eliminată. <code java> | ||
| + | <c:remove var="myVariable" scope="application" /> | ||
| + | </code> | | ||
| + | | ''<c:catch>'' | gestionează orice obiect de tip ''Throwable'' întâlnit în corpul său, eventual expunându-l utilizatorului\\ \\ Atributul asociat etichetei este ''var'' ce indică denumirea variabilei care va stoca excepţia generată, în cazul în care va fi produsă de instrucţiunile din corpul său <code java> | ||
| + | <c:catch var="${exception}"> | ||
| + | <% some expression(s) that may potentially throw an error %> | ||
| + | </c:catch> | ||
| + | <c:out value="exception: ${exception.message}" /> | ||
| + | </code> | | ||
| + | | ''<c:if>'' | etichetă de tip condiţional, al cărui corp este evaluat în cazul când condiţia asociată este îndeplinită\\ \\ Atributele asociate etichetei sunt:\\ • ''test'' (obligatoriu) – condiţia care se doreşte a fi evaluată;\\ • ''var'' – denumirea variabilei care va stoca rezultatul condiţiei;\\ • ''scope'' – scopul variabilei care va stoca rezultatul condiţiei. <code java> | ||
| + | <c:if test="${expression}" /> | ||
| + | <% do some operations %> | ||
| + | </c:if> | ||
| + | </code> | | ||
| + | | ''<c:choose>'' | etichetă de tip condiţional, indicând condiţii ce se exclud mutual, specificate prin ''<when>'' şi ''<otherwise>''; funcţionează ca instrucţiunea ''switch'' din Java, permiţând alegerea dintre mai multe alternative: ramurile case sunt specificate prin ''<when>'' în timp ce ramura default este specificată prin ''<otherwise>''.\\ \\ Eticheta nu are atribute. <code java> | ||
| + | <c:choose> | ||
| + | <c:when test="${expression1}"><% do some operations %></c:when> | ||
| + | <c:when test="${expression2}"><% do some operations %></c:when> | ||
| + | ... | ||
| + | <c:when test="${expressionn}"> | ||
| + | <% do some operations %> | ||
| + | </c:when> | ||
| + | <c:otherwise><% do some other operations %></c:otherwise> | ||
| + | </c:choose /> | ||
| + | </code> | | ||
| + | | ''<c:when>'' | subetichetă a ''<choose>'', al cărui corp este evaluat în cazul când condiţia asociată este îndeplinită\\ Atributul asociat etichetei este test ce indică condiţia care se doreşte a fi evaluată. | | ||
| + | | ''<c:otherwise>'' | subetichetă a ''<choose>'', ce urmează uneia sau mai multor etichete ''<when>'', determinând evaluarea corpului său, dacă nici una dintre condiţiile care o preced nu este îndeplinită.\\ \\ Eticheta nu are atribute. | | ||
| + | | ''<c:import>'' | primeşte un URL relativ sau absolut şi expune conţinutul său întregii pagini, unui şir de caractere specificat în atributul var sau unui obiect Reader specificat în atributul ''varReader''.\\ Atributele asociate etichetei sunt:\\ • ''url'' (obligatoriu) – URL-ul ce trebuie obţinut şi inclus în pagină;\\ • ''context'' – caracterul / urmat de numele aplicaţiei web;\\ • ''charEncoding'' – setul de caractere utilizat pentru datele preluate;\\ • ''var'' – denumirea variabilei utilizată pentru a stoca textul preluat;\\ • ''scope'' – domeniul de vizibilitate al variabilei utilizată pentru a stoca textul preluat;\\ • ''varReader'' – denumirea unei variabile alternative pentru a expune conţinutul sub forma unui obiect ''java.io.Reader''; <code java> | ||
| + | <c:import var="myVariabile" url="http://www.mysite.com" /> | ||
| + | </code> | | ||
| + | | ''<c:forEach>'' | etichetă de tip iteraţie, acceptând mai multe tipuri de colecţii, suportând parcurgerea submulţimilor; este o alternativă pentru instrucţiunile de iterare ''for'', ''while'' şi ''do-while'' din cadrul Java, care pot fi utilizate în cadrul unui scriplet\\ \\ Atributele asociate etichetei sunt:\\ • ''items'' – informaţia (colecţia) pe care se realizează iteraţia;\\ • ''begin'' – elementul colecţiei de la care se începe iteraţia;\\ • ''end'' – elementul colecţiei la care se termină iteraţia;\\ • ''step'' – pasul cu care se parcurg elementele colecţiei;\\ • ''var'' – denumirea variabilei care expune elementul curent;\\ • ''varStatus'' – denumirea variabilei care expune statutul iteraţiei; <code java> | ||
| + | <c:forEach var="myVariabile" items="${myCollection}"> | ||
| + | <c:out value="${myVariabile}" /><br /> | ||
| + | </c:forEach> | ||
| + | </code> | | ||
| + | | ''<c:forTokens>'' | iterează asupra unor particule, separate prin delimitatori\\ \\ Suportă aceleaşi atribute ca şi <foreach>, la care se adaugă delim, care indică caracterele utilizate ca delimitatori <code java> | ||
| + | <c:forTokens var="myVariabile" items="${myString}" delim=","> | ||
| + | <c:out value="${myVariabile}" /><br /> | ||
| + | </c:forTokens> | ||
| + | </code> | | ||
| + | | ''<c:param>'' | adaugă un parametru la URL-ul specificat în cadrul unei etichete ''<import>'', realizând şi codificarea acestuia\\ \\ Atributele asociate etichetei sunt:\\ • ''name'' – denumirea parametrului care va fi inclus în URL;\\ • ''value'' – valoarea parametrului care va fi inclus în URL; <code java> | ||
| + | <c:import var="myVariabile" url="http://www.mysite.com"> | ||
| + | <c:param name="param1Name" value="param1Value" /> | ||
| + | <c:param name="param2Name" value="param2Value" /> | ||
| + | ... | ||
| + | <c:param name="paramnName" value="paramnValue" /> | ||
| + | </c:import> | ||
| + | </code> | | ||
| + | | ''<c:redirect>'' | redirectează controlul la un alt URL, realizând suprascrierea sa în browser; suportă URL-uri relative la context şi eticheta ''<param>''\\ \\ Atributele asociate etichetei sunt:\\ • ''url'' (obligatoriu) – URL-ul la care se realizează redirectarea controlului;\\ • ''context'' – caracterul / urmat de numele aplicaţiei web. <code java> | ||
| + | <c:redirect url="http://www.mysite.com"> | ||
| + | </code> | | ||
| + | | ''<c:url>'' | creează un URL cu parametrii de interogare opţionali, stocând valoarea acestuia într-o variabilă şi realizând rescrierea URL-ului dacă este necesar; este o alternativă la invocarea metodei ''response.encodeURL()'', suportând şi eticheta ''<param>''\\ \\ Atributele asociate etichetei sunt:\\ • ''value'' (obligatoriu) – URL-ul de bază;\\ • ''context'' – caracterul / urmat de numele aplicaţiei web;\\ • ''var'' – denumirea variabilei ce reţine URL-ul procesat;\\ • ''scope'' – domeniul de vizibilitate al variabilei ce reţine URL-ul procesat; <code java> | ||
| + | <c:url value="http://www.mysite.com" /> | ||
| + | </code> | | ||
| - | Ulterior, modificările asupra codului sursă sunt reflectate la nivelul serverului de aplicaţii în mod automat atunci când acesta este salvat (codul sursă este compilat, iar clasele sunt plasate în contextul serverului GlassFish). | + | ==== Etichete JSTL pentru formatare ==== |
| - | {{ :laboratoare:laborator06:netbeans09.png?nolink }} | + | Etichetele JSTL pentru formatare sunt utilizate pentru a formata şi afişa text, informaţii cu privire la dată calendaristică şi timp, numere precum şi site-uri Internet într-un format localizat. |
| - | Accesând consola serverului de aplicaţii GlassFish (la adresa [[http://localhost:4848|]]), poate fi vizualizat serviciul web dezvoltat în secţiunea //Applications// sub denumirea care a fost indicată la crearea lui. | + | Pentru a putea referi aceste etichete, trebuie specificată locaţia de unde acestea pot fi încărcate. |
| - | <note tip>Datele de autentificare pot fi preluate din mediul de dezvoltare NetBeans, accesând //Tools// → //Servers// → //Glassfish Server 4.1// (tab-ul //Common//). De regulă, utilizatorul care deţine toate drepturile este ''admin'', iar parola asociată acestuia este vidă.</note> | + | <code java> |
| + | <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> | ||
| + | </code> | ||
| - | {{ :laboratoare:laborator06:glassfish.png?nolink&800 }} | + | Cele mai frecvent utilizate etichete JSTL pentru formatare sunt: |
| - | Legătura //ViewEndpoint// corespunzătoare componentei serviciului web trimite către fişierul WSDL care conţine descrierea serviciului web (la adresa [[http://localhost:8080/ReservationService/Reservation?wsdl|]]), permiţând şi testarea funcţionalităţii acestuia. | + | | ''<fmt:formatNumber>'' | utilizat pentru redarea unei valori numerice cu o anumită precizie sau format\\ \\ Atributele asociate etichetei sunt:\\ • ''value'' (obligatoriu) – valoarea numerică ce se doreşte afişată;\\ • ''type'' – poate lua valorile ''NUMBER'', ''CURRENCY'', ''PERCENT'';\\ • ''pattern'' – modelul de formatare pentru valoarea numerică ce se doreşte afişată; se folosesc codurile:\\ o ''0'' – reprezintă o cifră;\\ o ''E'' – reprezintă o formă exponenţială;\\ o ''#'' – reprezintă o cifră; se afişează 0 dacă lipseşte;\\ o ''.'' – separator pentru valorile zecimale;\\ o '','' – separator pentru grupurile reprezentând miile;\\ o '';'' – separator pentru formate;\\ o ''-'' – prefix pentru valori negative;\\ o ''%'' – afişează procentajul;\\ o ''?'' – afişează miimile;\\ o ''*'' – înlocuit de simbolul valutei curente;\\ o ''X'' – indică faptul că orice alt caracter poate fi folosit ca prefix sau sufix;\\ o ''''' – utilizat pentru a cita caractere speciale în prefix sau sufix.\\ • ''currencyCode'' – codul valutei (pentru tipul ''CURRENCY''), preluat din localizarea curentă;\\ • ''currencySymbol'' – simbolul valutei (pentru tipul ''CURRENCY''), preluat din localizarea curentă;\\ • ''groupingUsed'' – dacă se folosesc grupuri de numere; se foloseşte pentru a introduce '','' între grupurile care reprezintă miile;\\ • ''maxIntegerDigits'' – numărul maxim de cifre întregi care pot fi afişate; dacă valoarea este depăşită, atunci rezultatul se trunchează;\\ • ''minIntegerDigits'' – numărul minim de cifre întregi care pot fi afişate;\\ • ''maxFractionDigits'' – numărul maxim de zecimale care pot fi afişate; dacă valoarea este depăşită, atunci rezultatul se rotunjeşte;\\ • ''minFractionDigits'' – numărul minim de zecimale care pot fi afişate;\\ • ''var'' – denumirea variabilei care reţine valoarea formatată;\\ • ''scope'' – domeniul de vizibilitate al variabilei care reţine valoarea formatată. | |
| + | | ''<fmt:parseNumber>'' | parsează reprezentarea sub formă de şir de caractere pentru o valoare numerică, o valută sau un procentaj\\ \\ Atributele asociate etichetei sunt:\\ • ''value'' – valoarea numerică ce se doreşte a fi parsată;\\ • ''type'' – poate lua valorile NUMBER, CURRENCY, PERCENT;\\ • ''parseLocale'' – localizarea folosită la parsarea numărului;\\ • ''integerOnly'' – indică parsarea de valori întregi sau reale;\\ • ''pattern'' – modelul de parsare;\\ • ''timeZone'' – zona de timp a datei calendaristice parsate;\\ • ''var'' – denumirea variabilei care reţine valoarea parsată;\\ • ''scope'' – domeniul de vizibilitate al variabilei care reţine valoarea parsată. | | ||
| + | | ''<fmt:formatDate>'' | utilizat pentru formatarea unei date calendaristice / timp folosind stilurile şi modelele oferite\\ \\ Atributele asociate etichetei sunt:\\ • ''value'' (obligatoriu) – data calendaristică de afişat;\\ • ''type'' – poate lua valorile ''DATE'', ''TIME'', ''BOTH'';\\ • ''dateSytle'' – poate lua valorile ''FULL'', ''LONG'', ''MEDIUM'', ''SHORT'', ''DEFAULT'';\\ • ''timeStyle'' – poate lua valorile ''FULL'', ''LONG'', ''MEDIUM'', ''SHORT'', ''DEFAULT'';\\ • ''pattern'' – modelul de formatare pentru valoarea de tip dată calendaristică / timp ce se doreşte afişată; se folosesc codurile:\\ o ''G'' – era;\\ o ''y'' – anul;\\ o ''M'' – luna;\\ o ''d'' – ziua din lună;\\ o ''h'' – ora (format 12 ore);\\ o ''H'' – ora (format 24 ore);\\ o ''m'' – minutul;\\ o ''s'' – secunda;\\ o ''S'' – milisecunda;\\ o ''E'' – ziua din săptămână;\\ o ''D'' – ziua din an;\\ o ''F'' – ziua din săptămână în cadrul lunii;\\ o ''w'' – săptămâna din an;\\ o ''W'' – săptămâna din lună;\\ o ''a'' – indicatorul AM / PM;\\ o ''k'' – ora (format 12 ore);\\ o ''K'' – ora (format 24 ore);\\ o ''z'' – zona de timp;\\ o ''''' – caracter escape pentru informaţii de tip text;\\ o ''"'' – utilizat pentru citări;\\ • ''timeZone'' – zona de timp a datei calendaristice afişate;\\ • ''var'' – denumirea variabilei care reţine valoarea formatată;\\ • ''scope'' – domeniul de vizibilitate al variabilei care reţine valoarea formatată. | | ||
| + | | ''<fmt:parseDate>'' | parsează reprezentarea sub formă de şir de caractere pentru o valoare de tip dată calendaristică / timp\\ \\ Are aceleaşi atribute ca ''<formatDate>'' la care se adaugă ''parseLocale'', indicând localizarea care trebuie utilizată atunci când se parsează informaţia de tip dată calendaristică. | | ||
| + | | ''<fmt:bundle>'' | încarcă o resursă ce urmează să fie utilizată în corpul său, de eticheta ''<message>''\\ \\ Atributele asociate etichetei sunt:\\ • ''basename'' (obligatoriu) – specifică numele de bază pentru resursa care se doreşte a fi încărcată;\\ • ''prefix'' – valoarea care va preceda fiecare denumire de cheie în subeticheta ''<message>''. <code java> | ||
| + | <fmt:bundle basename="myBaseName"> | ||
| + | <fmt:message key="myPrefix.myKey" /> | ||
| + | </fmt:bundle> | ||
| + | echivalent cu | ||
| + | <fmt:bundle basename="myBaseName" prefix="myPrefix"> | ||
| + | <fmt:message key="myKey" /> | ||
| + | </fmt:bundle> | ||
| + | </code> | | ||
| + | | ''<fmt:setLocale>'' | stochează localizarea dată în variabila de configurare referitoare la localizare\\ \\ Atributele asociate etichetei sunt:\\ • ''value'' (obligatoriu) – specifică un cod format din două părţi indicând codul de limbă (ISO-639) şi codul de ţară (ISO-3166);\\ • ''variant'' – variantă specifică browser-ului;\\ • ''scope'' – domeniul de vizibilitate al variabilei de configurare referitoare la localizare. | | ||
| + | | ''<fmt:setBundle>'' | încarcă o resursă pe care o stochează într-o variabilă având un domeniu de vizibilitate, respectiv în variabila de configurare referitoare la resurse\\ \\ Atributele asociate etichetei sunt:\\ • ''basename'' (obligatoriu) – specifică numele de bază pentru familia de resurse pentru a fi expusă ca o variabilă având un anumit domeniu de vizibilitate, respectiv ca o variabilă de configurare;\\ • ''var'' – denumirea variabilei care reţine valoarea resursei;\\ • ''scope'' – domeniul de vizibilitate al variabilei care reţine valoarea resursei. | | ||
| + | | ''<fmt:timeZone>'' | specifică zona de timp pentru orice tip de acţiune vizând formatarea sau parsarea din corpul său.\\ \\ Atributul asociat etichetei este value ce indică zona de timp care va fi aplicată corpului său. | | ||
| + | | ''<fmt:setTimeZone>'' | stochează zona de timp dată în variabila de configurare referitoare la zona de timp\\ \\ Atributele asociate etichetei sunt:\\ • ''value'' (obligatoriu) – zona de timp care va fi expusă ca o variabilă având un anumit domeniu de vizibilitate, respectiv ca o variabilă de configurare;\\ • ''var'' – denumirea variabilei care reţine zona de timp;\\ • ''scope'' – domeniul de vizibilitate al variabilei care reţine zona de timp. | | ||
| + | | ''<fmt:message>'' | afişează un mesaj folosind un format localizat\\ \\ Atributele asociate etichetei sunt:\\ • ''key'' – cheia mesajului care se doreşte a fi obţinut;\\ • ''bundle'' – identificatorul resursei care se doreşte a fi folosit;\\ • ''var'' – denumirea variabilei care reţine valoarea mesajului localizat;\\ • ''scope'' – domeniul de vizibilitate al variabilei care reţine valoarea mesajului localizat. | | ||
| + | | ''<fmt:requestEncoding>'' | stabileşte mecanismul de configurare al caracterelor pentru cerere\\ Atributul asociat etichetei este ''key'' prin care se indică mecanismul de configurare al caracterelor care va fi aplicat la decodificarea parametrilor din obiectul ''request''. | | ||
| - | <note tip>În situația în care operațiile furnizate de serviciul web implică transmiterea (ca parametrii sau ca valori întoarse a metodelor) de obiecte, testarea funcționalității nu este relevantă, întrucât implică transferul de adrese (referințe) a căror valabilitate este restrânsă la nivelul serverului de aplicații, fără a putea fi vizualizat conținutul propriu-zis al acestora.</note> | + | ==== Etichete JSTL pentru gestiunea informațiilor dintr-o bază de date ==== |
| - | <file xml Reservation.xml> | + | Etichetele JSTL pentru gestiunea informaţiilor într-o bază de date SQL oferă funcţionalitatea pentru interacţiunea cu baze de date relaţionale ca Oracle, MySQL sau Microsoft SQL Server. |
| - | <?xml version="1.0" encoding="UTF-8"?> | + | |
| - | <!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is Metro/2.3.1-b419 (branches/2.3.1.x-7937; 2014-08-04T08:11:03+0000) JAXWS-RI/2.2.10-b140803.1500 JAXWS-API/2.2.11 JAXB-RI/2.2.10-b140802.1033 JAXB-API/2.2.12-b140109.1041 svn-revision#unknown. --> | + | Pentru a putea referi aceste etichete, trebuie specificată locaţia de unde acestea pot fi încărcate. |
| - | <!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is Metro/2.3.1-b419 (branches/2.3.1.x-7937; 2014-08-04T08:11:03+0000) JAXWS-RI/2.2.10-b140803.1500 JAXWS-API/2.2.11 JAXB-RI/2.2.10-b140802.1033 JAXB-API/2.2.12-b140109.1041 svn-revision#unknown. --> | + | |
| - | <definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy" xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://reservation.lab06.aipi.cs.pub.ro/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://reservation.lab06.aipi.cs.pub.ro/" name="Reservation"> | + | |
| - | <types> | + | |
| - | <xsd:schema> | + | |
| - | <xsd:import namespace="http://reservation.lab06.aipi.cs.pub.ro/" schemaLocation="http://andrei-pc:8080/ReservationService/Reservation?xsd=1"/> | + | |
| - | </xsd:schema> | + | |
| - | </types> | + | |
| - | <message name="getAvailableSeats"> | + | |
| - | <part name="parameters" element="tns:getAvailableSeats"/> | + | |
| - | </message> | + | |
| - | <message name="getAvailableSeatsResponse"> | + | |
| - | <part name="parameters" element="tns:getAvailableSeatsResponse"/> | + | |
| - | </message> | + | |
| - | <message name="cancelReservation"> | + | |
| - | <part name="parameters" element="tns:cancelReservation"/> | + | |
| - | </message> | + | |
| - | <message name="cancelReservationResponse"> | + | |
| - | <part name="parameters" element="tns:cancelReservationResponse"/> | + | |
| - | </message> | + | |
| - | <message name="getTimeTable"> | + | |
| - | <part name="parameters" element="tns:getTimeTable"/> | + | |
| - | </message> | + | |
| - | <message name="getTimeTableResponse"> | + | |
| - | <part name="parameters" element="tns:getTimeTableResponse"/> | + | |
| - | </message> | + | |
| - | <message name="makeReservation"> | + | |
| - | <part name="parameters" element="tns:makeReservation"/> | + | |
| - | </message> | + | |
| - | <message name="makeReservationResponse"> | + | |
| - | <part name="parameters" element="tns:makeReservationResponse"/> | + | |
| - | </message> | + | |
| - | <message name="getReservations"> | + | |
| - | <part name="parameters" element="tns:getReservations"/> | + | |
| - | </message> | + | |
| - | <message name="getReservationsResponse"> | + | |
| - | <part name="parameters" element="tns:getReservationsResponse"/> | + | |
| - | </message> | + | |
| - | <portType name="Reservation"> | + | |
| - | <operation name="getAvailableSeats"> | + | |
| - | <input wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/getAvailableSeatsRequest" message="tns:getAvailableSeats"/> | + | |
| - | <output wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/getAvailableSeatsResponse" message="tns:getAvailableSeatsResponse"/> | + | |
| - | </operation> | + | |
| - | <operation name="cancelReservation"> | + | |
| - | <input wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/cancelReservationRequest" message="tns:cancelReservation"/> | + | |
| - | <output wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/cancelReservationResponse" message="tns:cancelReservationResponse"/> | + | |
| - | </operation> | + | |
| - | <operation name="getTimeTable"> | + | |
| - | <input wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/getTimeTableRequest" message="tns:getTimeTable"/> | + | |
| - | <output wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/getTimeTableResponse" message="tns:getTimeTableResponse"/> | + | |
| - | </operation> | + | |
| - | <operation name="makeReservation"> | + | |
| - | <input wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/makeReservationRequest" message="tns:makeReservation"/> | + | |
| - | <output wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/makeReservationResponse" message="tns:makeReservationResponse"/> | + | |
| - | </operation> | + | |
| - | <operation name="getReservations"> | + | |
| - | <input wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/getReservationsRequest" message="tns:getReservations"/> | + | |
| - | <output wsam:Action="http://reservation.lab06.aipi.cs.pub.ro/Reservation/getReservationsResponse" message="tns:getReservationsResponse"/> | + | |
| - | </operation> | + | |
| - | </portType> | + | |
| - | <binding name="ReservationPortBinding" type="tns:Reservation"> | + | |
| - | <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> | + | |
| - | <operation name="getAvailableSeats"> | + | |
| - | <soap:operation soapAction=""/> | + | |
| - | <input> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </input> | + | |
| - | <output> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </output> | + | |
| - | </operation> | + | |
| - | <operation name="cancelReservation"> | + | |
| - | <soap:operation soapAction=""/> | + | |
| - | <input> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </input> | + | |
| - | <output> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </output> | + | |
| - | </operation> | + | |
| - | <operation name="getTimeTable"> | + | |
| - | <soap:operation soapAction=""/> | + | |
| - | <input> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </input> | + | |
| - | <output> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </output> | + | |
| - | </operation> | + | |
| - | <operation name="makeReservation"> | + | |
| - | <soap:operation soapAction=""/> | + | |
| - | <input> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </input> | + | |
| - | <output> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </output> | + | |
| - | </operation> | + | |
| - | <operation name="getReservations"> | + | |
| - | <soap:operation soapAction=""/> | + | |
| - | <input> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </input> | + | |
| - | <output> | + | |
| - | <soap:body use="literal"/> | + | |
| - | </output> | + | |
| - | </operation> | + | |
| - | </binding> | + | |
| - | <service name="Reservation"> | + | |
| - | <port name="ReservationPort" binding="tns:ReservationPortBinding"> | + | |
| - | <soap:address location="http://andrei-pc:8080/ReservationService/Reservation"/> | + | |
| - | </port> | + | |
| - | </service> | + | |
| - | </definitions> | + | |
| - | </file> | + | |
| - | ==== Dezvoltarea clientului ==== | + | <code java> |
| + | <%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %> | ||
| + | </code> | ||
| - | Se creează un proiect de tip //Java Desktop Application// care va conține un client al unui serviciu web (//New// → //Web Service Client// din meniul contextual). | + | Cele mai frecvent utilizate etichete JSTL pentru gestiunea informaţiilor dintr-o bază de date sunt: |
| - | {{ :laboratoare:laborator06:netbeans10.png?nolink }} | + | | ''<sql:setDataSource>'' | creează un obiect ''DataSource'' adecvat numai operaţiilor de prototipare\\ \\ Atributele asociate etichetei sunt:\\ • ''driver'' – numele clasei corespunzătoare "driver"-ului JDBC care trebuie înregistrată;\\ • ''url'' – URL-ul pentru realizarea conexiunii la baza de date;\\ • ''user'' – numele de utilizator folosit în mecanismul de autentificare pentru baza de date;\\ • ''password'' – parola folosită în mecanismul de autentificare pentru baza de date;\\ • ''dataSource'' – baza de date pregătită anterior;\\ • ''var'' – denumirea variabilei care va reprezenta baza de date;\\ • ''scope'' – domeniul de vizibilitate al variabile care va reprezenta baza de date. <code java> |
| + | <sql:setDataSource var="connection" url="${dataBaseConnection}" | ||
| + | user="${dataBaseUser}" password="${dataBasePassword}" /> | ||
| + | </code> | | ||
| + | | ''<sql:query>'' | execută interogarea SQL de tip ''SELECT'' definită în cadrul corpului folosind atributul sql, reţinând rezultatul într-o variabilă având un anumit domeniu de vizibilitate\\ \\ Atributele asociate etichetei sunt:\\ • ''sql'' – comanda SQL care va fi executată (ar trebui să întoarcă un obiect de tip ''ResultSet'');\\ • ''dataSource'' – conexiunea la baza de date care va fi utilizată (suprascrie valoarea implicită);\\ • ''maxRows'' – numărul maxim de rezultate care vor fi stocate în cadrul variabilei;\\ • ''startRow'' – numărul înregistrării (din cadrul rezultatului) de la care va începe stocarea;\\ • ''var'' – denumirea variabilei care va reține rezultatul;\\ • ''scope'' – domeniul de vizibilitate al variabilei care va reține rezultatul. <code java> | ||
| + | <sql:query sql="${myQuery}" var="result" /> | ||
| + | </code> | | ||
| + | | ''<sql:update>'' | execută instrucţiunea SQL de actualizare a informaţiilor (de tip ''INSERT'', ''UPDATE'', ''DELETE'') – care nu întoarce date, definită în cadrul corpului folosind atributul sql\\ \\ Atributele asociate etichetei sunt:\\ • ''sql'' – comanda SQL care va fi executată (ar trebui să NU întoarcă un obiect de tip ''ResultSet'');\\ • ''dataSource'' – conexiunea la baza de date care va fi utilizată (suprascrie valoarea implicită);\\ • ''var'' – denumirea variabilei care va stoca numărul de înregistrări afectate de instrucţiune;\\ • ''scope'' – domeniul de vizibilitate al variabilei care va stoca numărul de înregistrări afectate de instrucţiune. <code java> | ||
| + | <sql:update dataSource="${connection}" var="count"> | ||
| + | <%-- some INSERT, UPDATE or DELETE query --> | ||
| + | </sql:update> | ||
| + | </code> | | ||
| + | | ''<sql:param>'' | stabileşte valoarea unui parametru al unei instrucţiuni SQL, fiind folosit de obicei împreună cu etichetele ''<query>'' sau ''<update>''\\ \\ Atributul asociat etichetei este value prin care se indică valoarea care se doreşte a fi asociată parametrului. <code java> | ||
| + | <sql:query dataSource="${connection}" var="result"> | ||
| + | SELECT FROM table WHERE attribute = ? | ||
| + | <sql:param value="${missingTableAttributeValue}" /> | ||
| + | </sql:query> | ||
| + | </code> <code java> | ||
| + | <sql:update dataSource="${connection}" var="count"> | ||
| + | <%-- some INSERT, UPDATE or DELETE query with one or more | ||
| + | missing attribute values --> | ||
| + | <sql:param value="${missingTableAttributeValue}" /> | ||
| + | </sql:update> | ||
| + | </code> | | ||
| + | | ''<sql:dateParam>'' | stabileşte valoarea unui parametru al unei instrucţiuni SQL având tipul ''java.util.Date''\\ \\ Atributele asociate etichetei sunt:\\ • ''value'' – valoarea parametrului având tipul ''java.util.Date'', care trebuie stocat;\\ • ''type'' – poate avea valorile ''DATE'' (doar date caledaristice), ''TIME'' (doar timp) sau ''TIMESTAMP'' (dată calendaristică şi timp).\\ Utilizarea sa este similară cu a etichete ''<param>''. | | ||
| + | | ''<sql:transaction>'' | oferă elemente care realizează acţiuni folosind un obiect ''Connection'' partajat, executate în cadrul unei tranzacţii; grupează interogări exprimate de etichetele ''<query>'' şi ''<update>'' într-o tranzacţie, asigurând că efectul acestora este fie unitar asupra bazei de date, menţinându-se starea sa iniţială în cazul producerii unei erori.\\ \\ Atributele asociate etichetei sunt:\\ • ''dataSource'' – conexiunea la baza de date care va fi utilizată (suprascrie valoarea implicită);\\ • ''isolation'' – poate avea valorile ''READ_COMMITED'', ''READ_UNCOMMMITTED'', ''REPEATABLE_READ'' sau ''SERIALIZABLE''. <code java> | ||
| + | <sql:transaction dataSource="${connection}"> | ||
| + | <sql:update var="count1"> | ||
| + | <%-- some INSERT queries --> | ||
| + | </sql:update> | ||
| + | <sql:update var="count2"> | ||
| + | <%-- some UPDATE queries --> | ||
| + | </sql:update> | ||
| + | <sql:update var="count3"> | ||
| + | <%-- some DELETE queries --> | ||
| + | </sql:update> | ||
| + | </sql:transaction> | ||
| + | </code> | | ||
| - | Se indică locația (URL-ul) la care se găsește specificația WSDL a serviciului web ([[http://localhost:8080/ReservationService/Reservation?wsdl|]]), pe baza căreia vor fi generate clasele care descriu operațiile ce pot fi invocate. | + | ==== Etichete JSTL pentru gestiunea documentelor XML ==== |
| - | {{ :laboratoare:laborator06:netbeans11.png?nolink&600 }} | + | Etichetele JSTL pentru gestiunea documentelor XML oferă posibilitatea de a manipula acest tip de resurse, implementând operaţii precum parsarea şi transformarea acestora precum şi controlul fluxului bazat pe expresii XPath. |
| - | Clasele generate sunt vizibile în secțiunea //Generated Sources (jax-ws)//. | + | Pentru a putea referi aceste etichete, trebuie specificată locaţia de unde acestea pot fi încărcate. |
| - | {{ :laboratoare:laborator06:netbeans13.png?nolink }} | + | <code java> |
| + | <%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %> | ||
| + | </code> | ||
| - | <note tip>Clasele generate pot fi obținute accesând opțiunea //Refresh// din meniul contextual asociat referinței către serviciul web. O astfel de operație este necesară atunci când se modifică funcționalitatea serviciului web (semnăturile metodelor accesibile la distanță, nu și implementarea lor, care este transparentă pentru client).</note> | + | Cele mai frecvent utilizate etichete JSTL pentru gestiunea documentelor XML sunt: |
| - | <note tip>Opțiunea //Clean// din meniul contextual asociat proiectului determină pierderea claselor generate.</note> | + | | ''<x:out>'' | evaluează valoarea unei expresii XPath pe care o afişează\\ \\ Atributele asociate etichetei sunt:\\ • ''select'' (obligatoriu) – expresia XPath care trebuie evaluată, adeseori folosind variabile XPath;\\ • ''escapeXml'' – indică dacă caracterele speciale XML ar trebui ignorate | |
| + | | ''<x:parse>'' | utilizat pentru a parsa date XML specificate fie prin intermediul unui atribut, fie în corpul etichetei\\ \\ Atributele asociate etichetei sunt:\\ • ''var'' – variabila care conţine datele XML parsate;\\ • ''xml'' – textul documentului care se doreşte a fi parsat (de tip ''String'' sau ''Reader'');\\ • ''systemId'' – URI-ul identificatorului de sistem pentru a parsa documentul;\\ • ''filter'' – filtrul ce trebuie aplicat documentului sursă;\\ • ''doc'' – documentul XML ce se doreşte a fi parsat;\\ • ''scope'' – domeniul de vizibilitate al variabilei specificate de atributul ''var'';\\ • ''varDom'' – variabila care conţine datele XML parsate;\\ • ''scopeDom'' – domeniul de vizibilitate al variabilei specificate de atributul ''varDom''. <code java> | ||
| + | <x:parse xml="${myXmlDocument}" var="variable" /> | ||
| + | <x:out select="$variable/root/element[index]/attribute" /> | ||
| + | </code> | | ||
| + | | ''<x:set>'' | atribuie unei variabile valoarea unei expresii XPath; în funcţie de tipul rezultat la evaluarea expresiei XPath, vor fi create obiecte având tipul ''java.lang.Boolean'', ''java.lang.String'', ''java.lang.Number''.\\ \\ Atributele asociate etichetei sunt:\\ • ''var'' (obligatoriu) – variabila care va reţine valoarea expresiei XPath;\\ • ''select'' – expresia XPath care se doreşte evaluată;\\ • ''scope'' – domeniul de vizibilitate al variabilei specificate de atributul ''var''. <code java> | ||
| + | <x:parse xml="${myXmlDocument}" var="variable1" /> | ||
| + | <x:set var="variable2" select="$variable1/root/element" /> | ||
| + | </code> | | ||
| + | | ''<x:if>'' | evaluează o condiţie ce are forma unei expresii XPath şi dacă aceasta se verifică se procesează corpul etichetei\\ \\ Atributele asociate etichetei sunt:\\ • ''select'' (obligatoriu) – expresia XPath exprimând condiţia ce se doreşte evaluată;\\ • ''var'' – variabila care va reţine rezultatul evaluării condiţiei;\\ • ''scope'' – domeniul de vizibilitate al variabilei specificate de atributul ''var''. <code java> | ||
| + | <x:parse xml="${myXmlDocument}" var="variable" /> | ||
| + | <x:if select="$variable/root/element[index]/attribute != 0" /> | ||
| + | The attribute of the element at index is not null! | ||
| + | </x:if> | ||
| + | </code> | | ||
| + | | ''<x:forEach>'' | iterează asupra nodurilor unui document XML\\ \\ Atributele asociate etichetei sunt:\\ • ''select'' (obligatoriu) – expresia XPath care va fi evaluată;\\ • ''var'' – denumirea variabilei care va reţine valoarea elementului curent pentru fiecare iteraţie;\\ • ''begin'' – indexul de început pentru iteraţie;\\ • ''end'' – indexul de sfârşit pentru iteraţie;\\ • ''step'' – valoarea cu care va fi incrementat indexul pe parcursul incrementării colecţiei;\\ • ''varStatus'' – denumirea variabilei în care se va reţine statutul iteraţiei <code java> | ||
| + | <x:parse xml="${myXmlDocument}" var="variable" /> | ||
| + | <x:forEach select="$variable/root/element/attribute" var="item" /> | ||
| + | <x:out select="$item" /> | ||
| + | </x:forEach> | ||
| + | </code> | | ||
| + | | ''<x:choose>'' | etichetă de tip condiţional care stabileşte un context pentru operaţii condiţionale care se exclud mutual, marcate prin ''<when>'' şi ''<otherwise>''\\ \\ Eticheta nu are atribute. <code java> | ||
| + | <x:parse xml="${myXmlDocument}" var="variable" /> | ||
| + | <x:choose> | ||
| + | <x:when select="$variable//element/attribute eq value1"> | ||
| + | Attribute has value 1! | ||
| + | </x:when> | ||
| + | <x:when select="$variable//element/attribute eq value2"> | ||
| + | Attribute has value 2! | ||
| + | </x:when> | ||
| + | ... | ||
| + | <x:when select="$variable//element/attribute eq valuen"> | ||
| + | Attribute has value n! | ||
| + | </x:when> | ||
| + | <x:otherwise> | ||
| + | Attribute has unknown value! | ||
| + | </x:otherwise> | ||
| + | </x:choose> | ||
| + | </code> | | ||
| + | | ''<x:when>'' | subetichetă a etichetei ''<choose>'' al cărei corp este inclus dacă se verifică condiţia asociată.\\ \\ Eticheta are un singur atribut, ''select'', care conţine condiţia ce se doreşte a fi evaluată. | | ||
| + | | ''<x:otherwise>'' | subetichetă a etichetei ''<choose>'' ce urmează uneia sau mai multor etichete ''<when>'', determinând evaluarea corpului său, dacă nici una dintre condiţiile care o preced nu este îndeplinită.\\ \\ Eticheta nu are atribute. | | ||
| + | | ''<x:transform>'' | se aplică la transformare XSL a unui document XML\\ \\ Atributele asociate etichetei sunt:\\ • ''doc'' – documentul XML sursă pentru transformarea XSLT;\\ • ''docSystemId'' – URI-ul documentului XML original;\\ • ''xslt'' (obligatoriu) – foaia de stil XSLT care conţine instrucţiunile pentru transformare;\\ • ''xsltSystemId'' – URI-ul documentului XSLT original;\\ • ''result'' – obiectul rezultat care va accepta rezultatul transformării;\\ • ''var'' – denumirea variabilei în care se va reţine rezultatul transformării\\ • ''scope'' – domeniul de vizibilitate ce va expune rezultatul transformării. <code java> | ||
| + | <x:parse xml="${myXmlDocument}" var="variable" /> | ||
| + | <c:import url="http://www.mysite.com/document.xsl" var="xslt" /> | ||
| + | <x:transform doc="${variable}" xslt="${xslt}" /> | ||
| + | </code> | | ||
| + | | ''<x:param>'' | utilizat împreună cu eticheta de transformare pentru a stabili un parametru în foaia de stil XSLT\\ \\ Atributele asociate etichetei sunt:\\ • ''name'' – denumirea parametrului XSLT ce se doreşte a fi stabilit;\\ • ''value'' – valoarea parametrului XSLT ce se doreşte a fi stabilit. <code java> | ||
| + | <x:transform doc="${variable}" xslt="${xslt}" /> | ||
| + | <x:param name="attributeName" value="attributeValue" /> | ||
| + | </x:transform> | ||
| + | </code> | | ||
| - | Operaţiile pot fi testate din consola serverului de aplicaţii GlassFish, disponibile la [[http://localhost:8080/ReservationService/Reservation?Tester|]]. Invocarea unei funcţionalităţi în acest caz este întotdeauna însoţită de mesajele SOAP care sunt schimbate între client şi server, fiind descrise cererea (invocarea metodei din cadrul serviciului web) precum şi răspunsul (rezultatul execuţiei operaţiei respective în contextul serverului unde rulează serviciul web). | + | ==== Funcții JSTL ==== |
| - | {{ :laboratoare:laborator06:netbeans12.png?nolink&800 }} | + | Expresion Language permite folosirea de funcţii în cadrul expresiilor, acestea trebuind să fie definite în cadrul unor biblioteci de etichete predefinite, apelul său făcându-se folosind sintaxa: |
| - | Pentru exemplul considerat, în cazul metodelor ''getTimetable()'', ''getReservation()'' pot fi vizualizate referinţe (adrese) către obiecte de tip ''Interval'' / ''ReservationData'', în timp ce metodele ''getAvailableSeats()'' şi ''makeReservation()'' / ''cancelReservation()'' nu pot fi accesate corespunzător întrucât ar trebui specificaţi ca parametrii referinţe către obiecte de tip ''Interval'', existente în contextul serverului pe care se află serviciul web. | + | <code java> |
| + | ${ns:function(param1, param2, ..., paramn)} | ||
| + | </code> | ||
| - | Pentru operaţia ''getTimetable()'', formatul mesajelor SOAP interschimbate între client şi server este următorul: | + | JSTL include un număr de funcţii standard, dintre care numeroase implică manipularea şirurilor de caractere. |
| - | * SOAP Request <code xml> | + | Pentru a putea referi aceste etichete, trebuie specificată locaţia de unde acestea pot fi încărcate. |
| - | <?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> | + | |
| - | <SOAP-ENV:Header/> | + | <code java> |
| - | <S:Body> | + | <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> |
| - | <ns2:getTimeTable xmlns:ns2="http://reservation.lab06.aipi.cs.pub.ro/"/> | + | |
| - | </S:Body> | + | |
| - | </S:Envelope> | + | |
| </code> | </code> | ||
| - | * SOAP Response <code xml> | + | |
| - | <?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> | + | Lista de funcţii standard JSTL este redată în continuare: |
| - | <SOAP-ENV:Header/> | + | |
| - | <S:Body> | + | | ''fn:contains()'' | verifică dacă şirul de caractere conţine un alt subşir; primeşte doi parametrii de tip ''java.lang.String'' având semnificaţia şirului de caractere, respectiv a subşirului; rezultatul întors este de tip ''boolean''. <code java> |
| - | <ns2:getTimeTableResponse xmlns:ns2="http://reservation.lab06.aipi.cs.pub.ro/"> | + | <c:set var="variable" value="${fn:contains(stringToBeSearched, substringToSearch)}" /> |
| - | <return> | + | </code> | |
| - | <startingTime>2014-12-17T10:00:00+02:00</startingTime> | + | | ''fn:containsIgnoreCase()'' | verifică dacă şirul de caractere conţine un alt subşir, ignorând capitalizarea; primeşte doi parametrii de tip ''java.lang.String'' având semnificaţia şirului de caractere, respectiv a subşirului; rezultatul întors este de tip ''boolean''. <code java> |
| - | <endingTime>2014-12-17T12:00:00+02:00</endingTime> | + | <c:set var="variable" value="${fn:containsIgnoreCase(stringToBeSearched, substringToSearch)}" /> |
| - | </return> | + | </code> | |
| - | <return> | + | | ''fn:endsWith()'' | verifică dacă şirul de caractere are un anumit sufix; primeşte doi parametrii de tip ''java.lang.String'' având semnificaţia şirului de caractere, respectiv a sufixului; rezultatul întors este de tip ''boolean''. <code java> |
| - | <startingTime>2014-12-17T14:00:00+02:00</startingTime> | + | <c:set var="variable" value="${fn:endsWith(stringToBeSearched, sufix)}" /> |
| - | <endingTime>2014-12-17T20:00:00+02:00</endingTime> | + | </code> | |
| - | </return> | + | | ''fn:escapeXml()'' | transformă caracterele care ar putea fi interpretate ca adnotări XML la valoarea corespunzătoare; primeşte un parametru de tip ''java.lang.String'' având semnificaţia şirului de caractere care se doreşte a fi transformat; rezultatul întors este de tip ''java.lang.String''. <code java> |
| - | <return> | + | <c:set var="variable" value="${fn:escapeXml(stringToBeXmlEscaped)}" /> |
| - | <startingTime>2014-12-20T14:00:00+02:00</startingTime> | + | </code> | |
| - | <endingTime>2014-12-20T16:00:00+02:00</endingTime> | + | | ''fn:indexOf()'' | întoarce prima apariţie a unui subşir specificat în cadrul şirului de caractere; primeşte doi parametrii de tip ''java.lang.String'' având semnificaţia şirului de caractere în care se realizează căutarea, respectiv a şirului care este căutat; rezultatul întors este de tip ''int'' (dacă şirul nu este găsit se întoarce valoarea -1) <code java> |
| - | </return> | + | <c:set var="variable" value="${fn:indexOf(stringToBeSearched, substringToSearch)}" /> |
| - | <return> | + | </code> | |
| - | <startingTime>2014-12-20T18:00:00+02:00</startingTime> | + | | ''fn:join()'' | concatenează toate elementele unui vector într-un singur şir de caractere; primeşte doi parametrii, unul de tip ''java.lang.String[]'' conţinând elementele vectorului şi unul de tip ''java.lang.String'', reprezentând separatorul; întoarce un rezultat de tip ''java.lang.String'' <code java> |
| - | <endingTime>2014-12-20T20:00:00+02:00</endingTime> | + | <c:set var="variable" value="${fn:join(arrayToBeJoined, separator)}" /> |
| - | </return> | + | </code> | |
| - | </ns2:getTimeTableResponse> | + | | ''fn:length()'' | întoarce numărul de elemente al colecţiei sau dimensiunea şirului de caractere; primeşte un parametru de tip ''java.lang.Object'' (de tip colecţie sau şir de caractere); întoarce un rezultat de tip ''int''. <code java> |
| - | </S:Body> | + | <c:set var="variable1" value="${fn:length(myList)}" /> |
| - | </S:Envelope> | + | <c:set var="variable2" value="${fn:length(myString)}" /> |
| + | </code> | | ||
| + | | ''fn:replace()'' | întoarce un şir de caractere obţinut prin înlocuirea unei secvenţe din cadrul său cu o altă secvenţă; primeşte trei parametrii de tip ''java.lang.String'', reprezentând şirul de caractere în care se realizează înlocuirea, secvenţa care se doreşte înlocuită şi valoarea cu care aceasta este înlocuită; întoarce un rezultat de tip ''boolean'' <code java> | ||
| + | <c:set var="variable" value="${fn:length(myString, sequenceToReplace, sequenceToReplaceWith)}" /> | ||
| + | </code> | | ||
| + | | ''fn:split()'' | împarte şirul de caractere într-un vector de subşiruri primeşte doi parametrii de tip ''java.lang.String'', reprezentând şirul de caractere care va fi împărţit, respectiv delimitatorii pe baza cărora se va realiza această operaţie; întoarce un rezultat de tip ''java.lang.String[]''. <code java> | ||
| + | <c:set var="variable" value="${fn:split(myString, delimiter)}" /> | ||
| + | </code> | | ||
| + | | ''fn:startsWith()'' | verifică dacă şirul de caractere are un anumit prefix; primeşte doi parametrii de tip ''java.lang.String'' având semnificaţia şirului de caractere, respectiv a prefixului; rezultatul întors este de tip ''boolean''. <code java> | ||
| + | <c:set var="variable" value="${fn:startsWith(stringToBeSearched, prefix)}" /> | ||
| + | </code> | | ||
| + | | ''fn:substring()'' | întoarce un subşir al şirului de caractere; primeşte un parametru de tip ''java.lang.String'' reprezentând şirul din care se determină subşirul şi doi parametrii de tip int reprezentând poziţiile de început şi de sfârşit; rezultatul întors este de tip ''java.lang.String''. <code java> | ||
| + | <c:set var="variable" value="${fn:substring(myString, startIndex, endIndex)}" /> | ||
| + | </code> | | ||
| + | | ''fn:substringAfter()'' | întoarce un subşir al şirului de caractere ce succede unei anumite secvenţe; primeşte doi parametrii de tip ''java.lang.String'' având semnificaţia şirului de caractere din care se determină subşirul, respectiv secvenţa după care urmează subşirul respectiv; rezultatul întors este de tip ''java.lang.String''. <code java> | ||
| + | <c:set var="variable" value="${fn:substringAfter(myString, subSequence)}" /> | ||
| + | </code> | | ||
| + | | ''fn:substringBefore()'' | întoarce un subşir al şirului de caractere ce precede o anumită secvenţă; primeşte doi parametrii de tip ''java.lang.String'' având semnificaţia şirului de caractere din care se determină subşirul, respectiv secvenţa înainte de care se găseşte subşirul respectiv; rezultatul întors este de tip ''java.lang.String''. <code java> | ||
| + | <c:set var="variable" value="${fn:substringBefore(myString, subSequence)}" /> | ||
| + | </code> | | ||
| + | | ''fn:toLowerCase()'' | transformă toate caracterele şirului în minuscule; primeşte un caracter de tip ''java.lang.String'' reprezentând şirul de caractere ce se doreşte a fi transformat; rezultatul întors este de tip ''java.lang.String'' <code java> | ||
| + | <c:set var="variable" value="${fn:toLowerCase(myString)}" /> | ||
| + | </code> | | ||
| + | | ''fn:toUpperCase()'' | transformă toate caracterele şirului în majuscule; primeşte un caracter de tip ''java.lang.String'' reprezentând şirul de caractere ce se doreşte a fi transformat; rezultatul întors este de tip ''java.lang.String'' <code java> | ||
| + | <c:set var="variable" value="${fn:toUpperCase(myString)}" /> | ||
| + | </code> | | ||
| + | | ''fn:trim()'' | elimină spaţiile care se găsesc la începutul şi sfârşitul şirului de caractere; primeşte un caracter de tip ''java.lang.String'' reprezentând şirul de caractere care se doreşte a fi transformat; rezultatul întors este de ''tip java.lang.String'' <code java> | ||
| + | <c:set var="variable" value="${fn:trim(myString)}" /> | ||
| + | </code> | | ||
| + | |||
| + | ==== Etichete definite de utilizator ==== | ||
| + | |||
| + | În JavaServer Pages pot fi implementate etichete definite de utilizator, care în momentul transformării servlet-ului corespunzător sunt convertite în operaţiile specificate de clasa care îi este asociată, pentru ca atunci când se accesează pagina respectivă, acestea să fie executate. O clasă care defineşte funcţionalitatea unei anumite etichete trebuie să fie derivată din ''javax.servlet.jsp.tagtext.SimpleTagSupport'', implementând metoda ''doTag()''. Aceasta poate accesa obiectele din cadrul paginii JSP prin intermediul metodei ''getJSPContext()''. De asemenea, în cazul în care în corpul etichetei se specifică anumită valoare, aceasta poate fi obţinută într-un obiect de tip ''StringWriter'' prin metoda ''getJspBody().invoke()''. | ||
| + | |||
| + | <file java CustomTag.java> | ||
| + | import java.io.*; | ||
| + | import javax.servlet.jsp.*; | ||
| + | import javax.servlet.jsp.tagext.*; | ||
| + | |||
| + | public class CustomTag extends SimpleTagSupport { | ||
| + | |||
| + | private String customAttribute; | ||
| + | public void setCustomAttribute(String customAttribute) { | ||
| + | this. customAttribute = customAttribute; | ||
| + | } | ||
| + | public String getCustomAttribute() { | ||
| + | return customAttribute; | ||
| + | } | ||
| + | |||
| + | StringWriter stringWriter = new StringWriter(); | ||
| + | public void doTag() throws JspException, IOException { | ||
| + | if (customAttribute != null) { | ||
| + | // process tag attribute | ||
| + | getJspContext().getOut().println(customAttribute); | ||
| + | } else { | ||
| + | // get the content from the tag body | ||
| + | getJspBody().invoke(stringWriter); | ||
| + | // process tag body’s content | ||
| + | getJspContext().getOut().println(stringWriter.toString()); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | } | ||
| + | </file> | ||
| + | |||
| + | Clasa asociată etichetei definite de utilizator va trebui plasată la o locaţie vizibilă prin variabila de mediu ''CLASSPATH''. | ||
| + | |||
| + | Asocierea dintre etichetă şi clasa asociată se face într-un fişier ''custom.tld'' care va fi plasat în ''webapps/root/WEB-INF'' al serverului web Apache Tomcat 8.x. Astfel, se va specifica numele etichetei (aşa cum va fi specificat în pagina JSP – elementul ''<name>'', denumirea clasei care îi implementează funcţionalitatea (elementul ''<tag-class>'') precum şi tipul de conţinut al corpului etichetei (elementul ''<body-content>'', având ca valori posibile ''empty'', dacă trebuie să fie vid, ''scriptless'' dacă este acceptat numai text static, expresii EL sau alte etichete şi ''tagdependent'' în cazul în care conţinutul este scris în alt limbaj, fiind interpretat de implementarea etichetei). De asemenea, pentru fiecare atribut trebuie indicate proprietăţile ''name'' (identificator unic al atributului în cadrul etichetei), ''required'' (care distinge între atributele obligatorii şi cele opţionale), ''rtexprvalue'' (care stabileşte validitatea valorii unei expresii definită în momentul rulării pentru atributul etichetei), ''type'' (care specifică tipul Java al atributului respectiv, implicit fiind ''java.lang.String''), ''description'' şi ''fragment'' (care indică dacă valoarea asociată atributului va fi tratată ca un ''JspFragment''). | ||
| + | |||
| + | <code xml> | ||
| + | <taglib> | ||
| + | <tlib-version>1.0</tlib-version> | ||
| + | <jsp-version>2.0</jsp-version> | ||
| + | <short-name>A short description of my custom tag</short-name> | ||
| + | <tag> | ||
| + | <name>CustomTag</name> | ||
| + | <tag-class>mypackage.CustomTag</tag-class> | ||
| + | <body-content>scriptless</body-content> | ||
| + | <attribute> | ||
| + | <name>customAttribute</name> | ||
| + | <required>true</true> | ||
| + | <type>java.lang.Integer</type> | ||
| + | <fragment>false</fragment> | ||
| + | </attribute> | ||
| + | </tag> | ||
| + | </taglib> | ||
| </code> | </code> | ||
| - | Pentru operaţia ''getReservations()'', primind ca parametru un identificator de client egal cu 1, formatul mesajelor SOAP interschimbate între client şi server este următorul: | + | Pentru a putea fi folosită în cadrul unei pagini JSP, eticheta definită de utilizator trebuie declarată în acelaşi mod în care se procedează şi cu etichetele standard JSTL: |
| - | * SOAP Request <code xml> | + | |
| - | <?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> | + | <code java> |
| - | <SOAP-ENV:Header/> | + | <%@ taglib prefix="customPrefix" uri="WEB-INF/custom.tld"%> |
| - | <S:Body> | + | |
| - | <ns2:getReservations xmlns:ns2="http://reservation.lab06.aipi.cs.pub.ro/"> | + | |
| - | <customerId>1</customerId> | + | |
| - | </ns2:getReservations> | + | |
| - | </S:Body> | + | |
| - | </S:Envelope> | + | |
| </code> | </code> | ||
| - | * SOAP Response <code xml> | + | |
| - | <?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> | + | În momentul în care este utilizată, eticheta va avea numele definit în fişierul ''custom.tld'', fiind prefixată cu denumirea indicată la declararea ei, precizând valori pentru toate atributele care au proprietatea ''required'': |
| - | <SOAP-ENV:Header/> | + | |
| - | <S:Body> | + | <code java> |
| - | <ns2:getReservationsResponse xmlns:ns2="http://reservation.lab06.aipi.cs.pub.ro/"> | + | ... |
| - | <return> | + | <customPrefix:CustomTag customAttribute="0"> |
| - | <clientId>1</clientId> | + | Some custom tag body |
| - | <interval> | + | </customPrefix:CustomTag> |
| - | <startingTime>2014-12-17T14:00:00+02:00</startingTime> | + | ... |
| - | <endingTime>2014-12-17T18:00:00+02:00</endingTime> | + | |
| - | </interval> | + | |
| - | <numberOfSeats>10</numberOfSeats> | + | |
| - | </return> | + | |
| - | </ns2:getReservationsResponse> | + | |
| - | </S:Body> | + | |
| - | </S:Envelope> | + | |
| </code> | </code> | ||
| + | |||
| + | Potrivit implementării clasei asociate etichetei, efectul utilizării sale va fi afişarea valorii atributului specificat, în situaţia în care nu se decide realizarea altor tipuri de procesări asupra ei. | ||
| + | |||
| + | Se pot defini mai multe biblioteci de etichete definite de utilizator, grupate în funcţie de tipul de funcţionalitate pe care o pun la dispoziţia programatorilor, fiecare dintre acestea regăsindu-se într-un alt fişier şi utilizându-se un prefix diferit. | ||
| ===== Activitate de Laborator ===== | ===== Activitate de Laborator ===== | ||
| - | {{ :laboratoare:laborator06:aipi2014-lab06-eclipse.zip }} | + | ==== Structura aplicației web BookStore ==== |
| - | {{ :laboratoare:laborator06:aipi2014-lab06-netbeans.zip }} | + | Se doreşte implementarea unei interfeţe grafice cu utilizatorul (dezvoltată sub forma unei aplicaţii web, folosind serverul Apache Tomcat 8.x) pentru gestiunea informaţiilor reţinute într-o bază de date, aceasta urmând a fi utilizată de un sistem ERP destinat unei librării care comercializează doar cărţi. |
| + | Sistemul informatic va putea fi accesat de: | ||
| + | * un utilizator tip **administrator**, care va manipula – prin intermediul aplicaţiei – informaţiile din baza de date; acesta are la dispoziție operații de adăugare, editare și ștergere pentru oricare dintre tabele; | ||
| + | * 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''). | ||
| - | <note important>Persistența informațiilor (program de funcționare, rezervări ale clienților) este asigurată prin stocarea și încărcarea acestora în fișierele xml corespunzătoare corespunzătoare structurilor ''PersistentInterval'' și ''PersistentReservationData'' (''timetable.xml'', respectiv ''reservationData.xml'' din directorul ''output''), astfel încât orice operație care realizează modificări trebuie să asigure și sincronizarea cu informațiile de pe discul local.</note> | + | 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. |
| - | ==== Eclipse ==== | + | {{ :laboratoare:laborator05:bookstore_webapplication_structure.png?nolink&300 }} |
| - | <note important>O instanță a serverului rulează permanent, în contextul proiectului din care face parte. De aceea, de fiecare dată când sunt realizate modificări la nivelul implementării metodelor la distanță, acesta trebuie repornit, pentru ca noile funcționalități să fie vizibile către clienți.</note> | + | <html> |
| + | <center> | ||
| + | </html> | ||
| + | **Structura aplicaţiei BookStore** | ||
| + | <html> | ||
| + | </center> | ||
| + | </html> | ||
| - | ==== NetBeans & GlassFish ==== | + | 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. | ||
| - | <note important>Ο instanță a serverului va rula doar atâta timp cât există o invocare a unei metode pe care acesta o implementează. Fiecare invocare a unei metode la distanță presupune așadar apelarea constructorului în mod automat. Nu este necesar să se realizeze operația de deploy a serviciului web de fiecare dată când se realizează modificări la nivelul implementării serviciului web. Aceasta este realizată automat în momentul în care codul sursă este salvat, urmând ca arhiva .war corespunzătoare să fie plasată în contextul serverului de aplicații. În acest mod, se poate realiza procesul de întreținere a codului sursă, fără ca aceasta să implice perioade în care serviciul să nu fie accesibil.</note> | + | {{ :laboratoare:laborator04:bookstore_webapplication_loginservlet.png?nolink&300 }} |
| - | **0.** [**0 puncte**] Să se plaseze în contextul serverului de aplicații: | + | <html> |
| - | * directorul ''input'' cu fișierul ''timetable.txt''; | + | <center> |
| - | * directorul ''output'' (inițial acesta este gol). | + | </html> |
| + | **Pagina de tip autentificare din cadrul aplicaţiei BookStore** | ||
| + | <html> | ||
| + | </center> | ||
| + | </html> | ||
| - | <note tip>Aplicația va rula în cadrul serverului de aplicații, motiv pentru care este necesar ca informațiile care vor fi citite / scrise să fie plasate în cadrul acestuia: | + | {{ :laboratoare:laborator04:bookstore_webapplication_administratorservlet.png?nolink&800 }} |
| - | * Linux: ''~/glassfish-4.1/glassfish/domains/domain1/config'' (dacă mediul de dezvoltare a fost instalat folosind utilizatorul ''root'', acesta va fi plasat în ''/usr/local'') | + | |
| - | * Windows: ''%USERPROFILE%\AppData\Roaming\NetBeans\8.0.1\config\GF_4.1\domain1\config'' | + | |
| - | </note> | + | |
| - | ===== ===== | + | <html> |
| + | <center> | ||
| + | </html> | ||
| + | **Pagina de tip administrator din cadrul aplicaţiei BookStore** | ||
| + | <html> | ||
| + | </center> | ||
| + | </html> | ||
| - | **1.** [**10 puncte**] Să se încarce, în constructorul clasei ''Reservation'' (din pachetul ''ro.pub.cs.aipi.lab06.reservation''), orarul de funcționare al programului de rezervare, în condițiile în care pe server nu există un fișier XML care conține aceste informații. | + | {{ :laboratoare:laborator04:bookstore_webapplication_clientservlet.png?nolink&800 }} |
| + | |||
| + | <html> | ||
| + | <center> | ||
| + | </html> | ||
| + | **Pagina de tip client din cadrul aplicaţiei BookStore** | ||
| + | <html> | ||
| + | </center> | ||
| + | </html> | ||
| - | Obținerea programului de funcționare se realizează prin parsarea fișierului ''timetable.txt'' din directorul ''input'', acesta urmând a fi încărcat în atributul ''timetable''. De asemenea, va fi încărcată și valoarea atributului ''numberOfSeats''. | + | ===== ===== |
| - | **2.** [**10 puncte**] Să se implementeze metodele de conversie între tipurile de date ''ArrayList<Interval>'' şi ''PersistentInterval'', respectiv ''ArrayList<ReservationData>'' şi ''PersistentReservationData''. | + | **0**. Să se cloneze în directorul de pe discul local conținutul depozitului la distanță de la [[https://www.github.com/aipi2015/Laborator05|]]. În urma acestei operații, directorul ''Laborator05'' va trebui să conțină subdirectorul ''labtasks'', fișierele ''README.md'' și ''LICENSE''. <code> |
| + | student@aipi2015:~$ git clone https://www.github.com/aipi2015/Laborator05.git | ||
| + | </code> | ||
| - | Acestea sunt tipurile de date corespunzătoare atributelor clasei ''Reservation'', prin intermediul cărora se realizează persistența între invocări succesive ale metodelor la distanță, respectiv tipurile de date prin care aceste informații sunt accesate / sunt făcute vizibile la distanță, prin intermediul metodelor implementate. | + | **1**. Să se ruleze, folosind MySQL Workbench (sau alt utilitar similar), scriptul ''Laborator05l.sql'', localizat în directorul ''scripts''. Acesta instalează baza de date ''bookstore''. |
| - | <note tip>Este suficient să se implementeze conversiile într-un singur sens ''PersistentInterval'' → ''ArrayList<Interval>'' şi ''PersistentReservationData'' → ''ArrayList<ReservationData>''.</note> | + | <note>În cazul în care baza de date ''bookstore'' este deja instalată, nu mai este necesar să se ruleze acest script.</note> |
| - | **3.** [**10 puncte**] Să se implementeze metoda ''getTimeTable()''. | + | <note important>Această operație poate dura o perioadă de timp îndelungată, în funcție de configurațiile mașinilor pe care se lucrează.</note> |
| - | **4.** [**40 puncte**] Să se implementeze metoda ''getAvailableSeats()''. | + | **2.** În cazul Unix, daţi drepturi de execuţie tuturor fişierelor .sh din directorul ''bin'' al serverului Apache Tomcat, întrucât acestea sunt apelate la rândul lor de ''startup.sh'', respectiv ''shutdown.sh''. |
| - | **5.** [**10 puncte**] Să se implementeze metoda ''makeReservation()''. | + | <code bash> |
| + | student@aipi2015:~/apache-tomcat-8.0.28$ cd bin | ||
| + | student@aipi2015:~/apache-tomcat-8.0.28/bin$ sudo chmod +x *.sh | ||
| + | </code> | ||
| - | **6.** [**10 puncte**] Să se implementeze metoda ''cancelReservation()''. | + | **3.** Modificați în interfața ''Constants'' din pachetul ''ro.pub.cs.aipi.lab05.general'' informațiile necesare obținerii drepturilor de acces la baza de date (nume de utilizator, parola). |
| - | **7.** [**0 puncte**] | + | **4.** Să se configureze mediile integrate de dezvoltare astfel încât acestea să fie interfațate cu serverul web Apache Tomcat 8.x. Mai multe informații cu privire la modul în care poate fi realizată interfațarea dintre aceste componente pot fi găsite la [[:utile:apache_tomcat|serverul Apache Tomcat]]. |
| ==== Eclipse ==== | ==== Eclipse ==== | ||
| - | Să se lanseze în execuţie ''ReservationService'' accesând opțiunea //Run as...// → //Java Application// din meniul contextual asociat proiectului. | + | Să se creeze o referinţă către serverul HTTP Apache Tomcat care să fie adăugată la proiectul 04-BookStore-JavaServlets. |
| + | |||
| + | Să se deschidă proiectul folosind opţiunea //File// → //Import// → //General// → //Existing Project into Workspace..//. | ||
| + | |||
| + | Se accesează opţiunea //Run as...// → //Run On Server// din meniul contextual al aplicaţiei 04-BookStore-JavaServlets (right-click), bifându-se opţiunea //Always use this server when running this project//. | ||
| + | |||
| + | {{ :laboratoare:laborator04:eclipse01.png?nolink }} | ||
| + | |||
| + | {{ :laboratoare:laborator04:eclipse02.png?nolink }} | ||
| + | |||
| + | {{ :laboratoare:laborator05:eclipse03.png?nolink }} | ||
| ==== NetBeans ==== | ==== NetBeans ==== | ||
| - | Să se lanseze în execuţie ''ReservationService'' accesând opțiunea //Deploy// din meniul contextual asociat proiectului. | + | 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). | ||
| + | |||
| + | {{ :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. | ||
| ===== ===== | ===== ===== | ||
| - | **8.** [**0 puncte**] | + | Î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 ==== | ==== Eclipse ==== | ||
| - | Să se genereze sursele pentru client, rulând scriptul ''client.[bat|sh]'' din directorul ''scripts''. | + | 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 ==== | ==== NetBeans ==== | ||
| - | Să se genereze sursele pentru client, accesând opțiunea //Refresh// din meniul contextual asociat referinței serviciului web (//Web Service References// → //Reservation// (right-click)). | + | 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//. |
| - | <note>Se va bifa și check-box-ul //Also replace local wsdl file with original wsdl located at//: [[http://localhost:8080/ReservationService/Reservation?wsdl|]].</note> | + | {{ :laboratoare:laborator04:netbeans02.png?nolink }} |
| ===== ===== | ===== ===== | ||
| + | |||
| + | **5.** Să se testeze aplicaţia prin accesarea adresei [[http://localhost:8080/05-BookStore-JSP/|]]. | ||
| - | **9.** [**10 puncte**] Să se apeleze metodele ''makeReservation()'' şi ''cancelReservation()'' din client. | + | Se poate consulta script-ul ''Laborator05l.sql'' există exemple de utilizatori care pot fi folosite pentru accesarea paginilor de administrator, respectiv de client. |
| + | * administrator: mary.smith / - | ||
| + | * client: linda.williams / - | ||
| - | <note tip>Un obiect de tip ''GregorianCalendar'' din cadrul clasei ''Interval'' va putea fi afişat apelând metoda ''toXMLFormat()''.</note> | + | **6.** Să se acceseze pagina de tip administrator şi să se testeze funcţionalităţile implementate în cadrul acesteia (adăugare, editare, ştergere). |
| - | <note tip>Nu este generat și un constructor de copiere pentru obiectul de tip ''Interval'', motiv pentru carea un atribut ''GregorianCalendar'' al acestuia, desemnând una dintre limite, va fi specificat prin metodele de tip setter corespunzătoare, acesta fiind creat prin metoda <code java> | + | **7.** Să se acceseze pagina de tip client. Să se implementeze funcționalitatea corespunzătoare filtrării în funcție de limbile în care sunt disponibile cărțile din librărie. Un utilizator poate adăuga o valoare din lista de limbi disponibile. Filtrarea se face în funcție de limbile selectate, pentru acele formate de prezentare a cărții care conțin cel puțin una dintre aceste valori. În situația în care nu s-a specificat nici o valoare, sunt incluse toate volumele comercializate. Un utilizator poate șterge una sau mai multe dintre limbile selectate anterior. |
| - | DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar(year, month, day_of_month, hour_of_day, minute) | + | |
| - | </code> care furnizează un obiect de tip ''XMLGregorianCalendar'' corespunzător tipului de dată care poate fi transmis prin infrastructura de comunicație (pentru care există mapare într-o schemă XML).</note> | + | |
| - | **10.** [**10 puncte**] Să se implementeze o nouă metodă în serviciul web, denumită ''getReservations()'' care întoarce rezervările realizate de un anumit client, al cărui identificator este precizat ca parametru al metodei. | + | {{ :laboratoare:laborator04:activitate_de_laborator_exercitiu07.png?nolink }} |
| + | <spoiler|Indicații de Rezolvare> | ||
| + | Î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 (atributul ''languagesFilter'', transmis din ''ClientServlet''), iar pentru fiecare element: | ||
| + | * 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''). | ||
| + | |||
| + | Elementele vor fi incluse ca linii în cadrul unui tabel (''<tr><td>...</td></tr>''). | ||
| + | |||
| + | 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 ''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> | ||
| + | </spoiler> | ||
| + | |||
| + | **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> | ||
| + | Î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 determină identificatorul formatului de prezentare a cărții și cantitatea corespunzătoare: | ||
| + | |||
| + | {{ :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> | ||
| + | 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")); | ||
| + | } | ||
| + | </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> | ||
| + | **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")) { | ||
| + | String quantity = request.getParameter(Constants.COPIES.toLowerCase() + "_" + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "_" + bookPresentationId); | ||
| + | } | ||
| + | </code> | ||
| + | <note tip>Vor fi transmiși un număr de parametrii egal cu numărul de câmpuri text afișate în cadrul paginii Internet, însă va fi luat în considerare doar cel asociat butonului care a fost apăsat, chiar dacă pot fi introduse valori și în cadrul acestora. Obținerea valorii transmise prin intermediul unui parametru se realizează prin apelul ''request.getParameter(parameter)''.</note> | ||
| + | * se iterează asupra conținutului coșului de cumpărături (obiectul ''shoppingCart'', transmis prin intermediul sesiunii, este de tipul ''List<Record>'' unde ca atribut se reţine identificatorul formatului de prezentare a cărţii, iar ca valoare cantitatea): | ||
| + | * dacă se identifică un element având același identificator al formatului de prezentare a cărții: | ||
| + | * în situația în care cantitatea este nenulă, aceasta este modificată; | ||
| + | * î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ă. | ||
| + | |||
| + | <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> | <code java> | ||
| - | @WebMethod(operationName = "getReservations") | + | session.setAttribute(Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()), shoppingCart); |
| - | public ArrayList<ReservationData> getReservations(@WebParam(name = "customerId") int customerId); | + | |
| </code> | </code> | ||
| + | </note> | ||
| + | </spoiler> | ||
| + | |||
| + | **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 }} | ||
| + | |||
| + | <spoiler|Indicații de Rezolvare> | ||
| + | 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. | ||
| + | |||
| + | 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. | ||
| + | |||
| + | 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>''). | ||
| + | </spoiler> | ||
| + | |||
| + | **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> | ||
| + | Resursele grafice pentru butoane se regăsesc în directorul ''images'', în subdirectorul ''user_interface'', având denumirile: | ||
| + | * ''remove_from_shopping_cart.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). 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> | ||
| + | |||
| + | **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> | ||
| + | În cazul anulării unei comenzi, se şterge conţinutul obiectului ''shoppingCart''. | ||
| + | |||
| + | În cazul finalizării unei comenzi, trebuie realizate următoarele operaţii: | ||
| + | * se adaugă o înregistrare în tabela ''invoice_header''; se va folosi metoda ''create()'' din cadrul clasei ''InvoiceHeaderManager'' pentru care trebuie precizate valorile ce vor fi adăugate, aceasta furnizând identificatorul înregistrării din tabelă: | ||
| + | * numărul de identificare (câmpul ''identification_number'') va fi generat aleator folosind metoda ''Utilities.generateIdentificationNumber()'', care primește ca parametri numărul de caractere de tip literă (3), respectiv cifră (6); | ||
| + | * data de emitere (câmpul ''issue_date'') - ziua curentă - va fi obținută folosind metoda [[https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#now--|now()]] din clasa [[https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html|LocalDate]]; | ||
| + | * starea (câmpul ''state'') are valoarea ''issued'' reținut de constanta ''STATE_ISSUED'' din interfața ''Constants''; | ||
| + | * identificatorul utilizatorului (câmpul ''user_id'') va fi determinat pe baza denumirii (stocate în obiectul ''display'') - concatenarea dintre prenumele şi numele reţinute în tabela ''user'' - prin apelul metodei ''getIdentifier()'' din clasa ''UserManager''; | ||
| + | * 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 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: | ||
| + | * identificatorul facturii (câmpul ''invoice_header_id''), determinat anterior; | ||
| + | * identificatorul formatului de prezentare a cărții (câmpul ''book_presentation_id''); | ||
| + | * 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. | ||
| + | </spoiler> | ||
| + | |||
| + | **12.** Să se implementeze operaţia de deautentificare printr-un buton plasat sub mesajul de întâmpinare pentru fiecare utilizator în pagina de tip client. În această situație, utilizatorul se va întoarce în pagina de autentificare. | ||
| + | |||
| + | {{ :laboratoare:laborator04:activitate_de_laborator_exercitiu12.png?nolink }} | ||
| + | |||
| + | <spoiler|Indicații de Rezolvare> | ||
| + | Î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: | ||
| + | * se obține lista cu toți parametrii (metoda [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html#getParameterNames--|getParameterNames()]] din clasa [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html|ServletRequest]]), aceștia fiind eliminați, prin invocarea metodei [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html#removeAttribute-java.lang.String-|removeAttribute()]]; | ||
| + | * se elimină elementele conținute de listele ''shoppingCart'', ''formatsFilter'', ''languagesFilter'', ''categoriesFilter''; | ||
| + | * valorile conținute de obiectele ''previousRecordsPerPage'', ''currentRecordsPerPage'', ''currentPage'' vor fi cele implicite; | ||
| + | * se elimină conținutul obiectului ''books''; | ||
| + | * se transferă contextul către servletul care gestionează operația de autentificare (''LoginServlet''): <code java> | ||
| + | RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/" + Constants.LOGIN_SERVLET_PAGE_CONTEXT); | ||
| + | if (dispatcher != null) { | ||
| + | dispatcher.forward(request, response); | ||
| + | } | ||
| + | </code> | ||
| + | * se invalidează sesiunea prin invocarea metodei [[https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html#invalidate--|invalidate()]] pe obiectul de tip [[https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html|HttpSession]], - după această operație nu mai este permis să se utilizeze pagina Internet curentă; <code java> | ||
| + | session.invalidate(); | ||
| + | </code> | ||
| + | |||
| + | <note tip>Se poate utiliza ca model implementarea din cadrul paginii de administrator (clasa ''AdministratorServlet'' / pagina ''administrator.jsp'').</note> | ||
| + | </spoiler> | ||
| ===== Resurse ====== | ===== Resurse ====== | ||
| [[https://docs.oracle.com/javaee/7/tutorial/doc/javaeetutorial7.pdf|Eric Jendrock, Ricardo Cervera- | [[https://docs.oracle.com/javaee/7/tutorial/doc/javaeetutorial7.pdf|Eric Jendrock, Ricardo Cervera- | ||
| - | Navarro, Ian Evans, Kim Haase, William Markito - The Java EE 7 Tutorial]] - capitolele 27, 28\\ | + | Navarro, Ian Evans, Kim Haase, William Markito - The Java EE 7 Tutorial]] - capitolul 9\\ |
| - | [[https://netbeans.org/kb/docs/websvc/jax-ws.html|Getting Started with JAX-WS Web Services]]\\ | + | [[http://tomcat.apache.org/|Apache Tomcat]]\\ |
| - | [[http://www.oracle.com/technetwork/articles/javase/index-140168.html|Java Architecture for XML Binding (JAXB)]]\\ | + | [[http://www.tutorialspoint.com/jsp/|Basic JSP Tutorial]]\\ |
| - | [[http://www.vogella.com/tutorials/JAXB/article.html|JAXB - Tutorial]] | + | [[http://www.java-samples.com/jsp/|Knowledge Base on JSP]]\\ |
| + | [[http://www.javatpoint.com/jsp-tutorial|JSP Tutorial]]\\ | ||
| + | [[http://www.jsptut.com/|JSP Tutorial]]\\ | ||
| + | [[https://www.hscripts.com/tutorials/jsp/|JavaServer Pages Tutorial]]\\ | ||
| + | [[http://courses.coreservlets.com/Course-Materials/csajsp2.html|Building Web Apps in Java: Beginning & Intermediate Servlet & JSP Tutorials]]\\ | ||
| + | [[http://courses.coreservlets.com/Course-Materials/msajsp.html|Advanced Servlet and JSP Tutorials]]\\ | ||
| + | [[http://www.vogella.com/tutorials/EclipseWTP/article.html|Java web development with Eclipse WTP - Tutorial]]\\ | ||
| + | [[http://books.google.com/books?isbn=1430204656|Giulio Zambon with Michael Sekler – Beginning JSPTM, JSFTM and Tomcat Web Development: From Novice to Professional, Apress, 2007]]\\ | ||
| + | Irina ATHANASIU, //Java ca limbaj pentru programare distribuita//, Editura Matrix Rom, București, 2002 | ||
| ===== Soluții ===== | ===== Soluții ===== | ||
| - | [[https://github.com/aipi2014/Laborator06/tree/master/Eclipse/|Proiect Eclipse]]\\ | + | [[https://github.com/aipi2015/Laborator05/tree/master/solutions/eclipse/05-BookStore-JSP|Proiect Eclipse]]\\ |
| - | [[https://github.com/aipi2014/Laborator06/tree/master/NetBeans/|Proiect NetBeans]] | + | [[https://github.com/aipi2015/Laborator05/tree/master/solutions/netbeans/05-BookStore-JSP|Proiect NetBeans]] |
