EJB 3.0 in poche parole

Nonostante i numerosi aspetti positivi, la complessità dell'architettura Enterprise JavaBeans sta ostacolando l'adozione di J2EE. L'architettura EJB è probabilmente l'unico componente J2EE che ha fallito così miseramente nel mantenere la promessa di J2EE di una maggiore produttività degli sviluppatori grazie alla facilità di sviluppo. EJB 3.0 fa un altro tentativo di mantenere quella promessa riducendo la complessità di EJB per gli sviluppatori. EJB 3.0 riduce il numero di artefatti di programmazione che gli sviluppatori devono fornire, elimina o riduce al minimo i metodi di callback richiesti per essere implementati e riduce la complessità del modello di programmazione bean di entità e del modello di mappatura O / R.

In questo articolo, tratterò per prima cosa le modifiche più significative in EJB 3.0. È importante avere le basi prima di immergersi nella piscina EJB 3.0. Successivamente, fornisco una visione di alto livello della bozza EJB 3.0 e quindi entro nelle specifiche della specifica proposta, prestando attenzione a tutte le modifiche una per una: impatto sui tipi di bean aziendali, modello di mappatura O / R, entità- modello di relazione, EJB QL (EJB Query Language), ecc.

sfondo

I due cambiamenti più significativi nella specifica EJB 3.0 proposta sono l'uso della funzionalità di annotazione del programma introdotta in Java 5 e il nuovo modello di mappatura O / R basato su Hibernate.

Funzione metadati in Java 5

Java 5 (precedentemente chiamato J2SE 1.5 o Tiger) ha introdotto una nuova funzionalità di annotazione del programma nel linguaggio. Con questa funzione, puoi definire annotazioni personalizzate e quindi annotare campi, metodi, classi, ecc. Con queste annotazioni. Le annotazioni non influenzano direttamente la semantica del programma, ma gli strumenti (tempo di compilazione o runtime) possono ispezionare queste annotazioni per generare costrutti aggiuntivi (come un descrittore di distribuzione) o applicare il comportamento di runtime desiderato (come la natura stateful di un componente EJB). Le annotazioni possono essere ispezionate tramite l'analisi del codice sorgente (ad esempio, compilatori o strumenti IDE) o utilizzando le API di riflessione aggiuntive aggiunte in Java 5. Le annotazioni possono essere definite in modo che siano disponibili solo a livello di codice sorgente, a livello di classe compilata o in fase di runtime . Tutte le annotazioni proposte nella bozza iniziale di EJB 3.0 hanno un valore RetentionPolicydiRUNTIME. Ciò aumenta marginalmente l'impronta di memoria della classe, ma semplifica notevolmente la vita del fornitore di contenitori e del fornitore di strumenti.

Fare riferimento a Risorse per ulteriori letture su questo argomento.

Ibernazione

Hibernate è un popolare framework di mappatura O / R open source per ambienti Java, pensato per proteggere gli sviluppatori dalle più comuni attività di programmazione relative alla persistenza dei dati. Ha anche uno specifico Hibernate Query Language (HQL), le cui impronte possono essere viste nel nuovo EJB QL. Hibernate offre funzionalità per il recupero e l'aggiornamento dei dati, il pool di connessioni, la gestione delle transazioni, la gestione delle relazioni tra entità dichiarative e le query dichiarative e programmatiche.

Vista a volo d'uccello

Le modifiche nella specifica EJB 3.0 proposta possono essere suddivise in due categorie:

  • Un modello di programmazione EJB basato su annotazioni, oltre al modello EJB 2.1 di definizione del comportamento di un'applicazione tramite descrittori di distribuzione e diverse interfacce.
  • Il nuovo modello di persistenza per i bean di entità. Anche EJB QL è cambiato in modo significativo.

Ci sono anche diversi effetti collaterali a queste proposte, come un nuovo modello di programmazione client, l'uso di interfacce aziendali e un ciclo di vita del bean di entità. Notare che il modello di programmazione EJB 2.1 (con descrittori di distribuzione e interfacce home / remote) è ancora valido. Il nuovo modello semplificato non sostituisce completamente il modello EJB 2.1.

Annotazioni EJB

Uno degli obiettivi importanti del gruppo di esperti è ridurre il numero di artefatti che un fornitore di bean deve fornire e il gruppo ha svolto un lavoro piuttosto accurato per raggiungere tale obiettivo. Nel mondo EJB 3.0, tutti i tipi di bean enterprise sono semplicemente dei vecchi oggetti Java (POJO) con annotazioni appropriate. Le annotazioni possono essere utilizzate per definire l'interfaccia aziendale del bean, le informazioni sulla mappatura O / R, i riferimenti alle risorse e qualsiasi altra cosa definita tramite i descrittori di distribuzione o le interfacce in EJB 2.1. I descrittori di distribuzione non sono più necessari; l'interfaccia home è scomparsa e non è necessario implementare un'interfaccia aziendale (il contenitore può generarla per te).

