J2EE

di il
30 risposte

J2EE

Salve, a tutti mi chiamo Gianpiero e sono nuovo.Da qualche giorno mi sto avvicinando al mondo Java Enterprise e dopo aver letto un tutorial su EJB3.0 mi restano delle perplessità.
Per meglio capire il motivo dei miei dubbi vi spiego da dove nascono.

Per testare i session bean stateless e statefull, ho fatto un semplice esempio.
Ho creato un bean stateless "Counter" con una variabile istanza intera "contatore " inizializzata a 1 e con due metodi setCounter il quale incrementa di uno il contatore e getCounter che ritorna il valore della variabile intera.
Ho poi creato una jsp che tramite form chiama una servlet la quale recupera il riferimento al bean tramite annotazione @EJB e se riceve un comando di incremento dalla jsp chiama il metodo setCounter del bean e poi stampa il valore del contatore. Ora, avendo letto il tutorial della Sun mi aspettavo che la servlet chiamata rispondesse sempre con 1(se non invio parametri tramite jsp) o al più 2 se invece invio il comando di incremento.Invece quello che succede è che il bean stateless ricorda le vecchie chiamata e incrementa il contatore ogni volta come se il bean fosse di tipo statefull....come mai questo comportamento? Le specifiche Sun dicono che lo stato dei bean stateless dura solo il tempo dell'invocazioni dei metodi!!!
Spero di avervi chiarito la questione e mi aspetto una risposta che mi chiarisca

