|
EJB 3 - Les Entreprise Java Bean version 3 (JavaBeans)
5.EJB 3 en pratique
Nous reprenons l’exemple établi dans l’essentiel
EJB 2&2.1. Cela permet de comparer les deux spécifications
mais également les deux méthodes utilisées
(xDoclet + ant dans l’ancien cas) ; ant seulement dans le
nouveau (pour le packaging).
5.1.1.Session Bean
Pour le session bean, nous avons créé l’interface
distante et la classe du bean.
Voici le code de l’interface distante :
package
com.society.stockmanager3.sessions.interfaces;
import
javax.ejb.Remote;
import
com.society.stockmanager3.entities.beans.Product;
import
com.society.stockmanager3.entities.beans.ProductFamily;
import
com.society.stockmanager3.exceptions.NotFindException;
/**
*
Remote interface for StorageService.
*/
@Remote
public
interface RemoteStorage
{
/**
*
Business method
*/
public
java.lang.String sayHello( );
/**
*
Business method
*
@throws NotFindException
*/
public
java.lang.Integer[] getAllProductIds( ) throws NotFindException;
/**
*
Business method
*/
public
java.util.Collection<Product> getAllProduct( )
throws
NotFindException;
/**
*
Business method
*/
public
java.util.Collection<ProductFamily> getAllProductFamily( );
/**
*
Business method
*/
//
public void addProduct( com.society.stockmanager.vo.ProductData
datas,java.lang.String codeFamily );
/**
*
Business method
*/
public
void removeProduct( java.lang.Integer productId );
/**
*
Business method
*/
public
void addProductFamily( java.lang.String code,java.lang.String
designation );
public
void addProduct(Product product);
/**
*
Business method
*/
public
void removeProductFamily( java.lang.String code );
/**
*
Business method
*/
//
public void addProvider( com.society.stockmanager.vo.ProviderData
datas,java.lang.Integer cityId,java.util.Collection productIds );
/**
*
Business method
*/
public
void removeProvider( java.lang.Integer providerId );
/**
*
Business method
*/
public
void addCountry( java.lang.Integer countryId,java.lang.String name );
/**
*
Business method
*/
public
void removeCountry( java.lang.Integer countryId );
/**
*
Business method
*/
public
void addCity( java.lang.Integer cityId,java.lang.String
name,java.lang.Integer countryId );
/**
*
Business method
*/
public
void removeCity( java.lang.Integer cityId );
/**
*
Business method
*/
//
public com.society.stockmanager.vo.ProductFamilyData
findProductFamily( java.lang.String code );
/**
*
Business method
*/
public
java.util.Collection<Product> findProductByCountryId(
java.lang.Integer countryId );
}
Détails des annotations :
-
Remote : indique que l’interface est de type Remote (le
serveur d’application fera la liaison automatiquement avec les
différents bean implémentant cette interface)
Voici le code de l’interface locale :
package
com.society.stockmanager3.sessions.interfaces;
import
javax.ejb.Local;
import
com.society.stockmanager3.entities.beans.Product;
import
com.society.stockmanager3.entities.beans.ProductFamily;
import
com.society.stockmanager3.exceptions.NotFindException;
/**
*
Remote interface for StorageService.
*/
@Local
public
interface LocalStorage
{
/**
*
Business method
*/
public
void addProduct(Product product);
}
Détails des annotations :
-
Local : indique que l’interface est de type Locale (le
serveur d’application fera la liaison automatiquement avec les
différents bean implémentant cette interface)
Voici le code de la classe d’implémentation :
package
com.society.stockmanager3.sessions.beans;
import
java.util.Collection;
import
javax.ejb.Stateless;
import
javax.persistence.EntityManager;
import
javax.persistence.PersistenceContext;
import
com.society.stockmanager3.entities.beans.City;
import
com.society.stockmanager3.entities.beans.Country;
import
com.society.stockmanager3.entities.beans.Product;
import
com.society.stockmanager3.entities.beans.ProductFamily;
import
com.society.stockmanager3.entities.beans.Provider;
import
com.society.stockmanager3.exceptions.NotFindException;
import
com.society.stockmanager3.sessions.interfaces.LocalStorage;
import
com.society.stockmanager3.sessions.interfaces.RemoteStorage;
@Stateless
public
class StorageBean implements RemoteStorage, LocalStorage {
@PersistenceContext(unitName
= "stockManager")
protected
EntityManager em;
public
StorageBean() {
}
public
Collection<Product> findProductByCountryId(Integer countryId) {
return
em
.createQuery(
"select
p from Provider provider, IN(provider.products) p WHERE
provider.city.country.id = "
+
countryId.intValue()).getResultList();
}
public
Collection<Product> getAllProduct() throws NotFindException {
return
em.createQuery("from Product p").getResultList();
}
public
Collection<ProductFamily> getAllProductFamily() {
return
em.createQuery("from ProductFamily pf").getResultList();
}
public
String sayHello() {
return
"Hello";
}
public
Integer[] getAllProductIds() throws NotFindException {
Collection<Product>
allProducts = getAllProduct();
Integer[]
result = new Integer[allProducts.size()];
int
index = 0;
for
(Product product : allProducts) {
result[index]
= product.getId();
index++;
}
return
result;
}
public
void removeProduct(Integer productId) {
em.remove(em.find(Product.class,
productId));
}
public
void addProductFamily(String code, String designation) {
ProductFamily
productFamily = new ProductFamily();
productFamily.setName(designation);
em.persist(productFamily);
}
public
void removeProductFamily(String code) {
em.remove(em.find(ProductFamily.class,
code));
}
public
void removeProvider(Integer providerId) {
em.remove(em.find(Provider.class,
providerId));
}
public
void addCountry(Integer countryId, String name) {
Country
country = new Country();
country.setId(countryId);
country.setName(name);
em.persist(country);
}
public
void removeCountry(Integer countryId) {
em.remove(em.find(Country.class,
countryId));
}
public
void addCity(Integer cityId, String name, Integer countryId) {
City
city = new City();
city.setCountry(em.find(Country.class,
countryId));
city.setId(cityId);
city.setName(name);
em.persist(city);
}
public
void removeCity(Integer cityId) {
em.remove(em.find(City.class,
cityId));
}
public
void addProduct(Product product) {
em.persist(product);
}
}
Détails des annotations :
-
Stateless : spécifie que le type de l’EJB est
Stateless (session bean sans état)
-
PersistenceContext : permet d’indiquer une demande
d’injection automatique d’un objet de type
« EntityManager » permettant de gérer
des entity bean, directement dans la classe du bean lors de sa
création
-
unitName : définit le nom de l’unité
persistante à utiliser
5.1.2.Entity Bean
Dans cette partie, nous allons décrire les différents
bean entités (et les annotations) utilisés.
Country
Voici le code de l’entité Country :
package
com.society.stockmanager3.entities.beans;
import
java.io.Serializable;
import
javax.persistence.Entity;
import
javax.persistence.GeneratorType;
import
javax.persistence.Id;
import
javax.persistence.Table;
@Entity
@Table(name
= "COUNTRY")
public
class Country implements Serializable {
private
int id;
private
String name;
public
Country() {
}
public
Country(String name) {
this.name
= name;
}
@Id(generate
= GeneratorType.AUTO)
public
int getId() {
return
id;
}
public
void setId(int id) {
this.id
= id;
}
public
String getName() {
return
name;
}
public
void setName(String name) {
this.name
= name;
}
}
Voici le détail des annotations utilisées :
-
Entity : déclare que notre classe est de type entity
bean
-
Table : définit le nom de la table à rattacher à
notre entité
-
name : nom de la table à utiliser
-
Id : définit le champ persistant servant de clé
primaire
-
generate : attribut définissant le type de génération
à utiliser (ici « auto incrémenté »)
Remarque : l’utilisation d’un id auto
incrémenté obligé d’utiliser un type
« nombre » (entier, double …). Cela est
bien entendu lié à la base de données.
City
Voici le code de l’entité City :
package
com.society.stockmanager3.entities.beans;
import
java.io.Serializable;
import
javax.persistence.DiscriminatorColumn;
import
javax.persistence.Entity;
import
javax.persistence.GeneratorType;
import
javax.persistence.Id;
import
javax.persistence.Inheritance;
import
javax.persistence.JoinColumn;
import
javax.persistence.ManyToOne;
import
javax.persistence.Table;
@Entity
@Table(name
= "CITY")
public
class City implements Serializable {
protected
int id;
protected
String name;
protected
Country country;
public
City() {
}
public
City(String name) {
this.name
= name;
}
@ManyToOne(optional
= false)
@JoinColumn(name
= "countryId")
public
Country getCountry() {
return
country;
}
public
void setCountry(Country country) {
this.country
= country;
}
public
String getName() {
return
name;
}
public
void setName(String name) {
this.name
= name;
}
@Id(generate
= GeneratorType.AUTO)
public
int getId() {
return
id;
}
public
void setId(int id) {
this.id
= id;
}
}
Voici le détail des annotations utilisées :
-
ManyToOne : déclare un champ relationnel de type « many
to one » (N-1)
-
JoinColumn : définit le nom du champ qui sera utilisé
comme champ de jointure
-
name : attribut définissant le nom du champ
ProductFamily
Voici le code de l’entité ProductFamily :
package
com.society.stockmanager3.entities.beans;
import
java.io.Serializable;
import
javax.persistence.Entity;
import
javax.persistence.GeneratorType;
import
javax.persistence.Id;
import
javax.persistence.Table;
@Entity
@Table(name
= "PRODUCTFAMILY")
public
class ProductFamily implements Serializable {
protected
int id;
protected
String name;
public
ProductFamily() {
}
public
ProductFamily(String name) {
this.name
= name;
}
public
String getName() {
return
name;
}
public
void setName(String name) {
this.name
= name;
}
@Id(generate
= GeneratorType.AUTO)
public
int getId() {
return
id;
}
public
void setId(int id) {
this.id
= id;
}
@Override
public
String toString() {
return
name;
}
}
Product
Voici le code de l’entité Product :
package
com.society.stockmanager3.entities.beans;
import
java.io.Serializable;
import
java.util.Collection;
import
javax.persistence.Entity;
import
javax.persistence.GeneratorType;
import
javax.persistence.Id;
import
javax.persistence.ManyToMany;
import
javax.persistence.Table;
@Entity
@Table(name
= "PRODUCT")
public
class Product implements Serializable {
protected
int id;
protected
String name;
protected
Collection<Provider> providers;
public
Product() {
}
public
Product(String name) {
this.name
= name;
}
@ManyToMany
public
Collection<Provider> getProviders() {
return
providers;
}
public
void setProviders(Collection<Provider> providers) {
this.providers
= providers;
}
public
String getName() {
return
name;
}
public
void setName(String name) {
this.name
= name;
}
@Id(generate
= GeneratorType.AUTO)
public
int getId() {
return
id;
}
public
void setId(int id) {
this.id
= id;
}
}
Voici le détail des annotations utilisées :
-
ManyToMany : défini une relation ManyToMany (n-m) pour
le champ relationnel courant.
Provider
Voici le code l’entité Provider :
package
com.society.stockmanager3.entities.beans;
import
java.io.Serializable;
import
java.util.Collection;
import
javax.persistence.Entity;
import
javax.persistence.GeneratorType;
import
javax.persistence.Id;
import
javax.persistence.JoinColumn;
import
javax.persistence.ManyToMany;
import
javax.persistence.ManyToOne;
import
javax.persistence.Table;
@Entity
@Table(name
= "PROVIDER")
public
class Provider implements Serializable {
protected
int id;
protected
String name;
protected
String zipCode;
protected
String society;
protected
City city;
protected
Collection<Product> products;
public
Provider() {
}
public
Provider(String name) {
this.name
= name;
}
public
String getSociety() {
return
society;
}
public
void setSociety(String society) {
this.society
= society;
}
public
String getZipCode() {
return
zipCode;
}
public
void setZipCode(String zipCode) {
this.zipCode
= zipCode;
}
@ManyToOne(optional
= false)
@JoinColumn(name
= "cityId")
public
City getCity() {
return
city;
}
public
void setCity(City city) {
this.city
= city;
}
@ManyToMany(mappedBy="providers")
public
Collection<Product> getProducts() {
return
products;
}
public
void setProducts(Collection<Product> products) {
this.products
= products;
}
public
String getName() {
return
name;
}
public
void setName(String name) {
this.name
= name;
}
@Id(generate
= GeneratorType.AUTO)
public
int getId() {
return
id;
}
public
void setId(int id) {
this.id
= id;
}
}
Voici le détail des annotations :
-
ManyToMany : déclaration d’un champ relationnel de
type « Many to Many » (N-M)
-
mappedBy : définit le nom du champ persistant du
propriétaire de la relation (ici Product)
5.1.3.Message Driven Bean
Voici l’exemple d’un Message Driven Bean permettant
l’ajout d’un produit via un message JMS (ObjectMessage) :
package
com.society.stockmanager3.sessions.beans;
import
javax.annotation.EJB;
import
javax.ejb.ActivationConfigProperty;
import
javax.ejb.MessageDriven;
import
javax.jms.Message;
import
javax.jms.MessageListener;
import
javax.jms.ObjectMessage;
import
com.society.stockmanager3.entities.beans.Product;
import
com.society.stockmanager3.sessions.interfaces.LocalStorage;
@MessageDriven(activateConfig
=
{
@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination",
propertyValue="queue/StockManager/ProductAddQueue")
})
public
class ProductManageMessageBean
implements
MessageListener
{
@EJB
protected
LocalStorage storage;
public
ProductManageMessageBean() {
}
public
void onMessage(Message message) {
if(message
instanceof ObjectMessage) {
ObjectMessage
tmpMessage = (ObjectMessage)message;
try
{
Product
product = (Product) tmpMessage.getObject();
storage.addProduct(product);
System.out.println("New
product added : " + product);
}
catch(Exception
e) {
System.out.println("Can't add the product / cause : " +
e);
}
}
else
{
System.out.println("don't
know the type of message");
}
}
}
Voici le détail des nouvelles annotations :
-
MessageDriven : déclare un Message Driven Bean (à
partir de sa classe)
-
ActivationConfigProperty
-
propertyName : nom de la propriété
-
propertyValue : valeur de la propriété à
affecter
-
EJB : injection automatique lié à un EJB
(instanciation automatique)
5.1.4.Clients
Client console
Voici l’exemple d’un client console :
package
com.society.stockmanager3.clients;
import
javax.naming.Context;
import
javax.naming.InitialContext;
import
com.society.stockmanager3.sessions.interfaces.RemoteStorage;
public
class StorageClient {
public
static void main(String[] args) {
try
{
Context
ctx = new InitialContext();
RemoteStorage
storageService = (RemoteStorage) ctx
.lookup(RemoteStorage.class.getName());
System.out.println(storageService.sayHello());
storageService.addProductFamily("code1",
"designation1");
storageService.addProductFamily("code2",
"designation2");
System.out.println(storageService.getAllProductFamily());
System.out.println(storageService.getAllProduct());
}
catch (Exception e) {
System.out.println(e);
e.printStackTrace();
}
}
}

| |