Ad esempio, si dichiara un bean di sessione senza stato utilizzando l' @Statelessannotazione sulla classe Java. Per i bean con stato, l' @Removeannotazione è contrassegnata su un metodo particolare per indicare che l'istanza del bean deve essere rimossa dopo il completamento di una chiamata al metodo contrassegnato.

Per ridurre la quantità di informazioni che è necessario specificare per un componente, il gruppo di esperti ha adottato un approccio di configurazione per eccezione , il che significa che si forniscono impostazioni predefinite intuitive per tutte le annotazioni in modo che la maggior parte delle informazioni comuni possa essere dedotta.

Il nuovo modello di persistenza

Anche i nuovi bean di entità sono solo POJO con poche annotazioni e non sono entità persistenti per nascita. Un'istanza di entità diventa persistente una volta associata a EntityManagere diventa parte di un contesto di persistenza . Un contesto di persistenza è vagamente sinonimo di contesto di transazione; in parole povere, coesiste implicitamente con l'ambito di una transazione.

Le relazioni di entità vengono definite anche tramite annotazioni. Inoltre, la mappatura O / R viene eseguita anche tramite annotazioni e viene fornito il supporto per diverse operazioni specifiche del database. Con EJB 2.1, gli sviluppatori utilizzavano i propri modelli di progettazione o impiegavano tecniche non portatili (ad esempio, strategie di generazione automatica delle chiavi).

Scavando in profondità

È ora il momento di entrare nello specifico delle proposte fatte nella bozza iniziale di EJB 3.0. Cominciamo con tutti e quattro i tipi di bean enterprise e poi passiamo alle proposte generiche per tutto il modello di programmazione EJB.

Bean di sessione senza stato:

Un bean di sessione senza stato (SLSB), scritto nel modo EJB 3.0, è solo un semplice file Java con un'annotazione a livello di classe di @Stateless. La classe bean può implementare l' javax.ejb.SessionBeaninterfaccia, ma non è richiesta (e in genere non lo farà).

Un SLSB non ha più un'interfaccia home, infatti nessun tipo di EJB lo richiede. La classe bean può implementare o meno un'interfaccia aziendale. Se non implementa alcuna interfaccia aziendale, verrà generata un'interfaccia aziendale utilizzando tutti i metodi pubblici. Se solo determinati metodi devono essere esposti nell'interfaccia aziendale, tutti questi metodi possono essere contrassegnati con l' @BusinessMethodannotazione. Per impostazione predefinita, tutte le interfacce generate sono locali, ma l' @Remoteannotazione può essere utilizzata per indicare che deve essere generata un'interfaccia remota.

Le seguenti poche righe di codice sono sufficienti per definire un HelloWorldbean. Con EJB 2.1, lo stesso bean avrebbe richiesto almeno due interfacce, una classe di implementazione con diverse implementazioni di metodi vuote e un descrittore di distribuzione.

importare javax.ejb. *; / ** * Un bean di sessione senza stato che richiede la generazione di un'interfaccia aziendale remota * per esso. * / @Stateless @Remote public class HelloWorldBean {public String sayHello () {return "Hello World !!!"; }}

Fare riferimento a Risorse per il codice sorgente completo che accompagna questo articolo.

Bean di sessione con stato

La storia con i bean di sessione stateful (SFSB) è praticamente la stessa per SLSB, ad eccezione di un paio di punti specifici di SFSB:

  • Un SFSB dovrebbe avere un modo per inizializzarsi (fornito tramite il ejbCreate()metodo in EJB 2.1 e versioni precedenti). La specifica EJB 3.0 suggerisce che tali metodi di inizializzazione vengano forniti come metodi personalizzati ed esposti tramite l'interfaccia aziendale del bean. Ora spetta al client chiamare i metodi di inizializzazione appropriati prima di utilizzare il bean. Il gruppo di esperti sta ancora discutendo la necessità di fornire un'annotazione che contrassegni un particolare metodo di inizializzazione.
  • Il fornitore del bean può contrassegnare qualsiasi metodo SFSB con l' @Removeannotazione per indicare che l'istanza del bean deve essere rimossa dopo che il metodo annotato è stato chiamato. Ancora una volta, il gruppo di esperti sta ancora discutendo se è necessaria una funzione per indicare che il bean non deve essere rimosso se il metodo non viene completato normalmente.

