EJB - Stateful Bean
Un bean di sessione con stato è un tipo di bean enterprise, che preserva lo stato di conversazione con il client. Un bean di sessione con stato secondo il suo nome mantiene lo stato del client associato nelle sue variabili di istanza. EJB Container crea un bean di sessione stateful separato per elaborare ciascuna richiesta del client. Non appena l'ambito della richiesta è terminato, il bean di sessione statelful viene distrutto.
Passaggi per creare EJB con stato
Di seguito sono riportati i passaggi necessari per creare un bean stateful:
Creare un'interfaccia remota / locale che esponga i metodi aziendali.
Questa interfaccia verrà utilizzata dall'applicazione client EJB.
Utilizzare l'annotazione @Local se il client EJB si trova nello stesso ambiente in cui è necessario distribuire il bean di sessione EJB.
Utilizzare l'annotazione @Remote se il client EJB si trova in un ambiente diverso in cui è necessario distribuire il bean di sessione EJB.
Crea un bean di sessione con stato, implementando l'interfaccia precedente.
Usa l'annotazione @Stateful per indicare che è un bean stateful. EJB Container crea automaticamente le relative configurazioni o interfacce richieste leggendo questa annotazione durante la distribuzione.
Interfaccia remota
import javax.ejb.Remote;
@Remote
public interface LibraryStatefulSessionBeanRemote {
//add business method declarations
}
Stateful EJB
@Stateful
public class LibraryStatefulSessionBean implements LibraryStatefulSessionBeanRemote {
//implement business method
}
Applicazione di esempio
Creiamo un'applicazione EJB di prova per testare EJB con stato.
Passo | Descrizione |
---|---|
1 | Creare un progetto con un nome EjbComponent sotto un pacchetto com.tutorialspoint.stateful come spiegato nel capitolo EJB - Crea applicazione . È anche possibile utilizzare il progetto creato nel capitolo EJB - Crea applicazione come tale per questo capitolo per comprendere i concetti di EJB con stato. |
2 | Creare LibraryStatefulSessionBean.java e LibraryStatefulSessionBeanRemote come spiegato nel capitolo EJB - Crea applicazione . Mantieni il resto dei file invariato. |
3 | Pulisci e crea l'applicazione per assicurarti che la logica aziendale funzioni secondo i requisiti. |
4 | Infine, distribuisci l'applicazione sotto forma di file jar su JBoss Application Server. JBoss Application Server verrà avviato automaticamente se non è ancora stato avviato. |
5 | Ora crea il client EJB, un'applicazione basata su console nello stesso modo come spiegato nel capitolo EJB - Crea applicazione sotto l'argomentoCreate Client to access EJB. |
EJBComponent (modulo EJB)
LibraryStatefulSessionBeanRemote.java
package com.tutorialspoint.stateful;
import java.util.List;
import javax.ejb.Remote;
@Remote
public interface LibraryStatefulSessionBeanRemote {
void addBook(String bookName);
List getBooks();
}
LibraryStatefulSessionBean.java
package com.tutorialspoint.stateful;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.Stateful;
@Stateful
public class LibraryStatefulSessionBean implements LibraryStatefulSessionBeanRemote {
List<String> bookShelf;
public LibraryStatefulSessionBean() {
bookShelf = new ArrayList<String>();
}
public void addBook(String bookName) {
bookShelf.add(bookName);
}
public List<String> getBooks() {
return bookShelf;
}
}
Non appena distribuisci il progetto EjbComponent su JBOSS, osserva il registro jboss.
JBoss ha creato automaticamente una voce JNDI per il nostro bean di sessione - LibraryStatefulSessionBean/remote.
Useremo questa stringa di ricerca per ottenere un oggetto business remoto di tipo - com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote
Output del registro di JBoss Application Server
...
16:30:01,401 INFO [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
LibraryStatefulSessionBean/remote - EJB3.x Default Remote Business Interface
LibraryStatefulSessionBean/remote-com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote - EJB3.x Remote Business Interface
16:30:02,723 INFO [SessionSpecContainer] Starting jboss.j2ee:jar=EjbComponent.jar,name=LibraryStatefulSessionBean,service=EJB3
16:30:02,723 INFO [EJBContainer] STARTED EJB: com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote ejbName: LibraryStatefulSessionBean
16:30:02,731 INFO [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
LibraryStatefulSessionBean/remote - EJB3.x Default Remote Business Interface
LibraryStatefulSessionBean/remote-com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote - EJB3.x Remote Business Interface
...
EJBTester (client EJB)
jndi.properties
java.naming.factory.initial = org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs = org.jboss.naming:org.jnp.interfaces
java.naming.provider.url = localhost
Queste proprietà vengono utilizzate per inizializzare l'oggetto InitialContext del servizio di denominazione java.
L'oggetto InitialContext verrà utilizzato per cercare il bean di sessione stateful.
EJBTester.java
package com.tutorialspoint.test;
import com.tutorialspoint.stateful.LibraryStatefulSessionBeanRemote;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class EJBTester {
BufferedReader brConsoleReader = null;
Properties props;
InitialContext ctx;
{
props = new Properties();
try {
props.load(new FileInputStream("jndi.properties"));
} catch (IOException ex) {
ex.printStackTrace();
}
try {
ctx = new InitialContext(props);
} catch (NamingException ex) {
ex.printStackTrace();
}
brConsoleReader =
new BufferedReader(new InputStreamReader(System.in));
}
public static void main(String[] args) {
EJBTester ejbTester = new EJBTester();
ejbTester.testStatelessEjb();
}
private void showGUI() {
System.out.println("**********************");
System.out.println("Welcome to Book Store");
System.out.println("**********************");
System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice: ");
}
private void testStatelessEjb() {
try {
int choice = 1;
LibraryStatefulSessionBeanRemote libraryBean =
LibraryStatefulSessionBeanRemote)ctx.lookup("LibraryStatefulSessionBean/remote");
while (choice != 2) {
String bookName;
showGUI();
String strChoice = brConsoleReader.readLine();
choice = Integer.parseInt(strChoice);
if (choice == 1) {
System.out.print("Enter book name: ");
bookName = brConsoleReader.readLine();
Book book = new Book();
book.setName(bookName);
libraryBean.addBook(book);
} else if (choice == 2) {
break;
}
}
List<Book> booksList = libraryBean.getBooks();
System.out.println("Book(s) entered so far: " + booksList.size());
int i = 0;
for (Book book:booksList) {
System.out.println((i+1)+". " + book.getName());
i++;
}
LibraryStatefulSessionBeanRemote libraryBean1 =
(LibraryStatefulSessionBeanRemote)ctx.lookup("LibraryStatefulSessionBean/remote");
List<String> booksList1 = libraryBean1.getBooks();
System.out.println(
"***Using second lookup to get library stateful object***");
System.out.println(
"Book(s) entered so far: " + booksList1.size());
for (int i = 0; i < booksList1.size(); ++i) {
System.out.println((i+1)+". " + booksList1.get(i));
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}finally {
try {
if(brConsoleReader !=null) {
brConsoleReader.close();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
}
EJBTester esegue le seguenti attività:
Carica le proprietà da jndi.properties e inizializza l'oggetto InitialContext.
Nel metodo testStatefulEjb (), la ricerca jndi viene eseguita con il nome "LibraryStatefulSessionBean / remote" per ottenere l'oggetto business remoto (stateful ejb).
Quindi all'utente viene mostrata l'interfaccia utente di un negozio della biblioteca e gli viene chiesto di inserire una scelta.
Se l'utente immette 1, il sistema richiede il nome del libro e salva il libro utilizzando il metodo addBook () del bean di sessione stateful. Session Bean sta memorizzando il libro nella sua variabile di istanza.
Se l'utente immette 2, il sistema recupera i libri utilizzando il metodo getBooks () del bean di sessione stateful ed esce.
Quindi viene eseguita un'altra ricerca jndi con il nome "LibraryStatefulSessionBean / remote" per ottenere nuovamente l'oggetto di business remoto (EJB stateful) e l'elenco dei libri viene eseguito.
Eseguire il client per accedere a EJB
Individua EJBTester.java in Esplora progetti. Fare clic con il tasto destro sulla classe EJBTester e selezionarerun file.
Verifica il seguente output nella console Netbeans:
run:
**********************
Welcome to Book Store
**********************
Options
1. Add Book
2. Exit
Enter Choice: 1
Enter book name: Learn Java
**********************
Welcome to Book Store
**********************
Options
1. Add Book
2. Exit
Enter Choice: 2
Book(s) entered so far: 1
1. Learn Java
***Using second lookup to get library stateful object***
Book(s) entered so far: 0
BUILD SUCCESSFUL (total time: 13 seconds)
Eseguire nuovamente il client per accedere a EJB
Individua EJBTester.java in Esplora progetti. Fare clic con il tasto destro sulla classe EJBTester e selezionarerun file.
Verificare il seguente output nella console Netbeans.
run:
**********************
Welcome to Book Store
**********************
Options
1. Add Book
2. Exit
Enter Choice: 2
Book(s) entered so far: 0
***Using second lookup to get library stateful object***
Book(s) entered so far: 0
BUILD SUCCESSFUL (total time: 12 seconds)
L'output mostrato sopra indica che per ogni ricerca, viene restituita un'istanza EJB con stato differente.
L'oggetto EJB con stato mantiene il valore solo per una singola sessione. Come nella seconda manche, non otteniamo alcun valore per i libri.