Visualizzazione dei risultati da 1 a 10 su 10
  1. #1
    Utente di HTML.it L'avatar di ubisum
    Registrato dal
    Mar 2007
    Messaggi
    22

    Servlet non aggiorna attributo di sessione

    Salve a tutti.
    Sto realizzando un semplice sistema di gestione dei contatti in rubrica.
    Una pagina JSP/JSTL è stata scritta per visualizzare i contatti associati all'utente loggato, i cui dati sono tenuti in un attributo di sessione.
    Alla pagina JSP è associata una servlet:

    codice:
    package it.biagio.servlet;
    
    
    import java.io.IOException;
    import java.util.List;
    
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    import it.biagio.model.Contact;
    import it.biagio.model.User;
    import it.biagio.service.UserService;
    
    
    @WebServlet("/showContacts")
    public class showContacts extends HttpServlet {
        private static final long serialVersionUID = 1L;
           
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            User user = (User)request.getSession().getAttribute("id");
            UserService us = new UserService();
            RequestDispatcher requestDispatcher; 
            
            try
            {            
                // get list of contacts
                List<Contact> listOfContacts = us.getContacts(user.getId());
                
                // set session parameter
                request.getSession().setAttribute("contacts", listOfContacts);
                
                // forward
                requestDispatcher = request.getRequestDispatcher("contacts.jsp");
                requestDispatcher.forward(request, response);
            }
            
            catch(Exception e)
            {
                requestDispatcher = request.getRequestDispatcher("failure.jsp");
                requestDispatcher.forward(request, response);
            }
        }
    
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // TODO Auto-generated method stub
            doGet(request, response);
        }
    
    
    }
    I contatti vengono visualizzati correttamente ed accanto a ciascuno di essi è possibile cliccare su un link che porta ad un'altra pagina JSP in cui il contatto può essere modificato.
    Anche a quest'altra pagina è associata una servlet:
    codice:
    package it.biagio.servlet;
    
    
    import java.io.IOException;
    import java.util.logging.Logger;
    
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    import it.biagio.model.Contact;
    import it.biagio.model.User;
    import it.biagio.service.UserService;
    
    
    /**
     * Servlet implementation class updateContact
     */
    @WebServlet("/updateContact")
    public class updateContact extends HttpServlet {
        private static final long serialVersionUID = 1L;
        private int contactId;
        private UserService service;
        private Logger logger = Logger.getLogger(updateContact.class.getName());
      
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            contactId = Integer.parseInt(request.getParameter("contactId"));
            service = new UserService();
            
            try
            {
                Contact contact = service.getContact(contactId);
                request.getSession().setAttribute("contact", contact);
            }
            
            catch(Exception e)
            {
                logger.info(e.getMessage());
            }
            
            request.getRequestDispatcher("updateContact.jsp").forward(request, response);
        }
    
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // get info about contact
            String name = request.getParameter("name");
            String surname = request.getParameter("surname");
            String telephone = request.getParameter("telephone");
            String email = request.getParameter("email");
            
            // prepare a new contact
            Contact contact = new Contact();
            contact.setEmail(email);
            contact.setName(name);
            contact.setSurname(surname);
            contact.setTelephone(telephone);
            contact.setId(contactId);
            
            String result;
            
            try
            {
                result = service.editContact(contact);
            }
            
            catch(Exception e)
            {
                result = e.getMessage();
            }
            
            logger.info(result);
            request.getRequestDispatcher("contacts.jsp").forward(request, response);
            
            
        }
    
    
    }
    Quando l'utente conferma le modifiche, queste vengono correttamente salvate sul DB ma, quando la prima servlet viene richiamata, i contatti visualizzati non sono aggiornati.
    Da cosa può dipendere?

    Grazie.

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Molto probabilmente dal fatto che la servlet che si occupa di effettuare l'aggiornamento invoca il service per modificare il DB... e successivamente va a fare il forward alla pagina contacts.jsp senza aver ricaricato in sessione la nuova lista contatti (con i dati aggiornati), cosa di cui si occupa, appunto, la prima servlet.

    Quindi, dopo aver aggiornato il DB dovresti rileggere la lista contatti e aggiornare l'attributo "contacts" che è in sessione affinchè la JSP possa usarlo.... altrimenti continuerà ad usare quello vecchio.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Bisognerebbe vedere meglio cosa fanno i vari metodi di quel UserService (che io ovviamente non lo so).
    Ma a parte questo, una cosa te la posso segnalare subito, che è molto "seria".

    Nella seconda servlet tieni dei campi di istanza.

    private int contactId;
    private UserService service;

    Lo sai che la istanza della servlet è UNA sola e tutte le invocazioni ai doXXX possono anche essere effettuate in modo concorrente da più thread distinti?
    Che succede se, per dire uno scenario possibile, la sequenza delle richieste fosse:
    - l'utente A causa la invocazione di doGet per contactId 100
    - l'utente B causa la invocazione di doGet per contactId 200
    - l'utente A causa la invocazione di doPost per aggiornare name, surname ecc...
    - l'utente B causa la invocazione di doPost per aggiornare name, surname ecc...
    ?

    Questa si chiama "race condition" e ti consiglio di correggere subito, perché è parecchio grave.
    Ultima modifica di andbin; 29-06-2017 a 14:04
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  4. #4
    Utente di HTML.it L'avatar di ubisum
    Registrato dal
    Mar 2007
    Messaggi
    22
    Ti ringrazio per la risposta, anche perchè mi permette di farti un'altra domanda.
    Sono abbastanza nuovo alle servlet e questo spiega il fatto che non ne conosca ancora bene le problematiche, compresa la "race condition" di cui mi hai parlato.
    Ora so una cosa nuova a cui non potevo aver pensato.
    Ma ecco la domanda.
    La seconda servlet riceve un parametro all'interno dell'URL, che identifica il codice del contatto da modificare.
    Deve conservare questo parametro fin tanto che l'utente termini le modifiche al contatto, cioè fino all'istante in cui il suo metodo doPost non sia invocato.
    Come potrei fare questo in modo sicuro ed efficiente?
    Grazie

  5. #5
    Utente di HTML.it L'avatar di ubisum
    Registrato dal
    Mar 2007
    Messaggi
    22
    grazie dell'aiuto.
    ho risolto facendo il forwarding alla servlet e non più alla pagina che gestisce.
    Volevo modificare il post originale per segnalare che ho risolto, ma non riesco a trovare come modificarlo.
    Di solito, sui forum, c'è un "modifica post".
    Qui dove si trova?

  6. #6
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Quote Originariamente inviata da ubisum Visualizza il messaggio
    grazie dell'aiuto.
    ho risolto facendo il forwarding alla servlet e non più alla pagina che gestisce.
    Volevo modificare il post originale per segnalare che ho risolto, ma non riesco a trovare come modificarlo.
    Di solito, sui forum, c'è un "modifica post".
    Qui dove si trova?
    Qui non segnamo i thread come risolti... in questo modo chi altro avesse lo stesso problema potrebbe agganciarsi a questo.

    Va bene così... nel frattempo diamo tempo anche a andbin di darti tutte le informazioni che gli hai chiesto.

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  7. #7
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da ubisum Visualizza il messaggio
    Deve conservare questo parametro fin tanto che l'utente termini le modifiche al contatto, cioè fino all'istante in cui il suo metodo doPost non sia invocato.
    Come stavi facendo, con UNA variabile (che oltretutto come ho detto prima è in UNA sola istanza della servlet) proprio NO. Se avessi 2, 3, 4 ecc... utenti che stanno gestendo contatti con Id differenti? Dove li tieni questi Id?

    Una possibilità sarebbe tenere il Id nella sessione. La sessione è "per client". Ma non è comunque perfetta/ottimale come soluzione. L'utente potrebbe fare il furbo e tenersi 2 schede del browser aperte che condividono la stessa sessione e in una gestire un contatto con un certo Id e nell'altra scheda tentare di gestire un altro contatto. Avresti lo STESSO problema.

    Quote Originariamente inviata da ubisum Visualizza il messaggio
    Come potrei fare questo in modo sicuro ed efficiente?
    La soluzione pulita e corretta è davvero semplice: il doPost riceve il contactId insieme agli altri parametri, che dovrà ovviamente essere inviato dal updateContact.jsp.
    Tutto qui.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  8. #8
    Utente di HTML.it L'avatar di ubisum
    Registrato dal
    Mar 2007
    Messaggi
    22
    ok, grazie, perfetto.

  9. #9
    Utente di HTML.it L'avatar di ubisum
    Registrato dal
    Mar 2007
    Messaggi
    22
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Come stavi facendo, con UNA variabile (che oltretutto come ho detto prima è in UNA sola istanza della servlet) proprio NO. Se avessi 2, 3, 4 ecc... utenti che stanno gestendo contatti con Id differenti? Dove li tieni questi Id?

    Una possibilità sarebbe tenere il Id nella sessione. La sessione è "per client". Ma non è comunque perfetta/ottimale come soluzione. L'utente potrebbe fare il furbo e tenersi 2 schede del browser aperte che condividono la stessa sessione e in una gestire un contatto con un certo Id e nell'altra scheda tentare di gestire un altro contatto. Avresti lo STESSO problema.


    La soluzione pulita e corretta è davvero semplice: il doPost riceve il contactId insieme agli altri parametri, che dovrà ovviamente essere inviato dal updateContact.jsp.
    Tutto qui.
    Grazie per la risposta.
    Sono felice di leggere nelle tue parole (dette da uno certamente più esperto) alcune delle considerazioni che avevo fatto.
    Anche io avevo valutato la possibilità di aggiungere un attributo di sessione ad hoc, ma ho scartato questa soluzione perché ho ritenuto che non fosse una buona idea infarcire la sessione di attributi, specie con quelli che hanno una brevissima sopravvivenza.
    Quindi, prima di decidere (sbagliando) per il campo privato della servlet, mi sono chiesto: può updateContact.jsp, che riceve l'id del contatto tramite URL, passare quel medesimo id al metodo doPost della sua servlet, insieme ai parametri contenuti nel form per modificare i dati?
    Lo si potrebbe fare, per esempio, usando del semplice codice JSP?

    Grazie.

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da ubisum Visualizza il messaggio
    che non fosse una buona idea infarcire la sessione di attributi, specie con quelli che hanno una brevissima sopravvivenza.
    La questione qui non è tanto della "durata" ma del fatto che la sessione è UNA sola (e quindi ci tieni 1 Id) mentre nulla vieta all'utente di tenersi diversi tab o finestre di quella stessa istanza del browser aperte (che condividono la sessione) e tentare di gestire contatti con Id diversi. Avresti ben presto dei casini.

    Quote Originariamente inviata da ubisum Visualizza il messaggio
    mi sono chiesto: può updateContact.jsp, che riceve l'id del contatto tramite URL, passare quel medesimo id al metodo doPost della sua servlet, insieme ai parametri contenuti nel form per modificare i dati?
    Lo si potrebbe fare, per esempio, usando del semplice codice JSP?
    Quando fai

    request.getRequestDispatcher("updateContact.jsp"). forward(request, response);

    i dati del contatto li hai tutti nell'oggetto Contact che passi nella sessione e sono quindi accessibili alla pagina.
    Quindi puoi benissimo fare in modo che al submit del form venga inviato ANCHE il Id del contatto.
    Il Id del record di norma non lo si fa editare dall'utente, quindi non lo metterai certo in un campo di testo visibile. Ma lo puoi mettere in un campo "hidden", che viene comunque inviato con il resto dei dati nel form.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.