Ecco la mia opinione sulle due questioni aperte:

  • Deve esistere un'annotazione per il metodo di inizializzazione? Il mio voto è sì, partendo dal presupposto che il contenitore garantirà che almeno uno dei metodi di inizializzazione venga chiamato prima di chiamare qualsiasi altro metodo aziendale. Questo non solo protegge da errori di programmazione accidentali, ma rende anche il contenitore più sicuro di riutilizzare le istanze SFSB. Per chiarezza, permettetemi di menzionare qui che non vengono presi in considerazione metodi di inizializzazione designati (come ejbCreate); il gruppo di esperti sta solo valutando la possibilità di avere un contrassegno di annotazione un metodo come metodo di inizializzazione.
  • Dovrebbe essere configurabile che la terminazione anormale del @Removemetodo non rimuova l'istanza del bean? Ancora una volta, il mio voto è sì. Fornirà solo un controllo migliore al provider di bean e ai programmatori client. Rimane solo una domanda: cosa succede a quei bean contrassegnati per non essere rimossi in una chiamata non riuscita al metodo di rimozione e il metodo di rimozione di una particolare istanza non viene mai completato correttamente? Non è possibile rimuovere tali istanze a livello di codice, ma verranno rimosse al timeout della sessione.

Fare riferimento al codice sorgente per un esempio di SFSB.

Fagioli basati sui messaggi

I bean a messaggi (MDB) sono l'unico tipo di bean che deve implementare un'interfaccia aziendale. Il tipo di interfaccia indica il tipo di sistema di messaggistica supportato dal bean. Per gli MDB basati su JMS (Java Message Service), questa interfaccia è javax.jms.MessageListener. Si noti che l'interfaccia aziendale MDB non è veramente un'interfaccia aziendale , è solo un'interfaccia di messaggistica.

Fagioli di entità

I bean di entità sono contrassegnati con l' @Entityannotazione e tutte le proprietà / campi nella classe bean di entità non contrassegnati con l' @Transientannotazione sono considerati persistenti. I campi persistenti del bean di entità sono esposti tramite proprietà in stile JavaBean o semplicemente come campi di classe Java pubblici / protetti.

I bean di entità possono utilizzare classi helper per rappresentare lo stato del bean di entità, ma le istanze di queste classi non hanno un'identità persistente. Invece, la loro esistenza è fortemente legata all'istanza del bean di entità proprietaria; inoltre questi oggetti non sono condivisibili tra entità.

Fare riferimento al codice sorgente per alcuni bean di entità di esempio.

Relazioni tra entità

EJB 3.0 supporta relazioni unidirezionali e bidirezionali tra i bean di entità, che possono essere relazioni uno-a-uno, uno-a-molti, molti-a-uno o molti-a-molti. Tuttavia, i due lati di una relazione bidirezionale si distinguono come lato proprietario e lato inverso. Il lato proprietario è responsabile della propagazione delle modifiche alle relazioni al database. Per le associazioni molti-a-molti, il lato proprietario deve essere specificato esplicitamente. In realtà è il lato opposto che è specificato dal isInverse=truemembro di annotazione sull'annotazione del lato opposto ManyToMany; da questo si deduce il lato proprietario. Ora, il gruppo di esperti non ha detto che stava rendendo EJB più facile?

Mappatura O / R

The O/R mapping model has also significantly changed from the abstract-persistence-schema-based approach to a Hibernate-inspired one. Though the expert group is still discussing the model, and a clear picture will emerge only with the next draft, this draft features clear indications of the overall approach.

For one, the O/R mapping will be specified in the entity bean class itself by annotations. Also, the approach is to refer to concrete tables and columns instead of the abstract persistence schema. The O/R mapping model has intrinsic support for native SQL; that is, support at a deeper level, not just the ability to run native SQL queries. For example, the column definitions annotation (@Column) has a member columnDefinition that can be something like columnDefinition="BLOB NOT NULL".

Client programming model

An EJB client can acquire a reference to the bean's business interface using the injection mechanism (@Inject annotation). Using the newly introduced @javax.ejb.EJBContext.lookup() method is another approach. But the specification is not clear as to how a standalone Java client acquires reference to a bean instance since the standalone Java clients run in a J2EE client container and lack access to the @javax.ejb.EJBContext object. There is yet another mechanism—a newly introduced universal context object: @javax.ejb.Context(). But, again, the spec does not say how this object can be used in a client container.

EJB QL

Queries can be defined through the @NamedQuery annotation. Two members of this annotation are name and queryString. Once defined, this query can be accessed using the EntityManager.createNamedQuery(name) method. You can also create a regular JDBC-style (Java Database Connectivity) query by calling EntityManager.createQuery(ejbqlString) or a native query using EntityManager.createNativeQuery(nativeSqlString).

EJB QL queries can have both positional as well as named parameters. The javax.ejb.Query interface provides methods for setting these parameters, executing updates, listing results, etc.

Here is one example of how an EJB QL query can be created and executed:

.. .. @NamedQuery (name = "findAllCustomersWithName", queryString = "SELECT c FROM Customer c WHERE c.name LIKE: custName") .. .. @Inject public EntityManager em; clienti = em.createNamedQuery ("findAllCustomersWithName") .setParameter ("custName", "Smith") .listResults ();

Di seguito sono elencati alcuni dei numerosi miglioramenti apportati al QL stesso: