Resumo de estudo para certificação Java Business Component Developer 5 (SCBCD/OCPJBCD 5 – 1Z0-860)

Enterprise JavaBeans 3.0Em meus estudos para a certificação Java Business Component Developer (antiga SCBDC 5 na Sun e nova OCPJBCD 5 na Oracle), acabei criando um resumo a partir do meu livro guia de estudo Enterprise Java Beans 3.0 (Bill Burke, Richard Monson-Haefel) – 5a. edição.

A fim de me ajudar a revisar para o exame e pensando em disponibilizar este conteúdo para o público interessado, segue abaixo transcrito meu resumo. Bom proveito. 😉

Considerações iniciais

Abaixo segue o resumo do livro Enterprise Java Beans 3.0, capítulo a capítulo. Mas, além deste conteúdo, acredito que você deva se atentar para:

– Estudar as definições das responsabilidades de cada papel relacionado a Enterprise Beans, pois o livro não cobre e cai na prova (as primeiras 5 questões da minha prova foram sobre responsabilidades de cada papel): http://java.boot.by/bcd-guide/ch14s02.html.

– Estudar o básico de Web Services e sua relação com EJB, pois o resumo abaixo não cobre estes tópicos. Apesar de o livro ter os capítulos 18 (EJB 3.0: Padrões de Web Services) e 19 (EJB 3.0 e Web Services), preferi não estudá-los, já que a incidência de perguntas deste tema na prova é pequena e me pouparia tempo, além do que estes temas são cobertos na próxima certificação que pretendo tirar (Webservices).

Capítulo 3: gerenciamento de recursos e serviços primários

– O container EJB gerencia serviços primários como concorrência, transação (JTA), persistência (JPA), distribuição (EJB), nomes (JNDI) e segurança. Além de serviços adicionais como sistema de mensagens (JMS) e  temporização (Timer).

Gerenciamento de recursos

O EJB suporta explicitamente dois mecanismos para gerenciar grandes quantidades de beans em tempo de execução:

Pool de Instâncias:

* Utilizados em beans stateless e em beans baseados em mensagens.

* Pool reduz número de recursos necessários, reduzindo consumo de recursos e aumentando throughput.

* EJB usa JCA (JavaEE Connector Architecture) para criar pools.

* Os pools são possíveis entre os EJBs porque os clientes não acessam diretamente os objetos bean. Beans de sessão são acessados por objetos proxy que estendem a interface do bean e beans baseados em mensagens (JMS e JMS-MDBs) recebem a mensagem roteada pelo container.

* Ciclo de vida de beans stateless:

SEM ESTADO (1) -> ESTADO POOLED (2)  -> ESTADO READY (3)

(1) não instanciado

(2) Instanciado, mas não associado a nenhuma solicitação EJB

(3) Associado a uma solicitação EJB

Permite que poucas instâncias sirvam muitas requisições, pois tempo necessário para invocar método é muito menor que pausas entre requisições de clientes EJBs.

* Beans baseados em mensagens:

Depois do bean terminar de processar a mensagem (retorno do método onMessage()),  o container EJB retorna a instância ao pool.

– Mecanismos de ativação:

* Beans stateful usam ativação para conservar recursos.

* Quando precisa conservar recursos, container remove instâncias do bean da memória serializando seu estado conversacional para o armazenamento secundário, num processo conhecido como passivação.

* Quando cliente invoca esse objeto passivado, uma nova instância é criada e preenchida com o estado do objecto anterior, num processo conhecido como ativação.

* Métodos callbacks associados a este processo são @javax.ejb.PostActivate e @javax.ejb.PrePassivate.

* Referências mantidas após passivação/ativação incluem referências remotas a outros beans, SessionContext, contexto do ambiente JNDI, interface de componentes, EntityManager, UserTransaction, etc.

Além destes dois mecanismos, o EJB suporta o uso da JCA (JavaEE Connector Architecture):

* Define interface entre Enterprise Information Systems (EIS) e sistemas container JavaEE (servlet e EJB).

* EIS é termo para sistema de informação como MQSeries, CORBA, SGBDs, etc.

* Embora existam especificações corporativas como JDBC, JMS, etc, cada fornecedor JavaEE acabava tendo que se comunicar especificamente com cada produto, escrevendo código proprietário, e, portanto, tendo de escolher que EISs suportar. Ex: implementador A da especificação JDBC poderia suportar apenas Oracle.

Serviços Primários

Concorrência

* Beans de sessão não suportam acesso concorrente, o que faz sentido, pois beans stateful são usados apenas por um cliente e beans stateless não guardam estado (apenas executam um método de serviço), sendo utilizado um objeto diferente do pool a cada invocação.

* Desta forma, a spec EJB proíbe o uso da palavra-chave synchronized em beans de sessão.

 * Também não é possível criar threads dentro do bean, pois o container EJB é quem tem de manter controle sobre o ciclo de vida do bean.

* Beans de entidade podem ser acessados de forma concorrente. Neste caso, o container protege os dados da concorrência criando uma cópia da instância do bean de entidade por transação.

* Nos beans de mensagens, a concorrência é tratada criando-se várias instâncias do bean com um pool, de forma que cada requisição é atendida por um dos objetos do pool (assim como stateless).

 Transações: o contâiner possui mecanismos que gerenciam as transações no bean automaticamente.

Persistência: As instâncias do bean são acopladas ao armazenamento persistente por meio do EntityManager. Podem ser desacopladas e enviadas a clientes (evitando DTO/TO).

Objetos Distribuídos:

* O EJB 3.0 requer que o servidor EJB suporte Java RMI-IIOP, além de suporte ao SOAP 1.2 através da JAX-RPC.

* EJB permite acesso heterogêneo através do IDL CORBA (Interface Definition Language), usado para acessar EJBs a partir de clientes CORBA escritos em qualquer linguagem, além de clientes SOAP.

Sistema de Mensagens Assíncronas

* JMS é uma API/spec para envio/recebimento de mensagens assíncronas (não exige contâiner EJB).

* JMS-MDB (Message Driven Beans) foram introduzidos no EJB 3.0, tornando o JMS gerenciado pelo container, que requer entrega confiável (reentrega, tolerância a falhas). Assim como também é transacional (uma falha aborta a transação e o tratamento da mensagem é passada para outra instância).

EJB Timer Service: Agenda notificações que são enviadas aos EJBs.

– Atribuição de Nomes

* Serviço de atribuição de nomes precisa de vinculação de objeto (id a um objeto) e API de pesquisa. EJB requer JNDI como API para pesquisa:

InitialContext ic = new InitialContext();
Object ref = ic.lookup("IdJNDI");

Segurança: EJBs podem suportar autenticação, autorização, comunicação segura.

Interoperabilidade:

* IIOP: EJB exige suporte a Java RMI-IIOP (implementação de RMI que utiliza protocolo CORBA IIOP de acordo com a CORBA IDL). Também oferece interoperabilidade de transação, serviço de nomes, segurança.

* SOAP e WSDL: protocolo de serviços web e IDL dos serviços web, respectivamente

Capítulo 4: desenvolvendo seus primeiros beans

Beans de Entidade

– Pode ser criado fora de um servidor de aplicação

– POJOs anotados com metadados de mapeamento objeto/relacional.

@Entity
@Table(name = "CABIN")
public class Cabin implements Serializable {
     @Id
     @Column(name = "ID")
     private int id;
}

@Entity informa que a classe é bean de entidade e pode ser gerenciada por um serviço EntityManager.

@Table informa a tabela do banco (não obrigatório, default é nome da classe).

– Anotar bean de entidade com Serializable não é obrigatório, mas permite utilizá-lo em transferências remotas.

@Column define como a propriedade será mapeada para a coluna (não é obrigatório, default é o nome do atributo).

@Id define a chave primária (obrigatório).

– A especificação JPA requer um descritor /META-INF/persistence.xml no classpath (por default no war é /WEB-INF/classes e no jar /):

<persistence>
     <persistence-unit name="PU">
          <jta-data-source>java:/MyDS</jta-data-source>
     </persistence-unit>
</persistence>

– Uma unidade de persistência é um conjunto de classes gerenciadas por um EntityManager.

Beans de Sessão

Interface do bean:

@javax.ejb.Remote
public interface TravelAgentRemote {
     public void createCabin(Cabin cabin)
}

– Ao contrário do EJB 2.1, os métodos de negócio do EJB 3.0 não precisam declarar java.rmi.RemoteException.

Classe bean:

@javax.ejb.Stateless
public class TravelAgentBean implements TravelAgentRemote {
     public void createCabin(Cabin cabin) {
          // something here...
     }
}

Lookup:

InitialContext ic = new InitialContext();
TravelAgentRemote ref = (TravelAgentRemote)ic.lookup("TravelAgentBean/remote");

Capítulo 5: persistência: EntityManager

– Nas versões antigas da JavaEE, o EJB era responsável pela camada de persistência. Na JEE 5 surgiu uma spec própria: JPA 1.0.

Entity Manager é um serviço central que gerencia mapeamento O/R, APIs para queries, cache, transações com JTA.

– Entidades podem estar gerenciadas (acopladas) ou não-gerenciadas (desacopladas) pelo EntityManager, que monitora e sincroniza conforme necessário.

Contexto de Persistência

– Contexto de persistência é um conjunto de instâncias (entidades) gerenciadas por um gerenciador que sincroniza os dados com o BD de acordo com as regras de flush.

Contexto de persistência com escopo de transação existe durante o tempo de vida da transação. Quando a transação acaba, o contexto de persistência é destruído e, consequentemente, todas as entidades são desacopladas. Somente EntityManager gerenciados pelo container (ou seja, injetados com @PersistenceContext) pode sem de escopo de transação:

@PersistenceContext
private EntityManager em;

public void do() {
     Customer cust = em.find(Customer.class, 1);
}

// cust nao esta mais gerenciado...

Contexto de persistência estendido pode ser gerenciado pela aplicação e existir por mais tempo do que a transação. Neste caso as instâncias gerenciadas permanecem acopladas mesmo após o fim da transação:

tx.begin();
Customer cust = extendedEntityManager.find(Customer.class, 1);
tx.commit();
// cust ainda esta gerenciado...

Empacotamento

– persistence.xml é obrigatório e deve estar dentro de /META-INF no classpath da aplicação (jar, ear, war ou ejb-jar).

– Uma unidade de persistência é associada a uma origem de dados (data source).

– Declaração da unidade de persistência:

<persistence>
     <persistence-unit name="PU">
          <jta-data-source>java:/MyDS</jta-data-source>
          <properties>
               <property name="org.hibernate.hbm2ddl">update</property>
          </properties>
     </persistence-unit>
</persistence>

* Cada <persistence-unit> tem um atributo name (obrigatório) e um transaction-type (opcional):

* O atributo transaction-type pode ser JTA (default em JavaEE) ou RESOURCE_LOCAL (default em JavaSE). JTA tem as transações gerenciadas pelo container EJB (automaticamente ou programaticamente com javax.transaction.UserTransaction), enquanto RESOURCE_LOCAL utiliza a API javax.persistence.EntityTransaction para gerenciar as transações num servidor que não possua necessariamente um servidor EJB.

* <provider> (opcional) define o provedor que implementa javax.persistence.PersistenceProvider, por exemplo org.hibernate.ejb.HibernatePersistence no caso do Hibernate.

* <jta-data-source> ou <non-jta-datasource> geralmente contém o nome JNDI que referencia uma fonte de dados.

* <properties> define um conjunto de atributos específicos de fornecedor para informações ao provedor de persistência. Como na JavaSE não existe JNDI, geralmente é com essas propriedades que são configuradas fontes de dados.

* Adicionalmente, pode haver um arquivo orm.xml que define o mapeamento objeto/relacional.

* Pode ser usada a tag <mapping-file> para referenciar mais arquivos como orm.xml.

* Por padrão o jar que contém o persistence.xml será pesquisado em busca de classes anotadas com @Entity.

* Pode-se definir explicitamente classes pertencentes à unidade de persistência com <class>.

* Pode-se adicionar jars a serem buscadas entidades com <jar-file>[CAMINHO_JAR]</jar-file>.

* Se não devem ser pesquisadas classes no jar (usando apenas as explicitamente declaradas com <class>), deve ser usado <exclude-unlisted-classes />.

EntityManagerFactory

– javax.persistence.EntityManagerFactory possui os seguintes métodos:

* createEntityManager() – cria um EntityManager.

* createEntityManager(Map) – Sobreescreve ou estende as propriedades da unidade de persistência.

* close() – necessário somente se objeto não injetado

* isOpen()

– Para obter no JavaSE:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("MyPUName");
// do something...
emf.close(); // no JavaSE o container nao gerencia o contexto de persistencia...

– Para obter no JavaEE:

@PersistenceUnit(unitName = "MyPUName")
private EntityManagerFactory emf;

EntityManager

– Para obter através do EntityManagerFactory:

emf.createEntityManager();

– Para obter no JavaEE:

@PersistenceContext(unitName = "MyPUName", 
                    properties = {}, 
                    type = PersistenceContextType.TRANSACTION)

* PersistenceContextType possui os valores TRANSACTION (default) e EXTENDED, para criar contextos de persistência gerenciados pelo container e estendidos, respectivamente.

– Possui o método persist(Object object) – Enfileira a entidade para inserção (até fim da transação, flush ou contexto estendido ser associado a uma transação).

– Possui o método <T> T find(Class<T> entity, Object pk) – Retorna null ou carrega os dados da entidade (conforme configuração de fetch type de cada propriedade).

– Possui o método <T> T getReference(Class<T> entity, Object pk) – Lança EntityNotFoundException e não garante estado inicializado (pode ser que select só rode no primeiro acesso aos dados e, se a entidade foi desacoplada e transferida remotamente, uma exceção será disparada ao tentar acessar os dados).

– Possui os seguintes métodos para criar queries com EJBQL:

* Query createQuery(String query)

* Query createNamedQuery(String name)

* Query createNativeQuery(String sql)

* Query createNativeQuery(String sql, Class resultClass)

* Query createNativeQuery(String sql, String resultSetMapping)

– Se a entidade está gerenciada, ao fim da transação ou flush será sincronizado com o BD.

– O método merge(Object entity) reacopla uma entidade ao contexto de persistência.

– O método remove(Object entity) enfileira a entidade para remoção e entidade se torna desacoplada (persist(Object entity) reacopla).

– O método refresh(Object entity) sincroniza entidade com banco, sobreescrevendo quaisquers alterações não comitadas.Pode lançar EntityNotFoundException ou IllegalArgumentException se entidade não gerenciada ou TransactionRequiredException.

– O método flush() sincroniza instâncias, O padrão é acontecer o flush antes de consulta e de commit da transação, pode ser alterado para acontecer apenas no commit.

– O método setFlushMode(FlushModeType type) define o tipo de flush do contexto de persitência.

* FlushModeType possui os valores AUTO (default) e COMMIT.

– O método lock(Object entity, LockModeType type) pode ser usado para criar bloqueios de escrita ou leitura em determinada entidade.

* LockModeType possui os valores READ e WRITE.

– O método EntityManager getDelegate() pode ser usado para obter o objeto de implementação proprietário do EntityManager. Por exemplo: org.hibernate.ejb.EntityManagerImpl.

– Em um ambiente JavaSE, que não possui JTA (somente RESOURCE_LOCAL), a JPA fornece o método EntityTransaction getTransaction() que não pode ser utilizado num contexto de persistência JTA. Este objeto serve para controlar o ciclo de vida do contexto de persistência. Possui os métodos begin(), commit(), rollback(), isActive().

Capítulo 6: mapeando objetos persistentes

@Entity (obrigatório) define que a classe é uma entidade. Possui atributo name (alias para EJBQL).

@Id (obrigatório) define que é identificador. Se colocado acima do campo, demais propriedades são os campos da classe e anotações devem ser colocadas também sobre os campos, mas, se colocado acima do getter, demais propriedades são os outros getters.

– Mapeamento pode ser feito, além de com anotações, através de XML (por default container procura em /META-INF/orm.xml, mas outros arquivos podem ser definidos com a tag <mapping-file> dentro do persistence.xml):

<entity-mappings>
     <entity class="com.br.MyEntity" access="PROPERTY">
          <attributes>
               <id name="id" />
          </attributes>
     </entity>
</entity-mappings>

* o atributo access pode ter os valores PROPERTY (análogo a usar a anotação @Id acima do método) ou FIELD (análogo a usar a anotação @Id acima do campo).

@Table (opcional) informa a qual tabela relacional a entidade está mapeada (por default é o nome da classe não qualificado). Possui os atributos name (nome da tabela), catalog (conjunto de BDs agrupados no mesmo catálogo), schema (banco de dados), @UniqueConstraint[] uniqueConstraints (especifica restrições de UNIQUE para colunas que deveriam ser incluídas na geração).

* @UniqueConstraint possui apenas o atributo String[] columnNames.

* Exemplo de mapeamento com anotação:

@Entity
@Table(name = "my_table_name", 
       schema = "my_bd_name", 
       uniqueConstraints = {@UniqueConstraint(columnNames = {"nome, telefone"})}) 
public class Pessoa {
     @Id
     private int id;

     private String nome;

     private String telefone;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.com.MyEntity" access="FIELD">
          <table name="my_table_name" schema="my_bd_name">
               <unique-constraints>
                    <column-name>nome</column-name>
               </unique-constraints>
          </table>
          <attributes>
               <id name="id" />
          </attributes>
     </entity>
</entity-mappings>

@Column (opcional) possui os atributos name (nome da coluna, default é o nome do campo não qualificado), boolean unique, boolean nullable, boolean insertable, boolean updatable, String columnDefinitions (DDL usado para definir a coluna), table (indica a qual tabela pertence no caso de múltiplos mapeamentos), length (comprimento de um VARCHAR apenas para quando o campo é String), int precision (para campos numéricos), int scale (para campos numéricos).

* Exemplo de mapeamento com anotação:

@Entity
public class Pessoa {
     @Id
     @Column(name = "meu_id")
     private Integer id;

     @Column(name = "idad")
     private String idade;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.com.MyEntity" access="FIELD">
          <attributes>
               <id name="id">
                    <column name="meu_id />
               </id>
               <basic name="idade">
                    <column name="idad" />
               </basic>
          </attributes>
     </entity>
</entity-mappings>

* No mapeamento por XML, <column> é subelemento de <id>, <basic>, <temporal>, <lob> e <enumerated>.

Geração de Chaves

@GeneratedValue edefine que a chave deve ser gerada, possui os atributos GenerationType strategy (GenerationType possui os valores AUTO, TABLE, SEQUENCE e IDENTITY) e String generator.

– GenerationType.AUTO gera a chave automaticamente.

* Exemplo de mapeamento com anotação:

@Entity
public class Pessoa {
     @Id
     @GeneratedValue
     private int id;

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.com.Pessoa" access="FIELD">
          <attributes>
               <id name="id">
                    <generated-value strategy="AUTO" />
               </id>
          </attributes>
     </entity>
</entity-mappings>

– GenerationType.IDENTITY usa um tipo especial de coluna.

– GenerationType.TABLE usa uma tabela com contador para gerar os ids:

create TABLE GENERATOR_TABLE
{
     PRIMARY_KEY_COLUMN VARCHAR NOT NULL,
     VALUE_COLUMN LONG NOT NULL
}

* @TableGenerator é usado para definir as configurações desta tabela. Pode ser anotada sobre a classe, método ou campo id. Possui os atributos name (alias que referencia @Id.generator), table, catalog, schema, pkColumnName (nome da coluna que guarda o contador), valueColumnName (nome da coluna que guarda o identificador do contador), pkColumnValue (identificador do contador), allocationSize (valor do incremento a ser utilizado, permite cachear, já que não busca na tabela a cada geração de chave), UniqueConstraint[] uniqueConstraints (permite definir campos UNIQUE, assim como na anotação @Table) .

* Exemplo de mapeamento com anotação:

@Entity
@TableGenerator(name = "MY_TABLE_GENERATOR", 
                table = "GENERATOR_TABLE", 
                pkColumnName = "PRIMARY_KEY_COLUMN", 
                valueColumnName = "VALUE_COLUMN", 
                pkColumnValue = "gen_pessoa")
public class Pessoa {

     @Id
     @GeneratedValue(strategy = GenerationType.TABLE, generator = "MY_TABLE_GENERATOR")
     private int id;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.com.Pessoa" access="FIELD">
          <table-generator name="MY_TABLE_GENERATOR"
                           table="GENERATOR_TABLE", 
                           pk-column-name="PRIMARY_KEY_COLUMN", 
                           value-column-name = "VALUE_COLUMN", 
                           pk-column-value = "gen_pessoa" />
          <attributes>
               <id name="id">
                    <generated-value strategy="TABLE" generator="MY_TABLE_GENERATOR" />
               </id>
          </attributes>
     </entity>
</entity-mappings>

– GenerationType.SEQUENCE usa uma estrutura de alguns BDs para gerar as chaves.

@SequenceGenerator é usado para definir as configurações desta sequence, de forma análoga a @TableGenerator. Pode ser anotada sobre a classe, método ou campo id. Possui os atributos name (alias que referencia @Id.generator), sequenceName (tabela de sequence no BD), initialValue (primeiro valor de chave a ser usado), allocationSize (valor do incremento a ser utilizado.

* Exemplo de mapeamento com anotação:

@Entity
@SequenceGenerator(name = "MY_SEQUENCE_GENERATOR",
                   sequenceName = "SEQ_TABLE")
public class Pessoa {
     @Id
     @GeneratedValue(strategy = GenerationType.SEQUENCE, 
                     generator = "MY_SEQUENCE_GENERATOR")
     private int id;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.com.Pessoa" access="FIELD">
          <sequence-generator name="MY_SEQUENCE_GENERATOR"
                                 sequence-name="SEQ_TABLE" />
          <attributes>
               <id name="id">
                    <generated-value strategy="SEQUENCE" 
                                     generator="MY_SEQUENCE_GENERATOR" />
               </id>
          </attributes>
     </entity>
</entity-mappings>

Chaves Compostas

@IdClass define classe da chave composta utilizada na entidade. Possui apenas o atributo value (classe da chave composta). Precisa duplicar a definição dos campos da chave na entidade e na classe da chave.

* Cada campo de chave deve ser anotado com @Id na entidade e deve ser criada uma classe com os mesmos campos, com construtor default, serializável e que implemente os métodos equals() e hashCode().

* Exemplo de mapeamento com anotação:

@Entity
@IdClass(MyPK.class)
public class MyEntity {
     @Id
     private int id1;

     @Id
     private int id2;
}
public class MyPK implements Serializable {
     private int id1;
     private int id2;

     public MyPK() {
     }

     public boolean equals(Object obj) {
          // ...
     }

     public int hashEquals() {
          // ...
     }
}

*Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.com.MyEntity" access="FIELD">
          <id-class>br.com.MyPK</id-class>
          <attributes>
               <id name="id1" />
               <id name="id2" />
          </attributes>
     </entity>
</entity-mappings>

@EmbeddedId e @Embeddable permite criar ids compostos “incluindo” as classes com os campos, sem ter que duplicar a definição dos campos da chave na entidade e na classe da chave.

* Exemplo de mapeamento com anotação:

@Embeddable
public class MyPK implements Serializable {

     private int id1;
     private int id2;
}
@Entity
public class MyEntity {
     @EmbeddedId
     public MyPK getPK() {
          // ...
     }
}

* Exemplo de mapeamento com anotação e sobreescrevendo atributos da classe da chave

@Entity
public class MyEntity {
     @EmbeddedId
     @AttributeOverrides({
          @AttributeOverride(name = "id_1", column = @Column(name = "ID1")),
          @AttributeOverride(name = "id_2", column = @Column(name = "ID2"))
     })
     public MyPK getPK() {
          // ...
     }
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <embeddable class="br.com.MyPK" access-property="FIELD">
          <embeddable-attributes>
               <basic name="id1" />
               <basic name="id2" />
          </embeddable-attributes>
     </embeddable>
     <entity class="br.com.MyEntity" access="FIELD">
          <attributes>
               <embedded-id name="pk">
                    <attribute-override name="id1">
                         <column name="ID_1" />
                    </attribute-override>
               </embedded-id>
          </attributes>
     </entity>
</entity-mappings>

Propriedades de Mapeamento

@Transient ignora campo e não trata como persistente.

* Exemplo de mapeamento com anotação:

@Transient
private int myTransient;

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.MyEntity" access="FIELD">
          <attributes>
               <transient name="myTransient"/>
          </attributes>
     </entity>
</entity-mappings>

@Basic é usado para atributos de tipos primitivos (String, byte, Byte, char, BigInteger, BigDecimal, Date, Calendar, Date, Time, Timestamp). Possui os atributos FetchType fetch (indica como deve ser o carregamento da propriedade) e boolean optional (quando gera tabela, seta valor nullable).

* FetchType possui os valores EAGER (preenche dado no carregamento da entidade) e LAZY (preenche dado sob demanda).

* Exemplo de mapeamento com anotação:

@Basic(fetch = FetchType.LAZY, optional = false)
private int numero;

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.MyEntity" access="FIELD">
          <attributes>
               <basic name="numero" fetch="LAZY" optional="false">
          </attributes>
     </entity>
</entity-mappings>

@Temporal permite especificar formato para um campo Date ou Calendar (data, hora ou data/hora). Possui o atributo TemporalType value (tipo de formatação de data). Pode ser usado em conjunto com a anotação @Basic.

TemporalType possui os valores DATE, TIME, TIMESTAMP.

* Exemplo de mapeamento com anotação:

@Temporal(TemporalType.DATE)
private Date created;

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.MyEntity" access="FIELD">
          <attributes>
               <basic name="created">
                    <temporal>DATE</temporal>
               </basic>
          </attributes>
     </entity>
</entity-mappings>

@Lob persiste o dado como java.sql.Blob se tipo é byte[], Byte[] ou Serializable e como java.sql.Clob se tipo é char[], Character[] ou String. Pode ser usado em conjunto com a anotação @Basic.

* java.sql.Blob representa dados binários e java.sql.Clob representa dados de caracter.

* Exemplo de mapeamento com anotação:

@Lob
private Byte[] image;

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.MyEntity" access="FIELD" />
          <attributes>
               <basic name="image">
                    <lob />
               </basic>
          </attributes>
     </entity>
</entity-mappings>

@Enumerated mapeia Java enum para banco de dados. Possui o atributo EnumType value.

* EnumType possui os valores ORDINAL e STRING.

* Exemplo de mapeamento com anotação:

@Enumerated
private MyEnum enum;

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.MyEntity" access="FIELD">
          <attributes>
               <basic name="enum>
                    <enumerated>ORDINAL</enumerated>
               </basic>
          </attributes>
     </entity>
</entity-mappings>

@SecondaryTable usado para mapear múltiplas tabelas numa mesma entidade. Possui os atributos name (nome da outra tabela), schema, catalog, uniqueConstraints, PrimaryKeyJoinColumn[] pkJoinColumns. Também existe o @SecondaryTables que possui o atributo SecondaryTable[] values.

* @PrimaryKeyJoinColumn possui os atributos name (nome da chave estrangeira na tabela secundária que referencia o id da tabela principal), referencedColumnName (nome da chave na tabela principal, por default é a chave primária da entidade), columnDefinition (para geração DDL).

* Exemplo de mapeamento com anotação:

@Entity
@SecondaryTable(name = "TABELA_ADICIONAL", 
                pkJoinColumns  = {@PrimaryKeyJoinColumn(
                                      name = "id_estrangeiro", 
                                      referencedColumnName = "id")}
)
public class MyEntity {
     @Id
     private int id;

     @Column(table = "TABELA_ADICIONAL")
     private String dadoOutraTabela;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.MyEntity" access="FIELD">
          <secondary-table name="TABELA_ADICIONAL">
               <primay-key-join-column name="id_estrangeiro />
          </secondary-table>
          <attributes>
               <id name="id" />
               <basic name="dadoOutraTabela">
                    <column table="TABELA_ADICIONAL" />
               </basic>
          </attributes>
     </entity>
</entity-mappings>

@Embedded usado para mapear mesma tabela em múltiplas entidades. Pode utilizar @AttributeOverrides assim como @EmbeddedId

* Exemplo de mapeamento com anotação:

@Embeddable
public class Endereco {
     private String city;
}
@Entity
public class Pessoa {
     private String nome;

     @Embedded
     private Endereco endereco;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <embeddable class="br.Endereco" access-type="FIELD" />
     <entity class="br.Pessoa" access="FIELD">
          <attributes>
               <basic name="nome" />
               <embedded name="endereco" />
          </attributes>
     </entity>
</entity-mappings>

Capítulo 7: relacionamentos de entidades

Tipos de Relacionamentos

– Relacionamentos unidirecionais são aqueles onde apenas uma entidade referencia a outra e bidirecionais é quando ambas as entidades referenciam umas as outras.

@JoinColumn é análogo à @Column, só não possui os atributos precision, scale e length, por se tratar de campos objeto e não primitivos (String e numérico). O atributo name é a chave estrangeira entre as entidades. E, adicionalmente, possui o atributo referencedColumnName (campo na outra tabela no qual é feito o join, default é a chave primária da outra tabela). Também existe o @JoinColumns que possui o atributo JoinColumn[] values. Se schema gerado pelo JPA esta anotação torna-se opcional.

– @PrimaryKeyJoinColumn é análogo à @JoinColumn, mas utilizado quando não há chave estrangeira em nenhuma das duas tabelas e o elemento de ligação é a chave primária de cada tabela. Possui apenas os atributos name (opcional), referencedColumnName (opcional) e columnDefinitions (opcional). Também existe o @PrimaryKeyJoinColumns que possui o atributo PrimaryKeyJoinColumn[] value para chaves compostas.

– @JoinTable é análogo à @Table e utilizada para mapear relacionamentos definidos em tabelas de relacionamento. Adicionalmente à anotação @Table, possui os atributos JoinColumn[] joinColumns (define a chave estrangeira na tabela de ligação) e JoinColumn[] inverseJoinColumns (mapeia o lado não possuidor).

– @OneToOne, @OneToMany, @ManyToOne e @ManyToMany são análogo a @Basic. Enquanto @Basic é utilizado em tipos primitivos, estes são utilizados com tipos de outras entidades. Adicionalmente aos atributos fetch e optional de @Basic também possuem Class targetEntity (geralmente descobre pelo tipo da propriedade), CascadeType[] cascade, mappedBy (utilizado em relacionamentos bidirecionais).

Lado possuidor é a entidade num relacionamento que declara a chave estrangeira em @JoinColumn.name. Na persistência, a entidade possuidora deve setar a outra entidade, e não o contrário. Por exemplo, se Customer é o lado possuidor e Endereco não, a persistência deve ser feita com cust.setEndereco(new Endereco()).

– Há 4 tipos de cardinalidade (1 para 1, 1 para N, N para 1 e N para N), unidirecional e bidirecional, totalizando 7 tipos de relacionamento.

Relacionamento 1 para 1 Unidirecional 

* Exemplo de mapeamento com  anotação:

@Entity
public class Customer {
     @Id
     private int id;

     @OneToOne
     @JoinColumn(name = "ENDERECO_ID")
     private Endeco endereco;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Customer" access="FIELD">
          <attributes>
               <id name="id" />
               <one-to-one name="endereco" target-entity="br.Endereco">
                    <join-column name="ENDERECO_ID" />
               </one-to-one>
          <attributes>
     </entity>
</entity-mappings>

– Relacionamento 1 para 1 Bidirecional (Customer possui a chave estrangeira de Endereco)

* Exemplo de mapeamento com anotação:

@Entity
public class Customer {
     @Id
     private int id;

     @OneToOne
     @JoinColumn(name = "ENDERECO_ID")
     private Endereco endereco;
}
@Entity
public class Endereco {
     @Id
     @Column(name = "ENDERECO_ID");
     private int id;

     @OneToOne(mappedBy = "endereco")
     private Customer customer;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Customer" access="FIELD">
          <attributes>
               <id name="id" />
               <one-to-one name="endereco" target-entity="br.Endereco">
                    <join-column name="ENDERECO_ID" />
               </one-to-one>
          <attributes>
     </entity>
     <entity class="br.Endereco" access="FIELD">
          <attributes>
               <id name="enderecoId">
                    <column name="ENDERECO_ID" />
               </id>
               <one-to-one name="customer" mapped-by="endereco" target-entity="br.Customer" />
          </attributes>
     </entity>
</entity-mappings>

– Relacionamento 1 para N Unidirecional (Customer é chave estrangeira na tabela Enderecos)

* Exemplo de mapeamento com anotação:

@Entity
public class Customer {
     @Id
     @Column(name = "CUSTOMER_ID")
     private int id;

     @OneToMany
     @JoinColumn(name = "CUSTOMER_ID")
     private List<Endereco> endereco;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Customer" access="FIELD">
          <attributes>
               <id name="id" />
               <one-to-many name="endereco" target-entity="br.Endereco">
                    <join-column name="CUSTOMER_ID" />
               </one-to-many>
          <attributes>
     </entity>
</entity-mappings>

* Exemplo de mapeamento com anotação (Tabela de relacionamento com as chaves estrangeiras de Customer e Endereco):

@Entity
public class Customer {
     @OneToMany
     @JoinTable(name = "CUSTOMER_ENDERECO", 
                joinColumns = {@JoinColumn(name = "CUSTOMER_ID")}, 
                inverseJoinColumns = {@JoinColumn(name = "ENDERECO_ID")})
     private List<Endereco> enderecos;
}

* Exemplo de mapeamento com XML (Tabela de relacionamento com as chaves estrangeiras de Customer e Endereco):

<entity-mappings>
     <entity class="br.Customer" access="FIELD">
          <attributes>
               <one-to-many name="enderecos" target-entity="br.Endereco">
                    <join-table name="CUSTOMER_ENDERECO">
                         <join-column name="CUSTOMER_ID" />
                         <inverse-join-column name="ENDERECO_ID" />
                    </join-table>
               </one-to-many>
          </attributes>
     </entity>
</entity-mappings>

– Relacionamento N para 1 Unidirecional (Customer é chave estrangeira na tabela Endereco)

* Exemplo de mapeamento com anotação:

@Entity
public class Endereco {
     @ManyToOne
     @JoinColumn(name = "CUSTOMER_ID")
     private Customer customer;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Endereco" access="FIELD">
          <attributes>
               <many-to-one name="customer" target-entity="br.Customer">
                     <join-column name="CUSTOMER_ID" />
                </many-to-one>
          </attributes>
     </entity>
</entity-mappings>

– Relacionamento 1 para N / N para 1 Bidirecional é análogo ao aos outros mapeamentos bidirecionais (utiliza atributo mappedBy).

– Relacionamento N para N Bidirecional é análogo ao mapeamento 1 para N / N para 1 com tabela de junção, utilizando o @JoinTable.

– Relacionamento N para N Unidirecional é análogo ao aos outros mapeamentos bidirecionais (utiliza atributo mappedBy).

Relacionamentos Baseados em Coleções

Lista Ordenada utiliza java.util.List com a anotação @OrderBy.

* @OrderBy possui o atributo value que é um segmento de EJBQL (opcional, default é ordenar de forma ascendente pela chave primária).

* Exemplo de mapeamento com anotação:

@Entity
public class Pessoa {
     @OneToMany
     @JoinColumn(name = "ENDERECO_ID")
     @OrderBy("TELEFONE DESC")
     private List<Endereco> enderecos;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Pessoa" access="FIELD">
          <attributes>
               <one-to-many name="enderecos" target-entity="br.Endereco">
                    <join-column name="ENDERECO_ID" />
                    <order-by>TELEFONE DESC</order-by>
               </one-to-many>
          </attributes>
     </entity>
</entity-mappings>

– Map utiliza java.util.Map para mapear os objetos para um Map sendo a chave um campo determinado.

@MapKey possui o atributo name (nome do atributo que deve ser usado como chave, default é a chave primária).

* Exemplo de mapeamento com anotação:

@Entity
public class Pessoa {
     @OneToMany
     @JoinColumn(name = "ENDERECO_ID")
     @MapKey(name = "rua")
     private Map<Integer, Endereco> enderecos;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Pessoa" access="FIELD">
          <attributes>
               <one-to-many name="enderecos" target-entity="br.Endereco">
                    <join-column name="ENDERECO_ID" />
                    <map-key name="rua" />
               </one-to-many>
          </attributes>
     </entity>
</entity-mappings>

Cascading

* CascadeType possui os valores ALL, PERSIST, MERGE, REMOVE, REFRESH

* Exemplo de mapeamento com anotação:

@Entity
public class Pessoa {
     @OneToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
     @JoinColumn(name = "ENDERECO_ID")
     private Endereco endereco;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Pessoa" access="FIELD">
          <attributes>
               <one-to-many name="enderecos" target-entity="br.Endereco">
                    <join-column name="ENDERECO_ID" />
                    <cascade-merge />
                    <cascade-persist />
               </one-to-many>
          </attributes>
     </entity>
</entity-mappings>

Capítulo 8: herança de entidade

– @Inheritance possui o atributo InheritanceType strategy (define qual dos três tipos de estratégia de mapeamento de herança está sendo utilizado na tabela).

InheritanceType possui os valores SINGLE_TABLE, TABLE_PER_CLASS e JOINED.

Tabela Única por Hierarquia de Classe (SINGLE_TABLE) possui uma única tabela com as propriedades de todas as classes da hierarquia. Vantagens: rápido (sem joins) e fácil manutenção. Desvantagens: não normalizado e todas as colunas permitem NULL.

@DiscriminatorColumn indica o campo usado para mapear o registro da tabela única para a entidade correspondente na hierarquia. Possui os atributos name, DiscriminatorType discriminatorType (default é String), columnDefinition e length.

DiscriminatorType possui os valores STRING, CHAR e INTEGER

@DiscriminatorValue possui o atributo value que indica que valor deve ser usado no campo discriminatório para a entidade.

* Exemplo de mapeamento com anotação:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISC")
@DiscriminatorValue("PESSOA")
public class Pessoa {

}
@Entity
@DiscriminatorValue("FUNCIONARIO")
public class Funcionario {

}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Pessoa" access="FIELD">
          <inheritance strategy="SINGLE_TABLE" />
          <discriminator-column name="DISC" />
          <discriminator-value>PESSOA</discriminator-value>
          <attributes>
          </attributes>
     </entity>
     <entity class="br.Funcionario" access="FIELD">
          <discriminator-value>FUNCIONARIO</discriminator-value>
          <attributes>
          </attributes>
     </entity>
</entity-mappings>

– Tabela por Classe Concreta (TABLE_PER_CLASS) possui uma tabela associadas a cada classe concreta que possui todos as propriedades das superclasses. Vantagens: mapeamento de legados e permite NULL. Desvantagens: não normalizado e baixo desempenho.

* Exemplo de mapeamento com anotação:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Pessoa {

}
@Entity
public class Funcionario extends Pessoa {

}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Pessoa" access="FIELD">
          <inheritance strategy="TABLE_PER_CLASS" />
          <attributes>
          </attributes>
     </entity>
     <entity class="br.Funcionario" access="FIELD" />
</entity-mappings>

– Tabela por Subclasse (JOINED) possui uma tabela para cada classe da hierarquia.

* @PrimaryKeyJoinColumn precisa ser usado somente se o id do filho for diferente do id da entidade pai.

* Exemplo de mapeamento com anotação:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Pessoa {
     @Id
     @Column(name = "ID")
     private int id;
}
@Entity
@PrimaryKeyJoinColumn(name = "PK_FUNCIONARIO")
public class Funcionario extends Pessoa {
     @Id
     @Column(name = "PK_FUNCIONARIO")
     private int id;
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Pessoa" access="FIELD">
          <inheritance strategy="JOINED" />
          <attributes>
               <id name="id">
                    <column name="ID" />
               </id>
          </attributes>
     </entity>
     <entity class="br.Funcionario" access="FIELD">
          <primary-key-join-column name="PK_FUNCIONARIO" />
          <attributes>
               <id name="id">
                    <column name="PK_FUNCIONARIO" />
               </id>
          </attributes>
     </entity>
</entity-mappings>

– Classe Não-Entidade na Hierarquia é uma classe que está na hierarquia, mas não é uma entidade.

* @MappedSuperclass é utilizado para indicar estas classes. Classes filhas herdam propriedades.

* Exemplo de mapeamento com anotação:

@MappedSuperclass
public class Pessoa {

}
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Funcionario extends Person {

}
@Entity
public class Empregado extends Funcionario {

}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <mapped-superclass class="br.Pessoa" access="FIELD">
          <attributes>
          </attributes>
     </entity>
     <entity class="br.Funcionario" access="FIELD">
          <inheritance strategy="TABLE_PER_CLASS" />
          <attributes>
          </attributes>
     </entity>
     <entity class="br.Empregado" access="FIELD">
          <attributes>
          </attributes>
     </entity>
</entity-mappings>

Capítulo 9: consultas e a EJBQL

– javax.persistence.Query possui os seguintes métodos:

* List getResultList()

* Object getSingleResult()

* int executeUpdate()

* Query setMaxResults(int max)

* Query setFirstResult(int start)

* Query setHint(String hintName, Object value)

* Query setParameter(String name, Object value)

* Query setParameter(String name, Date value, TemporalType temporalType)

* Query setParameter(String name, Calendar value, TemporalType temporalType)

* Query setParameter(int position, Object value)

* Query setParameter(int position, Date value, TemporalType temporalType)

* Query setParameter(int position, Calendar value, TemporalType temporalType)

* Parâmetros:

Query q = em.createQuery("FROM customer c WHERE c.firstname = :name");
q.setParameter("name", "Vanessa");

* Paginação:

Query q = em.createQuery("FROM Customer c");
q.setMaxResults(10);
q.setFirstResult(5);

* Hints:

Query q = em.createQuery("FROM Customer c");
q.setHint("org.hibernate.timeout", 1000);

FlushMode

Query q = em.createQuery("FROM Customer c");
q.setFlushMode(FlushModeType.COMMIT);

– EJBQL

* Nome Abstrato do Schema é definido por @Entity.name (default é o nome não qualificado da classe). Esse nome é usado no seletor das EJBQLs:

SELECT OBEJCT(c) FROM Customer AS c
SELECT c FROM Customer AS c
SELECT c FROM Customer c

* Alias não pode ser o nome abstrato do schema, nem palavras reservadas da EJBQL e é case insensitive.

* Seleção de propriedades:

SELECT c.name FROM Customer c
SELECT c.creditCard.creditCompany.address.city FROM Customer c

* Expressões de Construtor podem ser usadas quando o retorno desejado é diferente do selecionado:

SELECT new br.Fatura(c.name, c.type) FROM Customer c

* Operador IN é usado para selecionar todos os elementos de um relacionamento baseado em coleção (Ex: seleciona todas as reservas de todos os clientes):

SELECT r FROM Customer c, IN (c.reservations) r

* Operador INNER JOIN (equivalente a JOIN) define uma sintaxe diferente para o operador IN:

SELECT r FROM Customer c INNER JOIN c.reservations r

* Operador LEFT JOIN (equivalente a LEFT OUTER JOIN) permite selecionar um conjunto de entidades onde um dos lados da associação podem não existir (retorna NULL):

SELECT c FROM Customer c LEFT JOIN c.phone

* Operador FETCH JOIN e LEFT FETCH JOIN é usado pré-carregar as propriedades de relacionamento mesmo quando definidas como FetchType.LAZY (evita o problema N+1 queries):

SELECT c FROM Customer c FETCH JOIN c.phones

DISTINCT assegura que a query não retorna duplicatas:

SELECT DISTINCT cust FROM Reservation res INNER JOIN res.cust c

* Literais permitidos são aspas simples para aspas, números, notação científica para pontos flutuantes e booleanos ‘true’ e ‘false’.

* Comparação de igualdade devem comparar tipos iguais (regras de promoção numérica se aplicam), pode comparar entidades (usa chaves primárias).

* Operador BETWEEN deve ser usado apenas em valores numéricos:

SELECT c FROM Customer WHERE c.age BETWEEN 10 AND 18

* Operador IN com literais:

SELECT c FROM Customer c WHERE c.name IN ('João', 'Maria')

* Operador NULL:

SELECT c FROM Customer c WHERE c.name IS NOT NULL

* Operador IS EMPTY (não pode ser usado em coleções identificadas no INNER JOIN, pois retornam vazio, não NULL):

SELECT c FROM Customer c WHERE c.name IS EMPTY

* Operador MEMBER OF:

...WHERE c MEMBER OF r.customers

* Operador LIKE (‘%’ para qualquer sequência de char e _ para um char):

... WHERE c.name LIKE '%A%'

* Expressões funcionais na cláusula WHERE incluem LOWER(), UPPER(), TRIM(), CONCAT(), LENGTH(), LOCATE(), SUBSTRING(), ABS(), SQRT(), MOD().

* Funções retornando dates e horas incluem CURRENT_DATECURRENT_TIMECURRENT_TIMESTAMP.

* Funções agregadoras na cláusula SELECT incluem COUNT(), MAX(), MIN(), AVG(), SUM().

* ORDER BY só pode ser usado com campos que estão na cláusula SELECT e se retorna uma coleção, somente campos da entidade retornada podem ser ordenados:

SELECT c FROM Customer c ORDER BY c.name

GROUP BYHAVING devem usar campos selecionados no SELECT:

SELECT c.name, COUNT(res) FROM Customer c
INNER JOIN c.reservations res
GROUP BY c.name
HAVING count(res) > 10

* Subconsultas:

SELECT res FROM Reservation res WHERE res.amountPaid = 
     (SELECT max(r.amountPaid) FROM Reservation r)

ALL, ANY (equivalente a SOME), EXISTS:

FROM Cruise cr WHERE ALL (SELECT res.amountPaid FROM cr.reservations res) > 0

* Update e Delete em lote:

UPDATE Reservation res SET res.amountPaid = (res.amountPaid + 10) 
     WHERE EXISTS (SELECT c FROM res.customers c WHERE c.name = 'Bill')

Queries Nativas

* É possível obter a conexão JDBC subjacente injetando um javax.sql.DataSource com @Resource.

* Query nativa com valores escalares (Query createNativeQuery(String sql)):

Query q = em.createNativeQuery("SELECT c.name FROM CUSTOMER AS c")

* Query nativa com entidade simples (Query createNativeQuery(String sql, Class entityClass)). Atributos retornados devem corresponder exatamente à entidade mapeada:

Query q = em.createNativeQuery("SELECT p.* FROM PHONE as p", Phone.class)

* Query nativa complexa (Query createNativeQuery(String sql, String mappingName)). Usa as anotações a seguir para mapear:

@ResultSetMapping possui os atributos name, EntityResult[] entities, ColumnResult[] columns.

@EntityResult possui os atributos Class entityClass, FieldResult[] fields, discriminatorColumn.

@FieldResult possui os atributos name e column.

@ColumnResult possui o atributo name.

Exemplo de query nativa complexa com anotação:

@Entity
@ResultSetMapping(name = "customerAndCreditCardMapping",
                  entities = {@EntityResult(entityClass = Customer.class),
                              @EntityResult(entityClass = CreditCard.class,
                                            fields = {@FieldResult(name = "id",
                                                                   column = "CC_ID"),
                                                      @FieldResult(name = "number", 
                                                                   column = "NUMBER")})})
public class Customer {
     ...
     Query q = em.createNativeQuery("SELECT c.id, c.firstName, " + 
                                    "cc.id AS CC_ID, cc.number " +
                                    "FROM CUST_TABLE c, CREDIT_CARD_TABLE", 
                                    "customerAndCreditCardMapping");
     ...
}

Exemplo de query nativa complexa com XML:

<entity-mappings>
     <sql-result-set-mapping name="customerAndCreditCardMapping">
          <entity-result entity-class="br.Customer" />
          <entity-result entity-class="br.CreditCard">
               <field-result name="id" column="CC_ID" />
               <field-result name="number" column="number" />
          </entity-result>
     </sql-result-set-mapping>
</entity-mappings>

Exemplo de query nativa complexa mista (escalar e entidades no resultado) com anotação:

@Entity
@ResultSetMapping(name = "reservationCount"
                  entities = {@EntityResult(entityClass = Cruise.class,
                                            fields = @FieldResult(name = "id",
                                                                   column = "id")),
                  columns = @ColumnResult(name = "resCount")
public class Customer {
     ...
     Query q = em.createNativeQuery("SELECT c.id, count(Reservation.id) as resCount " + 
                                    "FROM Cruise c LEFT JOIN Reservation " +
                                    "ON c.id = Reservation.CRUISE_ID" +
                                    "GROUP BY c.id", 
                                    "reservationCount");
     ...
}

Exemplo de query nativa complexa mista (escalar e entidades no resultado) com XML:

<entity-mappings>
   <sql-result-set-mapping name="reservationCount">
      <entity-result entity-class="com.titan.domain.Cruise">
          <field-result name="id" column="id"/>
      </entity-result>
      <column-result name="resCount"/>
   </sql-result-set-mapping>
</entity-mappings>

Named Queries são análogas a constantes, as queries podem ser reutilizadas em vários lugares.

* @NamedQuery possui os atributos name, query e QueryHint[] hints. Também possui @NamedQueries.

* @QueryHint possui os atributos name e value.

* Exemplo de mapeamento com anotação:

@NamedQuery(name = "findFullyPaidCruises",
                      query = "FROM Cruise cr
                               WHERE 0 < ALL 
                               (SELECT res.amountPaid FROM cr.reservations res)")
@Entity
public class Cruise {
     ...
     Query q = em.createNamedQuery("findFullyPaidCruise");
     ...
}

* Exemplo de mapeamento com XML:

<entity-mappings>
   <named-query name="findFullyPaidCruises">
      <query>
             FROM Cruise cr
             WHERE 0 < ALL
             (SELECT res.amountPaid FROM cr.reservations res)
      </query>
   </named-query>
</entity-mappings>

Capítulo 10: retornos de chamadas e ouvintes de entidade

– São invocados nessa ordem: listeners segundo ordem de mapeamento e depois callbacks da entidade.

Callbacks são @PrePersist, @PostPersist, @PostLoad (ao usar find() ou refresh()), @PreUpdate, @PostUpdate, @PreRemove, @PostRemove. Estas anotações devem ser usadas num método void sem argumentos e que não lance exceções numa entidade particular:

* Exemplo de mapeamento com anotação:

@Entity
public class Cabin {
     @PostPersist
     void afterInsert() {
          ...
     }
}

* Exemplo de mapeamento com XML:

<entity-mappings>
     <entity class="br.Cabin" access="FIELD">
          <post-persist name="afterInsert" />
     </entity>
</entity-mappings>

Entity Listeners escutam as entidades nas quais foram registrados. O listener deve ter um construtor default e o método anotado com um dos eventos de callback deve receber um Object que representa a entidade dona do evento. Deve ser registrado o listener na entidade desejada.

@EntityListeners possui o atributo Class[] value.

* Exemplo de mapeamento com anotação:

public class MeuListener {
     @PostPersist
     void postInsert(Object entity) {
     }
}
@Entity
@EntityListeners({MeuListener.class})
public class Cabin {
}

* Exemplo de mapeamento com XML:

<entity class="br.Cabin">
   <entity-listeners>
      <entity-listener class="br.MeuListener" />
   </entity-listeners>
</entity>

* Listeners default são mapeados no arquivo de mapeamento ORM e ouvem todas as entidades. É declarado inserindo o elemento <entity-listeners> abaixo do elemento root <entity-mappings>.

* @ExcludeDefaultListeners pode ser usado para desativar os listeners defaults numa determinada entidade:

@Entity
@ExcludeDefaultListeners
public class Cabin {
}
<entity-mappings>
     <entity class="br.Cabin" access="FIELD">
          <exclude-default-listeners />
     </entity>
<entity-mappings>

* @ExcludeSuperclassListeners pode ser usado para desativar os listeners herdados das classes pais numa determinada entidade:

@Entity
@ExcludeSuperclassListeners
public class Cabin extends SuperCabin {
}
<entity-mappings>
     <entity class="br.Cabin" access="FIELD">
          <exclude-superclass-listeners />
     </entity>
<entity-mappings>

Capítulo 11: beans de sessão

Interfaces

@Remote quando chamados por clientes passam seus parâmetros copiados (por valor).

@Local quando chamados por clientes passam seus parâmetros por referências, já que ambos, cliente e bean, estarão rodando na mesma VM.

* Beans podem implementar várias interfaces.

* Uma interface pode ser @Local e @Remote, não ambos, mas podem estender mesma interface por economia.

* Exceções não verificadas (filhas de RuntimeException) são empacotadas em uma EJBException.

* Não é obrigatório bean implementar interfaces. A própria classe do bean pode ser anotada com @Local e/ou @Remote. Neste caso a anotação usa um argumento que é uma lista de interfaces. Ideia ruim, pois classe não tem a obrigação de implementar os métodos definidos no contrato da interface.

– Mapeamento pode ser feito, além de com anotações, através do XML ejb-jar.xml dentro de /META-INF no classpath da aplicação

@Stateless/@Stateful possui o atributo name (default é o nome não qualificado), usado somente para sobreescrever metadados no XML.

* Exemplo de mapeamento com anotação:

@Remote
public interface PaymentRemote {

}
@Stateless
public class PaymentBean implements PaymentRemote {

}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>PaymentBean</ejb-name>
               <remote>br.PaymentRemote</remote>
               <ejb-class>br.PaymentBean</ejb-class>
               <session-type>Stateless</session-type>
          </session>
     </enterprise-beans>
</ejb-jar>

<ejb-name> define um nome para o bean que pode ser referenciado em outras configurações (default é o nome não qualificado da classe).

<remote> <local> identificam as interfaces remotais e locais, respectivamente.

<ejb-class> declara a classe do bean.

<session-type> identifica se o bean é STATELESS ou STATEFUL.

– Callbacks

* Exemplo de mapeamento de callback com anotação:

@PostConstruct
public void construiu() {

}

* Exemplo de mapeamento de callback com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <post-construct>
                    <lifecycle-callback-method>construiu</lifecycle-callback-method>
               </post-construct>
          </session>
     </enterprise-beans>
</ejb-jar>

javax.ejb.SessionContext extends javax.ejb.EJBContext possui os seguintes métodos:

* EJBLocalObject getEJBLocalObject() throws IllegalStateException (deprecated, dispara exceção se invocado).

* EJBObject getEJBObject() throws IllegalStateException (deprecated, dispara exceção se invocado).

* MessageContext getMessageContext() throws IllegalStateException.

* <T> getBusinessObject(Class<T> businessInterface) throws IllegalStateException (retorna uma referência para o EJB atual que pode ser invocado por outros clientes, já que é ilegal bean passar this por referência):

@Stateless
public class MyBean implements MyRemote {
     @Resource 
     private SessionContext sc;

     private void method() {
          OtherBean ob = // lookup...
          MyBean myself = sc.getBusinessObject(MyRemote.class);
          ob.aMethod(myself);
     }
}

* Class getInvokedBusinessInterface() (retorna a classe da interface invocada: remote, local ou web service).

javax.ejb.EJBContext possui os seguintes métodos:

* Object lookup(String name) (método de conveniência que permite pesquisar no EJB ENC).

Métodos de Segurança

* java.security.Principal getCallerPrincipal()

* boolean isCallerInRole(String roleName)

Métodos de Transação

* javax.transaction.UserTransaction getUserTransaction() throws IllegalStateException

* boolean getRollbackOnly() throws IllegalStateException

* void setRollbackOnly() throws IllegalStateException

Métodos obsoletos 

* Incluem getCallerIdentity, isCallerInRole(java.security.Identity identity), Properties getEnvironment, getEJBHome, getEJBLocalHome, getTimerService (este só no EJB 2.1).

– Stateless

Ciclo de Vida EJB Stateless

Figura: Ciclo de vida EJB Stateless

* Deve possui construtor default.

* Apesar da instância stateless ser reaproveitada para outros clientes, a cada invocação o contexto SessionContext é alterado para refletir o novo cliente.

* A referência do EJB retornado ao cliente não causa a criação ou alocação de uma instância no pool. Somente na invocação do método.

* Callbacks: @PreDestroy e @PostConstruct

– Stateful

Ciclo de Vida EJB Stateful

Figura: Ciclo de vida EJB Stateful

* Cada vez que um lookup de um bean stateful é realizado, é criada uma nova sessão.

* @Remove no método faz com que o container remova a sessão.

* Garante integridade transacional (métodos são atômicos).

* Beans stateful são passivados, embora sessão continue a existir.

* Callbacks: Além do @PreDestroy e @PostConstruct, possui o @PrePassivate e @PostActivate

* Não expira enquanto transação está em progresso

* Ao expirar o @PreDestroy não é chamado.

* Ao ser passivado, alguns tipos são serializados e desserializados automaticamente pelo container, são eles primitivos, objetos serializáveis, javax.ejb.SessionContext, javax.jta.UserTransaction, javax.naming.Context, javax.persistence.EntityManagerFactory, javax.persistence.EntityManager, referências a recursos gerenciados e referências a EJBs.

* Na passivação os campos transientes são ignorados.

* Quando EJB lança uma exceção de sistema (não verificada e não anotada com @ApplicationException), a instância é destruída e o @PreDestroy não é chamado.

* Ao fim de cada método a transação acaba e instâncias são desacopladas, exceto se o contexto de persistência for definido como EXTENDED (somente stateful pode criar contextos de persistência estendidos, já que stateless não possui sessão):

@Stateful
public class MyBean implements MyRemote {
     @PersistenceContext(unitName = "titan", type = "EXTENDED")
     private EntityManager em;
}

* Bean de sessão stateful injetado com @EJB possuem a sessão injetada e, quando morrem, a sessão do bean também morre.

* Quando um stateful bean injeta outro stateful através da interface local, e ambos possuem contexto de persistência estendido, o contexto de persistência é compartilhado.

Capítulo 12: beans baseados em mensagens

– Todos os fornecedores EJB3 devem suportar JMS.

– JMS fornece uma API comum para acessar de forma independente diferentes sistemas de mensagens corporativos.

– Tópicos e filas são canais virtuais independentes de rede.

– Uma aplicação JMS pode ser construída programaticamente obtendo os recursos por lookup e usando a API JMS ou com a facilidade dos Message Driven Beans (MDB), onde é possível injetar os recursos necessários e há as facilidades do container (segurança, transação, etc).

– Como o envio de mensagens por JMS é assíncrono, o contexto de segurança e transação não se estende do produtor ao consumidor.

– Se transação no recebimento da mensagem falha, mesagem é reentregue (MOM faz parte da transação).

API JMS

– Produtor pode ser criado dentro do container EJB obtendo os recursos com injeção de dependência, além de utilizar todas as facilidades do container (transação, segurança, etc) ou pode ser criado fora do container EJB obtendo os recursos através do lookup.

* Exemplo da API JMS para produzir mensagem (com lookup dos recursos ou injeção de dependência omitidos):

public void send() {
     // Obtem recursos necessarios...

     // Obtem sessao a partir de uma conexao
     Connection conn = connectionFactory.createConnection();
     Session session = connect.createSession(true, 0);

     // Cria mensagem
     TextMessage msg = session.createTextMessage();
     msg.setText("Minha mensagem");

     // Enviar mensagem
     MessageProducer producer = session.createProducer(true, 0);
     producer.send(msg);

     conn.close();
}

– Consumidor pode ser criado dentro do container EJB utilizando-se do tipo de bean Message Driven Bean (MDB) ou fora do container EJB criando programaticamente o servidor que recebe a mensagem ou utilizando um Listener do JMS.

* Exemplo da API JMS para consumir mensagem:

public void receive() {
     // Obtem recursos necessarios...

     // Obtem sessao a partir de uma conexao
     Connection conn = connectionFactory.createConnection();
     Session session = connect.createSession(true, 0);

     // Recebe mensagem
     MessageConsumer consumer = session.createConsumer(topic);
     TextMessage msg = (TextMessage) consumer.receive();

     conn.close();
}

* Exemplo de javax.jms.Listener para consumir mensagem:

public class MyMessageListener implements MessageListener {
     public void onMessage(Message message) {
          // do something...
     }
}
public void receive() {
     // Obtem recursos necessarios...

     // Obtem sessao a partir de uma conexao
     Connection conn = connectionFactory.createConnection();
     Session session = connect.createSession(true, 0);

     // Seta listener para receber mensagem
     MessageConsumer consumer = session.createConsumer(topic);
     consumer.setMessageListener(new MyMessageListener());

     conn.start();
}

javax.jms.Connection fornece uma conexão JMS com um broker (MOM).

 Possui o método createSession(boolean transacted, int aknowledMode), mas parâmetros são ignorados.

* javax.jms.Session é usado para agrupar ações.

* Mensagens JMS possuem cabeçalho e corpo.

* Tipos de Mensagens JMS:

javax.jms.TextMessage com o método setText(String message)

javax.jms.MapMessage com o método setDouble(String key, Double message), setInt, etc…

javax.jms.ObjectMessage com o método setObject(Object obj).

javax.jms.BytesMessage

javax.jms.StreamMessage

javax.jms.Consumer possui três métodos para receber mensagens. Sessions beans não deveriam receber mensagens, pois a thread pode ficar bloqueada até o recebimento.

receive() – bloqueia a thread até o recebimento de uma mensagem.

receive(long timeout) – bloqueia a thread até o recebimento da mensagem ou timeout.

receiveNoWait() – lê mensagem se já existir, caso contrário, não bloqueia a thread.

– Modelos de mensagens: Fila e Tópico

Modelos de mensagens

Figura: Modelos de mensagens

MDB (Message Driven Beans)

– Bean baseado em mensagens podem se preocupar apenas em processar as mensagens, pois container EJB gerencia transações, segurança, etc, enquanto clientes JMS normais precisam lidar com isso, além da concorrência.

* Exemplo de mapeamento com anotação:

@MessageDriven(activationConfig = {
                          @ActivationConfigProperty(
                                               propertyName = "destinationType", 
                                               propertyValue = "javax.jms.Queue"),
                          @ActivationConfigProperty(
                                               propertyName = "messageSelector", 
                                               propertyValue = "MessageFormat = 'Version 3'")
})
public class MessageBean implements MessageListener {
     public void onMessage(Message message) {
          // do something...
     }
}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <message-driven>
               <ejb-name>MyMessageBean</ejb-name>
               <ejb-class>br.MyMessageBean</ejb-class>
               <messaging-type>javax.jms.MessageListener</messaging-type>
               <transaction-type>CONTAINER</transaction-type>
               <message-destination-type>javax.jms.Queue</message-destionation-type>
               <activation-config>
                    <activation-property>
                         <activation-config-property-name>
                              destinationType
                         </activation-config-property-name>
                         <activation-config-property-value>
                              javax.jms.Queue
                         </activation-config-property-value>
               </activation-config>
          </message-driven>
     </enterprise-beans>
</ejb-jar>

@MessageDriven é utilizado para definir um MDB e possui o atributo ActivationConfigProperty[] activationConfig.

@ActivationConfigProperty é utilizado para configurar um MDB e possui os atributos propertyName e propertyValue. No EJB3 são definidas as seguintes propriedades:

acknowledgeMode – Valor Auto-Acknowledge ou Dups-ok-acknowledge. Irrelevante se dentro de transação.

messageSelector (seleciona mensagem para MDB baseado em um seletor no cabeçalho da mensagem. Utiliza notação SQL-92). Exemplo: propertyValue=”MessageFormat = ‘Version 3.4′”.

destinationType – javax.jms.Queue ou javax.jms.Topic.

subscriptionDurability – Valor Durable (armazena mensagem para entrega posterior em caso de indisponibilidade de tópico, já que em fila a mensagem permanace até ser entregue) ou NonDurable.

– javax.ejb.MessageDrivenContext extends javax.ejb.EJBContext, é irmão de javax.ejb.SessionContext. Esta classe não acrescenta métodos. Somente métodos relacionados a transação nesta classe podem ser invocados no MDB, os outros lançam uma RuntimeException.

– O ciclo de vida de um MDB é igual ao de um bean stateless.

– MDBs Baseados em Conector

* Conector é um jar, war, etc.

* Possui uma interface do sistema de mensagens (análogo à javax.jms.MessageListener):

@MessageDriven
public class MyMessageHandler implements com.vendorx.EmailListener {
     public void onMessage(com.vendorx.Message) {
          // do something...
     }
}

* Neste caso, as propriedades de ativação são específicas do fornecedor.

– Link de Mensagem

– É utilizado quando se deseja que mensagens enviadas por determinado enterprise bean sejam roteadas para um MDB específico. Com isso é possível orquestrar um fluxo de mensagens entre componentes.

* Exemplo de mapeamento:

<ejb-jar>
     <enterprise-beans>
           <session>
                <ejb-name>MyBean</ejb-name> 
                <message-destination-ref>
                     <message-destination-ref-name>jms/TicketTopic</message-destination-ref-name>
                     <message-destination-type>javax.jms.Topic</message-destination-type>
                     <message-destination-usage>Produces</message-destination-usage>
                     <message-destination-link>Distribuidor</message-destination-link>
                </message-destination-ref>
           </session>

           <message-driven>
                <ejb-name>MyMessageHandler</ejb-name>
                <message-destination-link>Distribuidor</message-destination-link>
           </message-driven>
     </enterprise-beans>

     <assembly-description>
          <message-destination>
               <message-destination-name>Distribuidor</message-destination-name>
          </message-destination>
     </assembly-description>
</ejb-jar>

Capítulo 13: serviço de timer

Tratamento de Timeout

* Pra tratar o timeout, deve ser implementado o método public void timeout(javax.ejb.Timer timer)

* Exemplo de tratamento implementando classe javax.ejb.TimedObject:

@Stateless
public class MyBean implemetns javax.ejb.TimedObject {
     public void timeout(javax.ejb.Timer timer) {
          // do something...
     }
}

* Exemplo de tratamento com anotação:

@Stateless
public class MyBean {
     @Timeout
     public void timeout(javax.ejb.Timer timer) {
          // do something...
     }
}

Agendamento

* É utilizado o objeto TimerService obtido através de injeção de dependência com @Resource ou do EJBContext.getTimerService().

* Exemplo de agendamento:

@Stateless
public class MyBean {
     @Resource
     private TimerService timer;

     public void schedule() {
          timer.createTimer(new Date(), "Timeout");
     }
}

javax.ejb.TimerService possui os seguintes métodos:

* Timer createTimer(Date expiration, Serializable info) throws IllegalArgumentException, IllegalStateException, EBJException

* Timer createTimer(long interval, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException

* Timer createTimer(Date initialExpiration, long interval, Serializable info) throws IllegalArgumentException, IllegalStateException, EJBException

* Timer createTimer(long initialInterval, long interval) throws IllegalArgumentException, IllegalStateException, EJBException

* Collection getTimers() throws IllegalStateException, EJBException – retorna timers associados ao EJB ao qual pertence.

– javax.ejb.Timer possui os seguintes métodos:

* void cancel() throws IllegalStateException, NoSuchObjectLocalException, EJBException

* Serializable getInfo() throws IllegalStateException, NoSuchObjectLocalException, EJBException

* Date getNextTimeout() throws IllegalStateException, NoSuchObjectLocalException, EJBException

* long getTimeRemaining() throws IllegalStateException, NoSuchObjectLocalException, EJBException

* TimerHandle getHandle() throws IllegalStateException, NoSuchObjectLocalException, EJBException

javax.ejb.TimerHandler possui os seguintes métodos:

* Timer getTimer() throws NoSuchObjectLocalException, EJBException

Exceções

javax.ejb.NoSuchObjectLocalException é lançada se invocado método em um timer expirado ou cancelado.

– Timers em Stateless

* Usado em batchs, etc.

* Quando evento expira, qualquer objeto do pool é selecionado para tratar.

* Não é boa idéia setar/resetar timers no @PostConstruct ou @PreDestroy, já que não há garantia de que serão chamados (alguns containers só executam quando instância fica READY na primeira chamada de um cliente, antes disso não cria pool).

* Boa idéia criar timers em método de negócio

– Timers em MDBs

* Usado em batchs, etc.

* Assim como stateless, quando evento expira, qualquer objeto do pool é selecionado para tratar.

* Boa idéia criar timer no método onMessage.

Capítulo 14: JNDI ENC e injeção

JNDI ENC

– Cada container EJB possui seu próprio registro interno (JNDI ENC)

ENC: Enterprise Naming Context

– Pode ser registrado no ENC EJBs, filas ou tópicos JMS, fábrica de conexões JMS, datasources, qualquer recurso JCA, primitivos, além de serviços JavaEE como UserTransaction, TimerService, etc.

– O JNDI ENC é preenchido sempre que um recurso ou serviço for anotado ou declarado no XML, podendo então ser feita sua pesquisa JNDI.

Registro

* Exemplo de mapeamento com anotação:

@Stateless
@EJB(name = "ejb/MyInjected"
     beanInterface = MyInjectedLocal.class,
     beanName = "myId")
public class MyBean {

}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <ejb-name>MyFather</ejb-name>
          <ejb-local-ref>
               <ejb-ref-name>ejb/MyInjected</ejb-ref-name>
               <ejb-ref-type>session</ejb-ref-type>
               <local>com.MyInjectedLocal</local>
               <ejb-link>myId</ejb-link>
          </ejb-local-ref>
     </enterprise-beans>
</ejb-jar>

– Pesquisa

* Exemplo de pesquisa com lookup JNDI:

InitialContext ic = new InitialContext();
MyInjected my = (MyInjected) ic.lookup("java:comp/env/ejb/MyInjected")

java:comp/env retorna o ENC do EJB específico.

* Exemplo de pesquisa com EJBContext:

@Resource
EJBContext ctx;

// ...

MyInjected my = (MyInjected) ctx.lookup("ejb/MyInjected");

* Exemplo de pesquisa com anotação:

@EJB
private MyInjected my;

// ou...

@EJB
public void getMy(MyInjected my) {}

Quando um recurso é injetado com anotação, seu nome default no ENC é classe pertencente + / + nome do campo. Ex: br.com.MyBean/my.

* Exemplo de pesquisa com XML:

<ejb-jar>
     <enterprise-beans>
          <ejb-name>MyFather</ejb-name>
          <ejb-local-ref>
               <ejb-ref-name>ejb/MyInjected</ejb-ref-name>
               <ejb-ref-type>session</ejb-ref-type>
               <local>com.MyInjectedLocal</local>
               <ejb-link>myId</ejb-link>
               <injection-target>
                    <injection-target-class>br.com.MyBean</injection-target-class>
                    <injection-target-name>my</injection-target-name>
               </injection-target>
          </ejb-local-ref>
     </enterprise-beans>
</ejb-jar>

Herança

* Subclasses herdam recursos injetados (se não privado).

* Subclasses podem sobrescrever injeção (injetando outra implementação, por exemplo), mas se recurso do pai for privado, não é herdado.

Tipos de Injeção

 EJB é injetado com @EJB, que possui os atributos name (nome do JNDI ENC relativo a java:comp/env), beanInterface (interface EJB), beanName (nome do bean referenciado) e mappedName (específico de fornecedor).

* Se anotado em classe, registra no JNDI ENC. Para múltiplos registros, usar anotação @EJBs com atributo EJB[] value.

* Se anotado em atributo ou getter injeta EJB na propriedade correspondente.

* Exemplo de mapeamento com anotação:

@Stateless
@EJB(name = "ejb/MyOtherBean",
     beanInterface = MyOtherBean.class,
     beanName = "otherBean")
public class MyBean {
     @EJB
     private MyOtherBean other;
}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <ejb-ref>
                    <ejb-ref-name>ejb/MyOtherBean</ejb-ref-name>
                    <ejb-ref-type>Session</ejb-ref-type>
                    <remote>br.com.MyOtherBean</remote>
                    <injection-target>
                         <injection-target-class>br.com.MyBean</injection-target-class>
                         <injection-target-name>other</injection-target-name>
                    </injection-target>
                    <ejb-link>otherBean</ejb-link>
               <ejb-ref>
          </session>

          <session>
               <ejb-name>otherBeann</ejb-name>
               ...
          </session>
     </enterprise-beans>
</ejb-jar>

* Cada <ejb-name> ou @Stateless.name deve ser único em cada implantação EJB JAR, mas não em um EAR. Nesse caso a diferenciação é feita assim:

@EJB(beanName = "a.jar#MyEjb")
<ejb-link>a.jar#MyEjb</ejb-link>

EntityManagerFactory é injetado com @PersistenceUnit que possui os atributos name (JNDI ENC relativo a java:comp/env) e unitName (nome da unidade de persistência, se só existe uma, esse atributo é opcional).

* A vantagem de injetar é que container cuida do ciclo de vida.

* Se anotado em classe, registra no JNDI ENC. Para múltiplos registros, usar anotação @PersistenceUnits com atributo PersistenceUnit[] value.

* Se anotado em atributo ou getter injeta EntityManagerFactory na propriedade correspondente.

* Exemplo de mapeamento com anotação:

@Stateless
@PersistenceUnit(name = "persistence/MyPu",
     unitName = "myPu")
public class MyBean {
     @PersistenceUnit
     private EntityManagerFactory emf;
}

* Exemplo de mapeamento com anotação:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <persistence-unit-ref>
                    <persistence-unit-ref-name>persistence/MyPu</persistence-unit-ref-name>
                    <persistence-unit-name>MyPu</persistence-unit>

                    <injection-target>
                         <injection-target-class>br.com.MyBean</injection-target-class>
                         <injection-target-name>emf</injection-target-name>
                    </injection-target>

               <persistence-unit-ref>
          </session>
     </enterprise-beans>
</ejb-jar>

EntityManger é injetado com @PersistenceContext que possui os atributos name (JNDI ENC relativo a java:comp/env), unitName (nome da unidade de persistência, se só existe uma, esse atributo é opcional), PersistenceContextType type (define se o escopo de persistência é estendido) e PersistenceProperty[] properties.

* PersistenceContextType possui os valores TRANSACTION e EXTENDED (este último só em stateful).

* Se anotado em classe, registra no JNDI ENC. Para múltiplos registros, usar anotação @PersistenceContexts com atributo PersistenceUnit[] value.

* Se anotado em atributo ou getter injeta EntityManager na propriedade correspondente.

* Exemplo de mapeamento com anotação:

@Stateful
@PersistenceContext(name = "persistence/MyPu",
     unitName = "myPu",
     type = PersistenceContextType.EXTENDED)
public class MyBean {
     @PersistenceContext
     private EntityManager em;
}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <persistence-context-ref>
                    <persistence-context-ref-name>persistence/MyPu</persistence-context-ref-name>
                    <persistence-unit-name>MyPu</persistence-unit>
                    <persistence-context-type>EXTENDED</persistence-context-type>

                    <injection-target>
                         <injection-target-class>br.com.MyBean</injection-target-class>
                         <injection-target-name>em</injection-target-name>
                    </injection-target>

               <persistence-context-ref>
          </session>
     </enterprise-beans>
</ejb-jar>

Resource é injetado com @Resource que possui os atributos name (JNDI ENC relativo a java:comp/env), Class type, AuthenticationType authenticationType (CONTAINER ou APPLICATION), boolean shareable (é compartilhado entre os beans, default true), description, mappedName (específico do fornecedor).

* Tipos permitidos são:

javax.sql.DataSource

javax.jms.ConnectionFactory

javax.jms.QueueConnectionFactory

javax.jms.TopicConnectionFactory

javax.mail.Session

javax.net.URL

javax.resource.cci.ConnectionFactory

Qualquer tipo definido por um adaptador JCA

* Se anotado em classe, registra no JNDI ENC. Para múltiplos registros, usar anotação @Resources com atributo Resource[] value.

* Se anotado em atributo ou getter injeta resource na propriedade correspondente.

* Exemplo de mapeamento com anotação:

@Stateful
@Resource(name = "jdbc/Oracle",
     type = javax.sql.DataSource,
     mappedName = "java:/DefaultDS")
public class MyBean {
     @Resource
     private DataSource oracleDB;
}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <resource-ref>
                    <res-ref-name>jdbc/Oracle</res-ref-name>
                    <res-type>javax.sql.DataSource</res-type>
                    <mapped-name>java:/DefaultDS</mappedName>

                    <injection-target>
                         <injection-target-class>br.com.MyBean</injection-target-class>
                         <injection-target-name>oracleDB</injection-target-name>
                    </injection-target>

               <resource-ref>
          </session>
     </enterprise-beans>
</ejb-jar>

Recursos do ambiente e objetos administrados são configurados em tempo de implantação e gerenciados pelo container em tempo de execução. Exemplo: UserTransaction e TransactionSynchronizationRegistry. Também utiliza a anotação @Resource.

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <resource-env-ref>
                    <resource-env-ref-name>UserTransaction</res-ref-name>
                    <resource-env-ref-type>javax.transaction.UserTransaction</resource-env-ref-type>

                    <injection-target>
                         <injection-target-class>br.com.MyBean</injection-target-class>
                         <injection-target-name>ut</injection-target-name>
                    </injection-target>

               <resource-ref>
          </session>
     </enterprise-beans>
</ejb-jar>

– Variáveis de ambiente são definidas no XML e podem ser injetadas com @Resource. Os tipos permitidos são Integer, Long, Double, Float, Byte, Boolean, Short.

 * Exemplo de mapeamento com anotação:

@Stateless
public class MyBean {
     @Resource(name = "minNumber")
     private Integer minNumber;
}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <env-entry>
                    <env-entry-name>minNumber</env-entry-name>
                    <env-entry-type>java.lang.Integer</env-entry-type>
                    <env-entry-value>2000</env-entry-value>

                    <injection-target>
                         <injection-target-class>br.com.MyBean</injection-target-class>
                         <injection-target-name>minNumber</injection-target-name>
                    </injection-target>

               <env-entry>
          </session>
     </enterprise-beans>
</ejb-jar>

Destino de mensagem também utilizam a anotação @Resource.

* Exemplo de mapeamento com anotação:

@Stateless
public class MyBean {
     @Resource(mappedName = "topic/TicketTopic")
     private Topic topic;
}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <message-destination-ref>
                    <message-destination-ref-name>jms/TicketTopic</message-destination-ref-name>
                    <message-destination-type>javax.jms.Topic</message-destination-type>
                    <message-destination-usage>Produces</message-destination-usage>
                    <message-destination-link>Distribuidor</message-destination-link>
                    <mapped-name>topic/TicketTopic</mappedName>

                    <injection-target>
                         <injection-target-class>br.com.MyBean</injection-target-class>
                         <injection-target-name>topic</injection-target-name>
                    </injection-target>

               <message-destination-ref>
          </session>
     </enterprise-beans>
</ejb-jar>

Webservice é injetado com @javax.xml.ws.WebServiceRef que possui os atributos name (JNDI ENC relativo a java:comp/env), wsdlLocation, Class type, Class value, mappedName.

 * Exemplo de mapeamento com anotação:

@Stateless
public class MyBean {
     @WebServiceRef(ProcessorService.class)
     private Processor endpoint;
}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <service-ref>
                    <service-ref-name>service/ProcessorService</service-ref-name>
                    <service-interface>br.com.ProcessorService</service-interface>
                    <wsdl-file>META-INF/wsdl/Processor.wsdl</wsdl-file>
                    <jaxrpc-mapping-file>META-INF/mapping.xml</jaxrpc-mapping-file>
                    <service-qname>chargetIt:ProcessorService</service-qname>
                    <mapped-name>webservice/ProcessorService</mapped-name>

                    <injection-target>
                         <injection-target-class>br.com.MyBean</injection-target-class>
                         <injection-target-name>endpoint</injection-target-name>
                    </injection-target>

               <message-destination-ref>
          </session>
     </enterprise-beans>
</ejb-jar>

Capítulo 15: interceptadores

– Interceptam métodos ou eventos do ciclo de vida dos beans.

Definição de interceptadores

* Exemplo de definição com anotação:

public class Logger {
     @AroundInvoke
     public Object log(InvocationContext ctx) throws Exception {
          // do something...
     }
}

* javax.interceptor.InvocationContext possui os seguintes métodos:

Object getTarget() – referência ao objeto do bean interceptado.

Method getMethod() – dados sobre o método interceptado.

Object[] getParameters() – parâmetros do método interceptado.

void setParameters(Object[] newArgs) – permite alterar os parâmetros do bean interceptado antes de sua invocação.

Map<String, Object> getContextData() – permance ativo durante toda a invocação e permite trocar dados contextuais entre interceptadores

Object proceed() throws Exception

* Exemplo de definição com XML:

<ejb-jar>
     <interceptors>
          <interceptor>
               <interceptor-class>br.Logger</interceptor-class>
               <around-invoke>
                    <method-name>log</method-name>
               </around-invoke>
          </interceptor>
     </interceptors>
</ejb-jar>

Aplicação de interceptadores

* Exemplo de aplicação com anotação:

@Stateless
@Interceptors({MyInterceptor1.class, MyInterceptor2.class})
public class MyBean {

}

* javax.interceptor.Interceptors pode ser aplicado em classe ou métodos e possui o atributo Class[] value.

* Exemplo de aplicação com XML:

<ejb-jar>
     <assembly-descriptor>
          <interceptor-binding>
               <interceptor-class>br.Logger</interceptor-class>
               <exclude-default-interceptors />
               <ejb-name>MyBean</ejb-name>
               <method-name>myMethod</method-name> 
               <method-params>
                    <method-param>double</method-param>
               </method-params>
          </interceptor-binding>
     </assembly-descriptor>
</ejb-jar>

Exclusão de Interceptadores

@ExcludeDefaultInterceptors ou <exclude-default-interceptors /> pode ser aplicado a classe ou método e desabilita os interceptadores defaults.

@ExcludeClassInterceptors ou <exclude-class-interceptors /> pode ser aplicado em método para desabilitar os interceptadores da classe.

– Interceptação de eventos do ciclo de vida

* Além dos métodos de negócio do bean, também podem ser interceptados métodos de callback de eventos do ciclo de vida do bean.

* Exemplo de mapeamento com anotação:

public void Logger {

     @PostConstruct
     public void log(InvocationContext ctx) {
          // do something...
     }
}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <interceptors>
          <interceptor>
               <interceptor-class>br.Logger</interceptor-class>
               <post-construct>
                    <lifecycle-callback-method>log</lifecycle-callback-method>
               </post-construct>
          </interceptor>
     </interceptors>
</ejb-jar>

<lifecycle-callback-method> define o método do interceptador que deve interceptar determinado evento de callback dos beans interceptados.

* Se o bean não possue método de tratamento do callback interceptado, somente os interceptadores são chamado (no-op) e InvocationContext.getMethod() retorna sempre null.

* Pode ser usado interceptadores de @PostConstruct para implementar injeção de dependência de recursos customizados com anotações customizadas.

* Interceptadores possuem o mesmo ciclo de vida que os EJBs ao qual interceptam.

* É possível adicionar um método @AroundInvoke na própria classe do bean. Nesse caso será o último “interceptador” antes do método de negócio.

Capítulo 16: transações

ACID

– A (Atômica): cada parte da transação deve executar sem erros, caso contrário a operação toda é revertida (ou tudo, ou nada).

– C (Consistente): dados devem manter-se íntegros (aplicação também deve assegurar isso).

– I (Isolada): uma transação não deve afetar outro processo ou transação.

– D (Durável): dados devem ser escritos antes da transação terminar com sucesso, evitando que crashes no sistema impeçam a escrita com a transação já concluída.

Gerenciamento declarativo de transações

– O escopo da transação começa na chamada ao EJB e é propagado para todos os componentes envolvidos (EJB, entidade, EntityManager, etc.).

– Container EJB controla as transações implicitamente, mas é possível setar seus atributos com @javax.ejb.TransactionAttribute. Pode ser aplicado a classes ou métodos (prioridade sobre classe). Possui o atributo TransactionAttributeType value.

* TransactionAttributeType possui os valores MANDATORY, REQUIRED (default), REQUIRES_NEW, SUPPORTS, NOT_SUPPORTED, NEVER.

* Exemplo de mapeamento com anotação:

@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Stateless
public class MyBean {

}

* Exemplo de mapeamento com XML:

<ejb-jar>
     <assembly-descriptor>
          <container-transaction>
               <method>
                    <ejb-name>TravelAgentEJB</ejb-name>
                    <method-param>*</method-param>
               </method>
               <trans-attribute>Required</trans-attribute>
          </container-transaction>
     </assembly-descriptor>
</ejb-jar>

* Tipos de atributos de transação:

NOT_SUPPORTED: transação não propagada (suspensa) no EJB “Not supported” ou quaisquers outros EJBs chamados por ele. Quando o método acaba, a transação original é resumida.

SUPPORTS: transação propagada se chamador possui escopo transacional, mas não propagada caso contrário.

REQUIRED: Sempre executa dentro de um contexto transacional, seja aproveitando o escopo do chamador ou, caso chamador fora de um contexto transacional, cria seu próprio.

REQUIRES_NEW: Sempre inicia um novo escopo transacional, independente do chamador.

MANDATORY: EJB deve ser invocado a partir de um escopo transacional ou será disparada EJBTransactionRequiredException.

NEVER: Se for invocado dentro de um contexto transacional dispara EJBException.

– Em MDBs apenas NOT_SUPPORTED e REQUIRED podem ser utilizados, já que os outros estados se referem ao cliente chamador, que o MDB não tem.

– Em EJB Endpoints não se pode usar MANDATORY, pois não propaga a transação do cliente.

Regras de propagação

* Quando um EntityManager em escopo de transação é invocado fora de transação, ele cria seu próprio escopo de persistência e quaisquers objetos gerenciados são desacoplados.

* Quando um EntityManager em escopo de transação é invocado de dentro de escopo transacional, aproveita o contexto de persistência ou cria um novo se não existe (propagação do contexto de persistência).

* Se um EJB com um contexto de persistência de transação invoca um stateful com contexto de persistência estendido é disparado um erro.

* Se um stateful estendido invoca um EJB de escopo transacional, o escopo do contexto de persistência é propagado.

* Se um EJB invoca outro de um diferente escopo de transação, o contexto de persistência não é propagado.

* Se um stateful estendido invoca outro com escopo estendido, um erro ocorre, pois stateful injetado em outro deve compartilhar o mesmo contexto de persistência.

– Isolamento

Dirty Reads: ocorre quando uma transação lê dados ainda não comitados feitos por outra transação (se a transação for rolledBack, os dados ficarão inconsistentes).

Repeatable Reads: garante que mesmas leituras na mesma transação retornem sempre o mesmo resultado. Pode ser feito com lock, que impede outra transação de alterar ou com snapshot do dado, que retorna os mesmos dados durante a transação.

* Phantom Reads: no curso de uma transação, duas leituras iguais apresentam resultados diferentes porque outra transação alterou os dados.

Locks

– Controlam como transações acessam dados concorrentemente.

– Tipos de Lock

Read Locks: transações podem ler dados, mas não escrever (pode ser em nível de registro, bloco de registros ou tabela).

Write Locks: previne outras transações de fazer escritas, mas a transação com o lock pode, o que pode gerar dirty reads (ler dados não comitados) pelas outras transações e pela própria que escreve.

Exclusive Write Locks: não permite que outras transações leiam ou escrevam até a transação com o lock acabar.

Snapshots: cada transação trabalha com um snapshot do início da transação.

– Níveis de isolamento de transações

Read uncommited: permite ler dados não comitados.

Read commited: dados sendo alterados por outras transações não podem ser lidos.

Repeatable reads: dados sendo lidos por outras transações não podem ser alterados.

Serializable: a transação possui privilégios de leitura e escrita exclusivos.

Consistência e performance são inversamente proporcionais.

– O nível de isolamento pode ser definido na API de banco (JDBC): conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE).

Lock otimista: design pattern no qual a tabela possui uma coluna de versão anotada com @Version, atualizada a cada commit. Antes de comitar, sistema verifica se a versão já foi atualizada por outra transação. Em caso afirmativo, efetua o rollback e lança javax.persistence.OptimisticLockException. Locks otimistas priorizam escalabilidade/performance.

Lock programático: permite criar lock programaticamente. EntityManager.lock(Object entity, LockModeType type).

LockModeType possui os valores READ e WRITE.

* Exemplo de lock:

em.lock(myEntity, LockModeType.READ);

– Tornar um EJB fora do escopo transacional garente maior performance (NOT_SUPPORTED, por exemplo).

Gerenciamento explícito de transações

– É feito utilizando-se do OTS (Object Transaction Service), na implementação da OMG ou do Java (JTA).

– javax.transaction.UserTransaction permite administrar o escopo da transação explicitamente.

* O objeto UserTransaction pode ser obtido a partir do método getUserTransaction() do SessionContext, ou injetando com @Resource ou com lookup para java:comp/UserTransaction.

* Possui os seguintes métodos:

void begin() throws IllegalStateException, SystemException – IllegalStateException se já existe uma transação.

void commit() throws IllegalStateException, SystemException, TransactionRolledbackException, HeuristicException, HeuristicMixedException – IllegalStateException se não associado a uma transação.

int getStatus() – retorna uma constante javax.transaction.Status com os seguintes valores possíveis: STATUS_ACTIVE, STATUS_COMMITTED, STATUS_COMMITTING, STATUS_MARKED_ROLLBACK, STATUS_NO_TRANSACTION, STATUS_PREPARED, STATUS_PREPARING, STATUS_ROLLEDBACK, STATUS_ROLLING_BACK, STATUS_UNKNOWN.

void rollback() throws IllegaStateException, SecurityException, SystemException

void setRollbackOnly() throws IllegalStateException, SystemException

void setTransactionTimeout(int seconds) throws SystemException

* Exemplo de gerenciamento explícito de transações:

UserTransaction ut = (UserTransaction) jndiContext.lookup("java:comp/UserTransaction");

ut.begin();
// do something...
ut.commit();

@TransactionManagement pode ser usado para definir se o bean será BTM (transação gerenciada pelo bean) ou CMT (transação gerenciada pelo container, default). Possui o atributo TransactionManagementType value.

TransactionManagementType possui os valores BEAN e CONTAINER.

* Exemplo de mapeamento com anotação:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class MyBean {

}

– Somente beans definidos para gerenciarem suas próprias transações podem gerenciar transações explicitamente.

– Beans com transações gerenciadas pelo container não podem usar o UserTransaction, mas podem setar a transação para rollback usando EJBContext.setRollbackOnly().

– Beans que gerenciam explicitamente transações não devem usar este método do EJBContext, apenas os do UserTransaction.

– getUserTransaction() retorna mesma transação se já existe uma.

Stateless devem começar e acabar transação no mesmo método, pois o mesmo bean pode ser compartilhado por vários clientes.

Stateful pode iniciar transação num método e acabar em outro.

MDBs devem iniciar transação dentro do método onMessage(). A entrega da mensagem não fará parte da mesma transação. E rollback na transação do método não implica em rollback da entrega da mensagem.

Exceções nas transações

– Quando uma RuntimeException (EJBException, etc) é lançada de um método em escopo de transação, o container faz o rollback, loga e descarta a instância.

– Quando uma instância de stateful é descartada, o estado conversacional é perdido e a referência do cliente ao EJB é invalidada, qualquer chamada subsequente resulta em javax.ejb.NoSuchEJBException.

– Quando uma RuntimeException ocorre, se o cliente propagou a transação, o container captura a exceção original e lança uma javax.ejb.EJBTransactionRolledbackException. Caso o cliente não tenha propagado a transação, o container lança javax.ejb.EJBException.

– Exceções de subsistemas (SQLException, por exemplo) no geral fazem com que o container lance uma EJBException/RemoteException.

– Exceções verificadas não causam rollback por default e são propagadas ao cliente sem serem encapsuladas numa EJBException.

– Para forçar o rollback em caso de determinada exceção verificada ser lançada, deve ser  usada a anotação @ApplicationException, que possui o atributo boolean rollback.

* Exemplo de mapeamento com anotação:

@ApplicationException(rollback = true)
public class MyException extends Exception {

}

– Para forçar o não rollback em caso de determina exceção não-verificada, a exceção pode ser anotada com rollback = false. Nesse caso a exceção não é encapsulada em uma EJBExceptin. Caso não tenha acesso a classe da exceção (exceções disparadas por outras libs do projeto, por exemplo), pode ser feito o mapeamento com XML.

* Exemplo de mapeamento com XML:

<ejb-jar>
     <assembly-descriptor>
          <application-exception>
               <exception-class>br.com.MyException</exception-class>
               <rollback>false</rollback>
          </application-exception>
     </assembly-descriptor>
</ejb-jar>

Transações em stateful

– Em stateful as vezes faz sentido “cachear” as alterações fazendo commit/rollback sem ser na mesma invocação de método  (exemplo: carrinho de compras).

– A interface javax.ejb.SessionSynchronization permite estender o ciclo de vida do stateful para receber notificações referentes a transações.

* void afterBegin() throws RemoteException

* void beforeCompletion() throws RemoteException

* void afterCompletion(boolean committed) throws RemoteException

– Ciclo de vida stateful estendido

Ciclo de Vida EJB Stateful Estendido

Figura: Ciclo de vida EJB Stateful Estendido

– Se um stateful está envolvido em uma transação, ele não pode ir para um diferente contexto de transação. Essa nova transação causará um erro. @Remove também causará um erro.

Contexto de persistência conversacional

– Ao criar um contexto de persistência estendido fora de um contexto transacional, as alterações são enfileiradas até que este contexto seja associado a uma transação.

Capítulo 17: segurança

– Fornece Autenticação, Autorização, Confidencialidade e Integridade.

– Apenas sessions beans possuem esquema de segurança.

Autenticação

– A especificação EJB não define como deve ser feita a autenticação, apenas que deve ser CORBA/IIOP. Em geral é feita usando a API JNDI:

properties.put(Context.SECURITY_PRINCIPAL, userName);
properties.put(Context.SECURITY_CREDENTIALS, pass);
InitialContext ic = new InitialContext(properties);
// ...

Autorização

– Autorização é feita definindo-se roles (papéis), atribuindo papéis a usuários e definindo as permissões de acesso baseadas nesses papéis.

– Quando um método é invocado sem permissão, é lançada uma javax.ejb.EJBAccessException.

– Configuração de permissão

* Exemplo de configuração de autorização com anotação:

@Stateless
public class MyBean {
     @RolesAllowed("ADMIN")
     public void do() {
          // do something...
     }
}

@javax.annotation.security.RolesAllowed pode ser usado na classe ou no método para definir os papéis que possuem autorização de acesso. Possui o atributo String[] value:

@javax.annotation.security.PermitAll faz com que todos os papéis possam usar o recurso (é o comportamento default).

* Exemplo de configuração de autorização com XML:

<ejb-jar>
     <assembly-descriptor>
          <security-role>
               <role-name>ADMIN</role-name>
               <description>Administrador do sistema</description>
          </security-role>

          <method-permission>
               <role-name>ADMIN</role-name>
               <method>
                    <ejb-name>MyEJB</ejb-name>
                    <method-name>log</method-name>
               </method>
          </method-permission>

          <method-permission>
               <unchecked />
               <method>
                    <ejb-name>MyEJB</ejb-name>
                    <method-name>log2</method-name>
               </method>
          </method-permission>
     </assembly-descriptor>
</ejb-jar>

<unchecked> é equivalente a @PermitAll.

<method-intf> diferencia métodos em interfaces locais e remotas. Possui os valors Remote, Home, LocalHome, Local, ServiceEndPoint.

– Configuração de negação de permissão

* Exemplo de configuração de negação de autorização com anotação:

@Stateless
public class MyBean {
     @DenyAll
     public void do() {
          // do something...
     }
}

@javax.annotation.security.DenyAll pode ser usado em classe ou método para negar permissão de acesso para todos os papéis.

* Exemplo de configuração de negação de autorização com XML:

<ejb-jar>
     <assembly-descriptor>
          <security-role>
               <role-name>ADMIN</role-name>
               <description>Administrador do sistema</description>
          </security-role>

          <method-permission>
               <exclude-list />
               <method>
                    <ejb-name>MyEJB</ejb-name>
                    <method-name>log2</method-name>
               </method>
          </method-permission>
     </assembly-descriptor>
</ejb-jar>

– Configuração de identidade

* Quando um EJB deve invocar outro, mas sem necessariamente usar as credenciais (papéis) do seu cliente, ele pode definir o papel com o qual deve ser associado nessa nova chamada.

* Exemplo de configuração de identidade com anotação:

@Stateless
@RunAs("Admin")
public class MyBean {
     public void do() {
          // do something...
     }
}

@javax.annotation.security.RunAs define qual deve ser a identidade ao chamar outros serviços. Possui o atributo String value.

* Exemplo de configuração de identidade com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <security-identity>
                    <run-as>
                         <role-name>ADMIN</role-name>
                    </run-as>
               </security-identity>
          </session>
     </enterprise-beans>
</ejb-jar>

* Para garantir que a identidade do cliente seja usada em vez da definida com run-as, deve ser usada a tag <use-caller-identity />:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <security-identity>
                    <use-caller-identity />
               </security-identity>
          </session>
     </enterprise-beans>
</ejb-jar>

– Segurança programática

* Segurança programática pode ser feito utilizando-se dos métodos de EJBContext javax.security.Principal getCallerPrincipal() e boolean isCallerInRole(String roleName),

* Os papéis administrados programaticamente devem ser declarados usando a anotação @javax.annotation.security.DeclareRoles, que possui o atributo String[] value.

* Exemplo de declaração de papéis com anotação:

@Stateless
@DeclareRoles("Admin")
public class MyBean {
     @Resource
     private EJBContext ctx;

     public void do() {
          ctx.isCallerInRole("ADMIN);
          ctx.getCallerPrincipal();
     }
}

* Exemplo de declaração de papéis com XML:

<ejb-jar>
     <enterprise-beans>
          <session>
               <ejb-name>MyBean</ejb-name>
               <security-role-ref>
                    <role-name>ADMIN</role-name>
               </security-role-ref>
          </session>
     </enterprise-beans>
</ejb-jar>

O que vem depois?

Após esta certificação, que cobre as versões JPA 1.0 e EJB 3.0, é hora de se atualizar:

– Java Persistence API:

* JPA 2.0: Versão atual da especificação (na data de publicação deste post):

Especificação JPA 2.0 (JSR #317 – Java Persistence 2.0)

Resumo “O que há de novo na JPA 2.0”

* JPA 2.1 (o futuro): Próxima versão, ainda não finalizada:

Especificação JPA 2.1 (JSR #338 – Java Persistence 2.1)

– Enterprise Java Beans:

* EJB 3.1: Versão atual da especificação (na data de publicação deste post):

Especificação EJB 3.1 (JSR #318 – Enterprise JavaBeans 3.1)

* EJB 3.2 (o futuro): próxima versão, ainda não finalizada:

Especificação EJB 3.2 (JSR #345 – Enterprise JavaBeans 3.2)

Referências

Livro “Enterprise JavaBeans 3.0” – Bill Burke, Richard Monson-Haefel
Especificação “EJB 3.0 (JSR #220 – Enterprise JavaBeans 3.0)”
Artigo “JPA Standalone (Fora do Servidor, Container ou da IDE)” – Vanessa Schissato

 

One comment on “Resumo de estudo para certificação Java Business Component Developer 5 (SCBCD/OCPJBCD 5 – 1Z0-860)

  1. Kelcio Barreto on said:

    Que post top! Muito obrigado!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>