30 Risposte

  • Re: J2EE

    Ciao, per un session bean stateless l'application server crea un pool di oggetti.Quando ne viene richiesto uno la selezione avviene in questo pool. In sostanza può accadere che quando si richiede il session bean venga effettivamente restituita l'istanza utilizzata in una precedente chiamata, più in generale però, ciò che accade è la selezione di una qualsiasi istanza presa dal pool. Un session bean stateless non mantiene alcuno stato conversazionale con il client, quello che hai ottenuto è stato un caso particolare in cui la chiamata per il session bean ha prodotto la selezione dal pool della stessa istanza ma questo in generale non è detto che accada.
  • Re: J2EE

    Ciao alessandro grazie per la risposta.Avrei qualche altra domande da fare riguardo J2EE però non so se porle su questo thread o creare un nuovo post ad ogni mia domanda
  • Re: J2EE

    Se hai qualche domanda puoi chiedermi pure su questo thread appena posso ti rispondo.Ciao.
  • Re: J2EE

    Se per ipotesi la mia Enterprise App è composta da una JSP, una servlet e un Bean Session statefull
    I mio prossimo quesito è:

    Come posso dalla JSP recuperare il riferimento al Session bean? Posso usare la sintassi
    "<jsp:useBean id=.... scope=.. >" o devo usare la sintassi <% @EJB private SessionBean %>
    Le due sintassi sono equivalenti? Nel caso non lo fossero quale è la differenza


    Premesso che sto provando ad usare JPA e Netbeans com IDE. Il secondo mio dubbio è legato appunto alla persistenza . Leggendo un tutorial in rete sullo sviluppo di una J2EE Application che fa uso di un database MySql e Glassfish come application server .L'autore del tutorial dice di creare prima il database, di creare la connessione allo stesso nell' IDE , un unità di persistenza e uno schema di database. Di seguito un pezzetto di tutorial seguito dal link allo stesso.

    ''.....Ora che la connessione è stata creata torniamo a visualizzare la lista dei progetti e clicchiamo con il tasto destro sul progetto MyFirstJee-ejb poi su New->Other.
    Nella finestra di dialogo selezioniamo la categoria persistence e dalla finestra di destra la voce Database Schema.
    Chiamiamo il nostro schema come preferiamo, nel mio caso mySchema, e clicchiamo su next, nella finestra successiva selezioniamo la connessione creata in precedenza ed andiamo avanti.
    Ora vi verrà chiesto quali tabelle vogliamo aggiungere allo schema, nel nostro caso ne abbiamo solo una, selezioniamola, clicchiamo su add e quindi su finish.
    Il file schema è stato creato nel nodo configuration files del nostro modulo ejb.
    Il prossimo passo è la creazione di una persistence unit ovvero un’ unità inglobata nell’application server che si occuperà di gestire la persistenza dei dati sul db e l’accesso condiviso in maniera completamente automatica.
    Clicchiamo con il tasto destro sul progetto MyFirstJee-ejb poi su New->Persistence Unit, nella finestra di dialogo lasciamo il nome e la libreria di defualt e settiamo la voce Table generation strategy a none, ovvero diciamo alla persistence unit di non creare le tabelle ogni volta che viene eseguita l’applicazione ma di non generare le tabelle visto che non ne abbiamo necessità.
    Prima di finire dal menu a tendina DataSource clicchiamo su new data source e chiamiamolo myfirstjeeconnection scegliendo la connessione al nostro db.
    Cliccando su finish noterete che quello che abbiamo fatto non è stato altro che scrivere un file XML di configurazione che servirà a dire all’application server come gestire le operazioni sul database e con quale libreria di persistenza, noterete in basso una spunta “Include all entities classes in …”: questa specifica che tutti gli Entity Beans che andremmo a creare saranno gestiti dall’unità di persistenza.
    ......."

    ( http://www.toforge.com/2009/04/java-enterprise-tutorial-getting-started-parte-1/ )

    Il mio quesito è:
    A che serve creare un "database schema" all'interno del progetto? Non è sufficiente creare solo l'unità di "persistenza.xml ".


    Caro Alessandro lo so che i miei dubbi sono tanti ma venendo da php e avendo studiato Java EE solo all'università (5 anni fa, non esisteva nemmeno la specifica EJB se non erro ) puoi capirmi.
    Sicuramente le tue risposte serviranno a tanti che come me si trovano in difficoltà .
  • Re: J2EE

    Ciao, posso dirti che ti capisco perfettamente. Allora proviamo a fare un pò di ordine nelle idee.
    Quando devi realizzare un applicazione J2EE non è sufficiente conoscere come si realizza una servlet,jsp o EJB, è fondamentale capire come utilizzarli per realizzare l'idea progettuale che hai.
    Adesso nel nostro caso possiamo dire che nei progetti web J2EE ci sono alcuni punti fissi, da un punto di vista architetturale, comuni a tutte le applicazioni ben fatte. Sto parlando dei seguenti aspetti:

    - Pattern MVC (Model View Controller)
    - Architettura a layer

    Il pattern MVC definisce quindi come deve essere la struttura portante della tua applicazione:

    1- Model.
    Il modello, ovvero le classi che rappresentano il dominio dei dati. Ad esempio immagina di
    di realizzare un sistema web tipo quello di repubblica, entità come Articolo o News fanno
    parte del tuo dominio dei dati e per esse realizzerai ad esempio le classi Articolo e News.

    2. View (Vista). Con View si intende la modalità di presentazione dei dati . Nel caso di
    applicazioni J2EE sono rappresentate da pagine JSP. E' importante capire che in pagine JSP
    dobbiamo inserire solo ciò che riguarda la presentazione dei dati che rappresentano la risposta
    a seguito della richiesta di un client, nessuna logica di elaborazione dovrebbe essere inserita
    in una pagina JSP. Una pagina JSP può rappresentare,ad esempio, un form per l'inserimento
    dei dati o una lista di record risultato di una ricerca.

    3.Controller. Il controller è quel modulo, nel nostro caso una servlet, responsabile della ricezione
    delle richieste http provenienti dal client e della successiva azione da intraprendere per la loro
    gestione.

    Architettura a layer

    Quando realizzi un'applicazione web J2EE hai sempre almeno questi layer dal punto di vista software:

    - Presentazione (tutto ciò che riguarda la formazione e la presentazione dei dati)
    - Business Logic ( tutto ciò che riguarda logica di elaborazione)
    - DAO (tutto ciò che riguarda gli aspetti legati all'accesso ad un db)

    Con riferimento a quanto mi hai scritto ,la mia risposta riguardo al riferimento del session bean
    è che in una jsp non dovrebbe proprio essere presente una porzione di codice che lo richiama.
    In questa risposta non riesco purtroppo a scriverti un esempio di quanto esposto ma se vuoi posso poi darti uno zip con una piccola applicazione che illustra quello che ho scritto.

    Per quanto riguarda la tecnologia EJB , e più precisamente JPA, con il file persistence.xml tu definisci verso quale db(datasource) e all'interno di quale schema vuoi mappare le tue entities verso le tabelle.
    Creare uno schema può essere necessario se sul db non ne è presente uno che vuoi utilizzare nel tuo progetto. Ad esempio installi un server db (esempio postgres) ti trovi solo gli schema di default e desideri crearne uno per la tua applicazione.Un esempio di persistence.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistenc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instanc" xsi:schemaLocation="http://java.sun.com/xml/ns/persistenc http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
    <persistence-unit name="MyPersitenceUnit">
    <jta-data-source>jdbc/MyDb</jta-data-source>
    <properties>
    <property name="openjpa.jdbc.Schema" value="MySchema" /></properties>
    </persistence-unit>
    </persistence>

    Dove jdbc/MyDb è il JNDI name definito nella creazione del datasource nel tuo application server,
    MySchema è lo schema del db dove risiedono le tue tabelle.All'interno di un session bean recuperi l'EntityManager per questa persistence unit nel seguente modo:

    @PersistenceContext(unitName="MyPersitenceUnit")
    private EntityManager entityManager;

    e gestisci la tua persistenza.... . Per adesso mi fermo qui ma ti suggerirei di andare per gradi,capire bene prima come utilizzare jsp,servlet,classi di modello e classi di logica di business per la tua architettura e poi spostarti verso EJB e JPA per non appesantirti con tante nozioni tutte insieme.Spero di essere stato comprensibile ho voluto farti un pò una prima panoramica.
  • Re: J2EE

    Lo so, ho messo tanta carne a cuocere e il tuo file zippato mi farebbe comodo per capire come muovermi.

    Riguardo la mia voglia di reperire il riferimento al session bean direttamente dalla jsp ti spiego da dove nasce questa mia esigenza tramite il progettino-tutorial che vorrei realizzare . Tu puoi aiutarmi a capire in che modo sbaglio ad utilizzare i pezzi di J2EE seguendo come ho intezione di operare.


    L'applicazione è una semplificata agenda web in cui l' utente una volta loggato può registrare appuntamenti o prendere visione degli stessi.Di un utente interessa nome, cognome, user e pass .Di un appuntamento interessa solo data,ora e descrizione.

    Seguendo il pattern MVC ti dico come disegnerei la J2EE Agenda

    Modello
    Utente.java(BeanEntità)
    Appuntamento(BeanEntità): associazione 1:N con Utente
    SessionManager(BeanSession Statefull ):Ha il compito di mantenere una variabile di tipo Utente una voltache che l'utente effettua il login.
    InterfacciaDB(SessionBean stateless):Ha il compito di accedere al db utilizzando un EntityManager

    Vista
    index.jsp:Contiene il un form di login
    home.jsp: Mostra le funzionalità all'utente loggato (inserisci appuntamento e visualizza appuntamenti) Per capire se l'utente è loggato avevo intenzione di interpellare il SessionManager (da qui la domanda che ti avevo posto riguardo la possibilità di accedere al SessionBean direttamente da jsp)
    appuntamenti.jsp: mostra tutti gli appuntamenti memorizzati nella richiesta dalla servlet
    inseirsciapp.jps: mostra un form per inserire un nuovo appuntamento

    Controller
    Logger: Servlet , chiamata da index.jsp, che controlla le credenziali dell'utente che si logga ( tramite bean (InterfacciaDB) e tramite bean SessionManager setta la Utente.
    Action:Servlet chiamata da home.jsp e da inserisciapp il cui compito è capire quale funzionalità viene scelta dall'utente (nuovo appuntamento o lista degli stessi).Nel primo caso tramite InterfacciaDB inserirà nuovo il nuovo utente o nel secondo caso reperirà tutti gli appuntamento dal DB inserendoli nell'oggetto request e facendo un forward a appuntamenti.jsp


    Alessandro dimmi se il disegno è fattibile , (avrei potuto gestire la sessione utente direttamente nella sessione http ma volevo provare a far funzionare tutte le tipologie di bean ) o se devo cambiare strada.
  • Re: J2EE

    Ciao, ok sei sulla buona strada, la tua idea ha solo bisogno di qualche correzione.Mi sono permesso di buttare giù lo scheletro della tua applicazione Agenda con
    una possibile implementazione del pattern MVC.Purtroppo non riesco ad allegare mi rifiuta
    molte estensioni come war,zip e java, ti scrivo i sorgenti un pò alla volta.
    Un esempio alcune volte
    può chiarire più di tante parole.La specifica servlet che ho utilizzato è la 2.5 ed il server GlassFish 3. In sintesi ho realizzato una demo di login in cui le pagine sono protette attraverso un controllo in sessione della presenza dell'utente autenticato da
    loro stesse effettuato.
    Per realizzare le jsp non ho utilizzato scriptlet ma JSTL (java standard tag library) e l'expression language (vedrai espressioni del tipo ${...} ).Ho definito i seguenti package:

    agenda.controller

    Con la classe ServletController che definisce il controller
    
    package agenda.controller;
    
    import java.io.IOException;
    import java.util.HashMap;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletConfig;
    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 agenda.actions.Action;
    import agenda.actions.LogOutAction;
    import agenda.actions.LoginAction;
    
    /**
     * Servlet implementation class ServletController
     */
    @WebServlet("/*")
    public class ServletController extends HttpServlet{
    	
    	private static final long serialVersionUID = 1L;
    
        /**
         * Hashmap utilizzata dal controller per capire
         * quale action deve eventualmente gestire la request
         */
    	private HashMap<String,Action> actionsMapping = new HashMap<String,Action>();
    	
    	public void init(ServletConfig config) throws ServletException {
    		
    		actionsMapping.put("login", new LoginAction("home.jsp","error.jsp"));
    		actionsMapping.put("logout", new LogOutAction("login.jsp","error.jsp"));
    	}
    
    	
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		processRequest(request, response);
    	}
    
    	
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		processRequest(request, response);
    	}
    
    	/**
    	 * Metodo per la gestione della request http
    	 * @param request
    	 * @param response
    	 * @throws IOException
    	 * @throws ServletException
    	 */
    	private void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException,ServletException {
    		
    
    		RequestDispatcher dispatcher = null;
    					
    		String uri = request.getRequestURI();
    		
    		/*La richiesta riguarda una jsp?*/
    		if(uri.toLowerCase().endsWith("jsp")){
    		
    		   /*Recupero delle parti dell'url*/	
    		   String[] uriTokens = request.getRequestURI().split("/");
    		   /*Recupero nome della pagina jsp*/	
    		   String jspPart = uriTokens[uriTokens.length-1];
    			
    		   /*Visualizzazione della pagina*/
    		   dispatcher = request.getRequestDispatcher("/"+jspPart);
    		   dispatcher.forward(request, response);
    		   
    		}else/*La richesta è diretta verso una action?*/
    			 if(uri.toLowerCase().endsWith(".do")){
    		
    				/*Recupero delle parti dell'url*/
    				String[] uriTokens = request.getRequestURI().split("/");
    				/*Recupero nome della action*/
    				String actionPart = uriTokens[uriTokens.length-1];
    				
    				/*Estrazione oggetto action*/
    			    Action action = actionsMapping.get(
    			    		actionPart.replace(".do", ""));
    			    /*Esecuzione action*/
    			    action.execute(request, response);
    			
    	    
    		}else{
    			   /*Se l'url non identifica una jsp oppure una action allora ritorno su login*/
    			   dispatcher = request.getRequestDispatcher("/login.jsp");
    			   
    			   dispatcher.forward(request, response);
    		}
    	}
    }
    
    
    Non voglio che tutta la logica sia presente all'interno del controller, le azioni da intraprendere
    saranno gestite da classi specifiche, il controller sarà in grado di capire di volta in volta quale
    action deve gestire la richiesta.Ho definito le classi LoginAction (gestisce il login) e LogOutAction( effettua il logout eliminando dalla sessione l'utente) che implementano l'interfaccia Action che modella il concetto di action.

    agenda.actions
    package agenda.actions;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * Definisce il concetto di action,
     * una action è una azione che viene decisa
     * dal controller in base alla request http
     * ricevuta
     */
    public interface Action {
        void execute(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException;
    }
    package agenda.actions;
    
    import java.io.IOException;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import agenda.model.Utente;
    
    public class LoginAction implements Action {
    
    	private String page;
    	private String errorPage;
    	
    	
    	public LoginAction(String page,String errorPage){
    		this.page = page;
    		this.errorPage = errorPage;
    	}
    	
    	@Override
    	public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    	
    		String username = request.getParameter("username");
    		String password = request.getParameter("password");
    		
    		RequestDispatcher dispatcher = null;
    		
    		/*Come dimostrazione se l'utente
    		 * inserisce username=a e password=b
    		 * allora il login ha successo altrimenti no*/
    		
    		if(username.equals("a") && password.equals("b")){
    		  
    		  /*login*/
    		  Utente utente = new Utente();
    		  
    		  HttpSession session = request.getSession();
    		  session.setAttribute("utente", utente);
    		  
    		  dispatcher = request.getRequestDispatcher("/"+page);
    		  
    		}else{
    		 /*no login*/
    		  request.setAttribute("errorMessage", "Credenziali non valide");
    		  dispatcher = request.getRequestDispatcher("/"+errorPage);
    		  
    		}
    		
    
    		dispatcher.forward(request, response);
    	
    	
    	}
    	
    
    }
    
    
    package agenda.actions;
    
    import java.io.IOException;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    public class LogOutAction implements Action {
    
    	private String page;
    	private String errorPage;
    	
    	
    	public LogOutAction(String page,String errorPage){
    		this.page = page;
    		this.errorPage = errorPage;
    	}
    	
    	@Override
    	public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    		HttpSession session = request.getSession();
    		session.removeAttribute("utente");
    		
    		RequestDispatcher dispatcher = request.getRequestDispatcher("/"+page);
    		
    		dispatcher.forward(request, response);
    		
    	}
    	
    
    }
    
    
    agenda.model

    Il package per le classi di modello Utente e Appuntamento

    Per la view le jsp:

    login.jsp
    
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        	               "http://www.w3.org/TR/html4/loose.dtd">
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <c:choose>
    <c:when test="${empty sessionScope.utente}">
    <html>
      <head>
        	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        	<title>Agenda Login</title>
      </head>
      <body>
        <h1>Login</h1>
        <form action="login.do" method="post">
        
         Username
         <input value="" name="username" type="text">
         Password
         <input value="" type="password" name="password">
         <input type="submit" value="Login">
        
        </form>
      </body>
    </html> 
    </c:when>
    <c:otherwise>
     <c:redirect url="/home.jsp"/>
    </c:otherwise>
    </c:choose>
    
    
    home.jsp
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        	               "http://www.w3.org/TR/html4/loose.dtd">
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    
    <c:choose>
    <c:when test="${not empty sessionScope.utente}">
    <html>
      <head>
        	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        	<title>Agenda Home</title>
      </head>
      <body>
        <h1>Inserisci Appuntamento</h1>
        <h1>Visualizza Appuntamento</h1>
        <a href="${pageContext.request.contextPath}/logout.do">Logout</a>
      </body>
    </html> 
    </c:when>
    <c:otherwise>
     <c:redirect url="/login.jsp"/>
    </c:otherwise>
    </c:choose>
    error.jsp
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        	               "http://www.w3.org/TR/html4/loose.dtd">
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <html>
      <head>
        	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        	<title>Agenda Error</title>
      </head>
      <body>
        <h1>Errore</h1>
        <h3>${requestScope.errorMessage}</h3>
      </body>
    </html> 
    web.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>Agenda</display-name>
      
      <servlet>
       <servlet-name>Controller</servlet-name>
       <servlet-class>agenda.controller.ServletController</servlet-class>
      </servlet>
      
      <servlet-mapping>
       <servlet-name>Controller</servlet-name>
       <url-pattern>*.do</url-pattern>
      </servlet-mapping>
      
      <welcome-file-list>
        <welcome-file>login.jsp</welcome-file>
      </welcome-file-list>
      
    </web-app>

    Prova a dare un'occhiata al codice,spero ti sia di aiuto, è poco ma racchiude parti importanti. Se non hai difficoltà con questi primi concetti poi passiamo vedere eventualmente la business logic e persistenza.
  • Re: J2EE

    Innanzitutto ti ringrazio per l'interesse che mi stai dedicando. Tornando al thread, temo che tu stia utilizzando un framework (Struts o Spring) per implementare l'agenda , ma io questi framework non li ho ancora presi inconsiderazione non avendo ancora solide basi di taglib e in generale sulla tecnologia J2EE. Il codice che hai scritto è chiaro dal punto di vista dell'organizzazione dell'applicazione ma la sintassi, in particolare l'uso dei tag custom, non la comprendo molto.
    Attualmente mi aiuterebbe molto se mi guidassi allo scrittura di codice senza utilizzo di framework MVC (almeno per ora).


    Quello che ho disegnato io, è implementabile o ci sono degli errori dal punto di vista dell'uso della tecnologia J2EE. Cosa non ti convince o non è fattibile?
  • Re: J2EE

    Ciao, no ti assicuro che non c'e' nessun framework, avrai notato similitudini perchè quelli che hai citato sono basati su MVC. Ho utilizzato gli aspetti fondamentali della tecnologia servlet(JSTL ed EL). Si diciamo che puoi realizzare un applicazione in qualsiasi forma compreso l'invocazione di session bean in una jsp, cosi come qualsiasi codice java all'interno di essa.Il problema è che non ti abitui fin da subito a portare la mente verso una buona progettazione, comunque sono scelte ognuno sceglie poi il percorso di studio che sente migliore. Non posso dirti che ci sono degli errori se non da un punto di vista di qualità di progettazione e architettura,quindi tecnicamente non sono sbagliate, nel senso che se le implementi dovrebbero darti il risultato desiderato. Comunque si quando hai quesiti chiedi pure, non appena accedo al forum ti rispondo volentieri.
  • Re: J2EE

    Faccio così, mi leggo qualkosa su JSTL ed EL e nel frattempo implemento un pò le classi che ho disegnato. Quando avrò dei problemi li posto qui. A tutorial terminato metto a disposizione il tutto per chi è interessato
  • Re: J2EE

    Salve a tutti i visitatori del thread. Proseguendo nello studio di JEE mi sono imbattuto in un articolo di un autore il cui scopo è quello di spiegare il funzionamento dei session bean statefull.
    Ecco cosa scrive l'autore.

    " Per comprendere la differenza rispetto ai session bean di tipo stateless, supponiamo di voler implementare un EJB in grado di contare il numero di volte che l’utente richiede una determinata servlet all’interno di una sessione utente."

    L'esempio usa il seguente bean semplice semplice
    
    @Stateful
    public class MioSFSB implements MiaIntSFSBLocal
    {
    private int contaa;
     
    public MioSFSB()
    {
    contaa=0;
    }
     
    @Override
    public int conta()
    {
    return contaa++;
    }
    }
    

    E la servlet come controller altrettanto semplice
    
    public class MiaServletSFSBLocal extends HttpServlet
    {
    private static final long serialVersionUID = 1L;
     
    @EJB
    private MiaIntSFSBLocal miobean;
     
    public MiaServletSFSBLocal()
    {
    }
     
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
    PrintWriter out = response.getWriter();
    out.println( "<html><body>"+miobean.conta()+"</body></html>" );
    out.close();
    }
     
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
    }
    }
    
    Il punto è questo. A mio avviso il risultato ottenuto è la stampa del numero di volte globale che gli utenti chiamano il bean e non il numero di volte che ogni singolo utente effettua la chiamata al bean.

    La mia motivazione è la seguente:
    Alla prima chiamata di MiaServlet , il servlet conteiner creare una istanza di MiaServlet. Nel caricare MiaServlet , all'istruzione @EJB viene creato, nell'EJB conteiner, una nuova istanza di SessionBean il cui riferimento è posto nella viariabile istanza di MiaServlet.
    Successivamente viene chiamato il metodo service() e stampato il valore del metodo conta().
    Ora, alle successive richieste MiaServlet da parte di nuovi utenti , il bean di sessione chiamato è sempre lo stesso poichè è quello istanziato alla prima richiesta, e quindi come risultato non avremo la stampa di conta per ogni utente ma degli utenti globalmente.
    (testando il codice il risultato è quello descritto)

    Per poter ottenere quello che vuole l'autore, invece di usare l'annotazione @EJB bisognava usare il
    metodo di lookup() all'interno del metodo service() in questo modo viene creato un nuovo session bean statefull per ogni richiesta e memorizzato in sessione (se non esiste già).


    Cosa ne pensi Alessandro, è giusta l'analisi o sono ancora in alto mare ?
  • Re: J2EE

    Ciao, si hai ragione dovrebbe andare come hai spiegato,infatti di una servlet esiste una sola istanza ed i suoi metodi vengono eseguiti in thread distinti per diversi utenti.Ogni esecuzione del metodo service utilizza la stessa varibile ejb inizializzata in fase di creazione ed istanziazione della servlet che può avvenire anche in fase di deploy.Per avere uno stateful per sessione utente bisogna richiedere l'istanza all'interno dei metodi della servlet come ad esempio il metodo service da te evidenziato.
  • Re: J2EE

    Bene allora inizio a far luce su JEE.
    Tanto per fare una prova, in quanto curioso, ho sostituito il session bean statefull con uno stateless che fa esattamente la stessa cosa.
    Beh, il risultato è identico a prima, cioè mi viene stampato il valore di conta incrementato da tutti gli utenti globalmente.
    Questo comportamento già evidenziato all'inizio del thread continuo a notarlo....può essere dovuto al fatto che sto facendo le mie prove il locale? e quindi viene scelto da pool sempre la stesso bean stateless?

    Il ciclo di vita del bean in questo caso è il seguente:

    Alla prima chiamata di MiaServlet , il servlet conteiner creare una istanza di MiaServlet. Nel caricare MiaServlet , all'istruzione @EJB viene reperito dal pool dell' EJB conteiner, una nuova istanza di SessionBean il cui riferimento è posto nella viariabile istanza di MiaServlet.
    Successivamente viene chiamato il metodo service() e stampato il valore del metodo conta().
    Ora essendo un bean stateless il bean viene riposto nel pool . Quando viene effettuata una nuova chiamata al metodo conta() il conteiner sceglie un istanza dal pool in maniera casuale. Ma anche se fosse scelto lo stesso bean di prima (coincidenza) lo stato dello stesso non viene resettato, cioè la variabile intera conta non viene posta a zero?

    Forse ho tradotto male io le specifiche Sun sui stateless bean che recitano:

    "A stateless session bean does not maintain a conversational state with the client. When a client
    invokes the methods of a stateless bean, the bean’s instance variables may contain a state specific
    to that client, but only for the duration of the invocation. When the method is finished, the
    client-specific state should not be retained. Clients may, however, change the state of instance
    variables in pooled stateless beans, and this state is held over to the next invocation of the
    pooled stateless bean. Except during method invocation, all instances of a stateless bean are
    equivalent, allowing the EJB container to assign an instance to any client. That is, the state of a
    stateless session bean should apply accross all clients.
    Because stateless session beans can support multiple clients, they can offer better scalability for
    applications that require large numbers of clients. Typically, an application requires fewer
    stateless session beans than stateful session beans to support the same number of clients."
  • Re: J2EE

    Ciao. Il fatto è che la dependency injection che porta alla valorizzazione della variabile del session bean della servlet con una sua istanza, viene eseguita una sola volta al momento della creazione da parte dell'application servlet dell'unica istanza della servlet. Quindi il session non viene mai rilasciato e soprattutto non viene più richiesto all'application server perchè l'nizializzazione della variabile di istanza della servlet non più viene rieseguita in quanto una servlet, giustamente, non vede la sua istanza ricreata ad ogni nuova chiamata.Il risultato che ottieni è giustamente l'utilizzo dello stesso session bean.Non a caso si dice sempre di prestare attenzione alle variabili a livello di servlet proprio perchè condivise da diversi thread.Credo che questo quesito facesse parte anche della tua prima domanda in questo post ma nella mia risposta avevo dimenticato questa precisazione.Se invece facciamo in modo che il session bean venga sempre richiesto ,ovvero che il suo lookup venga eseguito(mettendo ad esempio il relativo codice in un metodo della servlet) ,dovresti sperimentare proprio il funzionamento dell'application server relativamente al ciclo di vita di un session bean.
Devi accedere o registrarti per scrivere nel forum
30 risposte