Resumo Anotacoes Certificacao SCBCD 5

58
Resumo_Anotacoes_Certificacao_SCBCD_5.txt =============================================================================== Resumo Anotações para Certificação SCBCD 5.0 Autor: Gilberto Augusto Holms @gibaholms [email protected] http://gibaholms.wordpress.com/ =============================================================================== - Introdução . EJB: Modelo de componentes padrão do lado do servidor para aplicativos de negócio distribuídos - Escalonáveis - Transacionais - Seguros com multi-usuários . Bean de Entidade (JPA): - A JPA pode funcionar sozinha, porém o container EJB3 fornece integração adicional. - É um POJO, e não um componente (como era no 2.1). - Obrigatório uma chave primária ( @Id ), que pode ser um primitivo ou uma classe. - As anotations podem estar tanto nos atributos quanto nos métodos GETTER. . Persistence.xml - É obrigatório - Sobrescreve as annotations - Deployado num JAR junto com as entidades - Pode declarar várias Persistence Units - Persistence Unit -> composta por Entidades, representa uma base de dados . Interfaces de Negocio -> obrigatório ao menos uma interface de negócio - javax.ejb.Local (não utiliza protocolos distribuídos para acessar – apenas mesma JVM) - javax.ejb.Remote - javax.jms.MessageListener - javax.jws.WebService . Container EJB, seis serviços primários: - Concorrência - Transação - Persistência - Distribuição de Objetos - Atribuição de Nomes (JNDI) - Segurança - Mensageria Assíncrona - Temporização . Serviços que melhoram o desempenho para grande número de clientes e beans instanciados: - Pool de instâncias (Beans Stateless e MDB): . Clientes nunca acessam um bean diretamente, portanto o container pode criar um pool de instancias e gerenciá-lo reaproveitando recursos. Uma mesma instância serve vários clientes (um de cada vez). - Ativação (Beans Statefull) . As variáveis de instância do bean são persistidas em um armazenamento secundário, e o bean é removido da memória (apassivação). Quando é invocado outro método, uma nova instância é criada e seu estado anterior é recuperado do armazenamento (ativação). Porém, o Stub não perde a conexão durante a apassivação. Página 1

description

Meus resumos e anotações da época que fiz a prova de certificação java SCBCD 5 (nova OCPBCD).

Transcript of Resumo Anotacoes Certificacao SCBCD 5

Page 1: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt===============================================================================Resumo Anotações para Certificação SCBCD 5.0

Autor: Gilberto Augusto Holms @gibaholms [email protected] http://gibaholms.wordpress.com/

===============================================================================

- Introdução

. EJB: Modelo de componentes padrão do lado do servidor para aplicativosde negócio distribuídos - Escalonáveis - Transacionais - Seguros com multi-usuários . Bean de Entidade (JPA): - A JPA pode funcionar sozinha, porém o container EJB3 fornece integração adicional. - É um POJO, e não um componente (como era no 2.1). - Obrigatório uma chave primária ( @Id ), que pode ser um primitivo ou uma classe. - As anotations podem estar tanto nos atributos quanto nos métodos GETTER.

. Persistence.xml - É obrigatório - Sobrescreve as annotations - Deployado num JAR junto com as entidades - Pode declarar várias Persistence Units - Persistence Unit -> composta por Entidades, representa uma base de dados

. Interfaces de Negocio -> obrigatório ao menos uma interface de negócio - javax.ejb.Local (não utiliza protocolos distribuídos para acessar – apenas mesma JVM) - javax.ejb.Remote - javax.jms.MessageListener - javax.jws.WebService

. Container EJB, seis serviços primários: - Concorrência - Transação - Persistência - Distribuição de Objetos - Atribuição de Nomes (JNDI) - Segurança - Mensageria Assíncrona - Temporização

. Serviços que melhoram o desempenho para grande número de clientes e beans instanciados: - Pool de instâncias (Beans Stateless e MDB): . Clientes nunca acessam um bean diretamente, portanto ocontainer pode criar um pool de instancias e gerenciá-lo reaproveitando recursos. Uma mesma instânciaserve vários clientes (um de cada vez).

- Ativação (Beans Statefull) . As variáveis de instância do bean são persistidas em um armazenamento secundário, e o bean é removido da memória (apassivação). Quando é invocado outro método, uma nova instância é criada e seu estado anterior é recuperado do armazenamento (ativação). Porém, o Stub não perde a conexão durante a apassivação.

Página 1

Page 2: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt . O objeto não precisa ser serializável, o fornecedor escolhe um método de ativação que independa disso. Para atributos transientes, o comportamento depende da implementação do container. . É fornecido o callback @PrePassivate e @PostActivate. Serviços de contexto e o EntityManager devem ser mantidos durante o processo de apassivação.

. Java EE Connectors (JCA) . Fornece mecanismo para criação de interfaces entre o containere sistemas legados, permitindo que os legados disparem mensagens para MDBs do conteiner.

. Concorrência: . Beans se sessão não executam em multithread, portanto é proibido utilizar a palavra synchronized e também é proibido criar threads dentro de beans, pois o container precisater certeza que está com o controle sobre o comportamento de todas as instancias do bean. . Beans de entidade podem ser acessados de forma concorrente, o container pode utilizar Optimistic Locking ou isolamento Serialized no JDBC. . Beans de mensagem podem processar mensagens simultaneamente, onde cada instancia do pool pode processar uma mensagem. - Session Beans

. Interface Remota - Todos os parametros são copiados, inclusive os objetos, mesmo se estiver na mesma JVM (chamada "por valor")

@Remote public interface MyBusinessInterfaceRemote { ... } . Interface Local - Precisa estar na mesma JVM - Os parametros possuem comportamento normal, onde objetos são passados por referência (chamada "por referência)

@Local public interface MyBusinessInterfaceLocal { ... }

. Obs.: - Parametros de tipo objeto precisam extender Serializable ou Externalizable para poderem ser transferidos pela rede - Podem lançar exceções. Deve-se lançar apenas exceções de negócio, e não de subsistemas Java - Uma exceção de aplicativo é propagada ao cliente, e qualquer variável de instância dela deve ser serializavel - Todas exceções de runtime são capturadas pelo container e empacotadas em EJBException - Pode declarar @Local(MyBusinessInterfaceLocal.class) no próprio bean, não precisando ele declarar a implementação da interface explicitamente e nem precisando anotar a interface. Idem para @Remote . Descritor de Implantação - Fica dentro do JAR do projeto EJB, em: META-INF/ejb-jar.xml . Exemplo de EJB via XML

<ejb-jar> <enterprise-beans>

Página 2

Page 3: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt <session> <ejb-name>ProcessPaymentBean</ejb-name> <remote>com.titan.processpayment.ProcessPaymentRemote</remote> <local>com.titan.processpayment.ProcessPaymentLocal</local> <ejb-class>com.titan.processpayment.ProcessPaymentBean</ejb-class> <session-type>Stateless</session-type> </session> </enterprise-beans> </ejb-jar> - SessionContext public interface javax.ejb.SessionContext extends javax.ejb.EJBContext { MessageContext getMessageContext( ) throws IllegalStateException; <T> getBusinessObject(Class<T> businessInterface) throws IllegalStateException; Class getInvokedBusinessInterface( ); //METODOS OBSOLETOS - LANÇAM EXCEPTION SE CHAMADOS EJBLocalObject getEJBLocalObject( ) throws IllegalStateException EJBObject getEJBObject( ) throws IllegalStateException; } . getBusinessObject Retorna uma referência (do tipo da interface de parametro) ao objeto EJB atual. É ilegal que um bean envie uma referencia this para outro bean, para isso serve este método . getInvokedBusinessInterface Retorna a classe da interface de negócio invocada para obean atual

. Obs.: - Herda mais todos os métodos de EJBContext - O container injeta o SessionContext via anotação @Resource - EJBContext

public interface EJBContext {

public Object lookup(String name);

// security methods public java.security.Principal getCallerPrincipal( ); public boolean isCallerInRole(java.lang.String roleName);

// transaction methods public javax.transaction.UserTransaction getUserTransaction( ) throws java.lang.IllegalStateException; public boolean getRollbackOnly( ) throws java.lang.IllegalStateException; public void setRollbackOnly( ) throws java.lang.IllegalStateException;

// OBSOLETO public TimerService getTimerService( ) throws java.lang.IllegalStateException; // METODOS OBSOLETOS - LANÇAM RuntimeException SE CHAMADOS public java.security.Identity getCallerIdentity( ); public boolean isCallerInRole(java.security.Identity role); public java.util.Properties getEnvironment( );

Página 3

Page 4: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt public EJBHome getEJBHome( ) java.lang.IllegalStateException; public EJBLocalHome getEJBLocalHome( ) java.lang.IllegalStateException; public Properties getEnvironment(); }

. getCallerPrincipal Retorna o objeto Principal referente a quem está acessando o bean . isCallerInRole Retorna se o usuário atual pertence a determinada role . lookup Permite pesquisar entradas no ENC do EJB.

-------------------------------------------------------------------------------- ------------------------------------------

- Stateless Session Beans

@Stateless public class MyBean implements MyBusinessInterface {...}

. Ciclo de Vida (TODO) . Precisa de um construtor padrão . Métodos de ciclo de vida: @PostConstruct Após o conteiner instanciar o bean (não significa sair do pool) @PreDestroy Antes do container destruir o bean (não significa voltarpro pool). Durante a chamada, ainda estão disponíveis SessionContext e JNDI ENC . Obter a referência remota não indica que o bean saiu do pool. O bean sai do pool e é configurado para o cliente apenas depois que o cliente invoca o primeiro método do bean

-------------------------------------------------------------------------------- ------------------------------------------

- Statefull Sessson Beans

@Statefull public class MyBean implements MyBusinessInterface {...}

. Ciclo de Vida (TODO) . Precisa de um construtor padrão . Métodos de ciclo de vida: @PostConstruct Após o conteiner instanciar o bean @PreDestroy Antes do container destruir o bean. Durante a chamada, ainda estão disponíveis SessionContext e JNDI ENC @PrePassivate Antes do bean ser apassivado (serializado para armazenamento de estado). Deve liberar recursos e setar campos transient com valores nulos. Objetos que são passivados e gerenciados automaticamente: - Tipos primitivos

Página 4

Page 5: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt - Qualquer objeto java serializavel - SessionContext - UserTransaction - javax.naming.Context - EntityManager - EntityManagerFactory - Fabricas injetadas por @Resource - Referencias injetadas por @EJB @PostActivate Depois do bean ser ativado (desserializado para recuperação de estado). Foge à regra da desserialização java no que se trata de variáveis transient, cujo valor assumido será aleatório, e não o valor padrão, portanto este método deve reabrir os recursos e setar essas variáveis . O beans Statefull é removido da memória quando: - É chamado o método @Remove - O container detecta que deu timeout e o bean expirou (não podeexpirar durante uma transação) - @PreDestroy é chamado apenas no caso do @Remove. Em caso de expiração, depende do fornecedor a chamada desse método ou não . Apenas obter a referência remota já cria uma sessão dedicada ao cliente, porém não cria a instância. A instância é criada depois de chamar o primeiro método do bean . No caso de beans Statefull aninhados, a sessão do filho pertence ao pai, ou seja, se o cliente remove o pai, o pai remove o filho automaticamente . Contexto de Persistencia Extendido: - Pode apenas em bean Statefull - Faz com que todas as Entidades mantenham-se gerenciadas durante diferentes invocações de métodos - Se ele contiver outro bean Statefull aninhado, e esse bean: tiver interface local e também tiver contexto extendido, os dois beans compartilham o mesmo contexto de persistencia extendido (mesmo EntityManager)

- Entity Manager

@Stateless public class MyBean implements MyBusinessInterface { @PersistenceContext(unitName="titan", type=PersistenceContextType.TRANSACTION) private EntityManager manager; ... } . Atributo type é opcional, o padrão vem TRANSACTION, mas podemos optar por EXTENDED. Se for TRANSACTION, diferentes instancias de EntityManager injetadas em beans diferentes estarão no mesmo contexto de persistência, até que a transação geral termine O tipo EXTENDED pode ser utilizado apenas em beans @Statefull, e esse contexto dura o mesmo tempo de vida da instancia do bean (as transações em particular precisam ser demarcadas).

. Contexto de Persistência Tempo em que as entidade são gerenciadas pelo EntityManager. Quando o contexto de persistencia acaba, todas as entidades tornam-se detached.

Página 5

Page 6: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt . Escopo de Transação PersistenceContextType.TRANSACTION O contexto de persistência dura exatamente o tempo de uma transação JTA, pode apenas ser utilizado em servidores J2EE, com entidades injetadas via @PersistenceContext PersistenceContextType.EXTENDED O contexto de persistência permanece ativo durante várias transações, pode ser utilizado apenas em beans Statefull . Arquivo persistence.xml É obrigatório: <persistence> <persistence-unit name="titan"> <jta-data-source>java:/OracleDS</jta-data-source> <properties> <propertie name="org.hibernate.hbm2ddl">update</propertie> </properties> </persistence-unit> </persistence> Obs.: <persistence-unit> atributo name – obrigatório atributo transaction-type – opcional (conf. JTA para servers J2EE ou RESOURCE_LOCAL para Java SE) outras tags opcionais: <description> <provider> : provedor de persistência (para J2EEvem o default do container) <non-jta-data-source> <mapping-file> : outro arquivo de mapeamento (container procura orm.xml e outros listados aqui) <jar-file> : carregar outro jar de entidades <class> : carregar classes específicas <exclude-unlisted-classes> : não carregar qualquer classe que não esteja declarada no persistence.xml (o jar default é ignorado)

. Empacotamento Sempre um arquivo jar com persistence.xml dentro de seu META-INF(se houver, o arquivo orm.xml também deve estar nessa pasta) . Classpath Java SE <JAR AQUI> . EJB-JAR . WAR > WEB-INF > lib <JAR AQUI> . EAR <JAR AQUI> . EAR > lib <JAR AQUI> --------------------------------------------------------------------------------------------------------------------------

- Entity Manager Factory

@Stateless public class FactoryBean implements FactoryBusinessInterface {

@PersistenceUnit(unitName=”titan”) private EntityManagerFactory factory1;

private EntityManagerFactory factory2;

Página 6

Page 7: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt @PersistenceUnit(unitName=”toto”) public void setFactory2(EntityManagerFactory factory2) {...}

} . Não pode chamar método close() no EntityManagerFactory nem no EntityManager se eles forem injetados pelo container (lança IllegalStateException), pois o container cuida dessa limpeza. . O container injeta em um atributo ou em um setter . Se criar o EntityManager utilizando o factory, as transações serão de escopo extendido, ou seja, é preciso chamar EntityManager.joinTransaction()

--------------------------------------------------------------------------------------------------------------------------

- Métodos de EntityManager

persist(Object entity) .Enfileira a entidade para criação no banco (não representa o momento real do insert) . É possível chamar persist fora de uma transação apenas se o contexto for EXTENDED, nesse caso, a inserção é enfileirada até o contexto ser associado com uma transação . Se o parâmetro não for uma entidade, lança IllegalArgumentException . Se for invocado fora do contexto de transação e for tipo TRANSACTION, lança uma TransactionRequiredException

joinTransaction() . Usado apenas se o contexto for criado pela EntityManagerFactory . Associa o contexto de persistência à transação . Obs.: se o contexto for gerenciado pelo container, ele é associado automaticamente (não precisa desse método)

find(Class<T> entityClass, Object pk) : Entidade getReference(Class<T> entityClass, Object pk) : Entidade . Retornam uma entidade a partir de sua chave primária . O find, se não encontrar retorna null, e utiliza as configurações de lazy-loading . O getReference, se não encontrar lança EntityNotFoundException . Se o contexto de persistência estiver ativo, ela é acoplada, senão ela é desacoplada

createQuery e createXXXQuery . Executam querys EJB-QL e consultas nativas (retornam um objetoQuery) . Entidades retornadas permanegem gerenciadas enquanto o contexto de persistência estiver ativo

flush() . Sincroniza as atualizações no banco antes de terminar a transacao

merge(Object entity) : Entidade . Atualiza uma entidade desacoplada e retorna uma cópia dela acoplada . ATENÇÃO: o objeto de parâmetro nunca é gerenciado pelo EntityManager, e sim sua cópia que retorna. Se ele já estiver gerenciado a mesma instancia, ele atualiza ela e retorna sua referencia.

remove(Object entity) Remove a entidade da base e torna ela desacoplada

refresh(Object entity) . Atualiza a entidade acoplada com os dados da base

Página 7

Page 8: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt . Se ela não for acoplada ao próprio EntityManager que invoca o método, é lançada IllegalArgumentException . Se o objeto não estiver mais no banco devido outra Thread ou Processo ter removido ele, será lançado EntityNotFoundException

contains(Object entity) : Boolean . Retorna true se a entidade estiver acoplada, false caso contrario.

clear() . Desacopla todas as entidades atuais gerenciadas pelo EntityManager . Suas modificações são perdidas, portanto é prudente chamar flush() antes.

setFlushMode(FlushModeType tp) . Pode receber FlushModeType.AUTO ou FlushModeType.COMMIT . AUTO - é o padrão, onde a implementação da JPA decide quando quer fazer o flush(), onde é certo apenas que ele fará no final da transação, mas também fazer antes . COMMIT - força para que ele sincronize apenas no finalda transação. COMMIT Melhora a performance pois cada atualização requer um bloqueio, e fazer todas de uma vezé mais rápido

getDelegate() : EntityManagerImpl . Retorna uma instancia ao objeto do fornecedor do implementadorEntityManager, que pode proporcionar extensões à JPA padrão

-------------------------------------------------------------------------------------------------------------------------- - EntityTransaction É a API de transação fornecida como alternativa à JTA. Ela pode ser usada apenas se o atributo transaction-type for RESOURCE_LOCAL. Permite utilizar begin(), commit() e rollback() manualmente.

EntityTransaction et = myEntityManager.getTransaction(); et.begin(); myEntityManager.persist(myEntity); et.commit(); . O método begin() lança IllegalStateException se já houver uma transação ativa, commit() e rollback() lançam a mesma exceção se não houver transação ativa. - Criando Entidades

@Entity @Table(name="CUSTOMER_TABLE", catalog="TITAN", schema="TITAN", uniqueConstraints=@UniqueConstraint(columnNames={"EMP_ID", "EMP_NAME"}) ) public class Customer { @Id @GeneratedValue @Column(name="CUST_ID", nullable=false, columnDefinition="integer") private int id; @Column(name="FIRST_NAME", length=20, nullable=false) private String firstName;

Página 8

Page 9: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt ... } <entity-mappings> <entity class="com.titan.domain.Customer" access="PROPERTY"> <!-- PROPERTY e FIELD não se misturam --> <table name="CUSTOMER_TABLE"> <unique-constraint> <column-name>SOME_OTHER_ATTRIBUTE</column_name> </unique-constraint> </table> <attributes> <id name="id"> <column name="CUST_ID" nullable="false" column-definition="integer"/> <generated-value strategy="AUTO"/> </id> <basic name="firstName"> <column name="FIRST_NAME" nullable="false" length="20"/> </basic> </attributes> </entity> </entity-mappings>

--------------------------------------------------------------------------------------------------------------------------

- Tipos de geradores de PK

@GeneratedValue ou @GeneratedValue(strategy=GeneratorType.AUTO) <attributes> <id name="id"> <generated-value strategy="AUTO"/> </id> </attributes>

@TableGenerator(name="CUST_GENERATOR" table="GENERATOR_TABLE" pkColumnName="PRIMARY_KEY_COLUMN" valueColumnName="VALUE_COLUMN" pkColumnValue="CUST_ID" allocationSize=10 ) @GeneratedValue(strategy=GenerationType.TABLE, generator="CUST_GENERATOR") <table-generator name="CUST_GENERATOR" table="GENERATOR_TABLE" pk-column-name="PRIMARY_KEY_COLUMN" value-column-name="VALUE_COLUMN" pk-column-value="CUST_ID" allocation-size="10" /> <attributes> <id name="id"> <generated-value strategy="TABLE" generator="CUST_GENERATOR"/> </id> </attributes> @SequenceGenerator(name="CUSTOMER_SEQUENCE", sequenceName="CUST_SEQ") @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="CUSTOMER_SEQUENCE") <sequence-generator name="CUSTOMER_SEQUENCE"

Página 9

Page 10: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt sequence-name="CUST_SEQ" initial-value="0" allocation-size="50"/> <attributes> <id name="id"> <generated-value strategy="SEQUENCE" generator="CUSTOMER_SEQUENCE"/> </id> </attributes>

--------------------------------------------------------------------------------------------------------------------------

- PK Compostas: Por PK Class

public class CustomerPK implements java.io.Serializable { private String lastName; private long ssn;

public String getLastName( ) { return this.lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public long getSsn( ) { return ssn; } public void setSsn(long ssn) { this.ssn = ssn; }

public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof CustomerPK)) return false; CustomerPK pk = (CustomerPK)obj; if (!lastName.equals(pk.lastName)) return false; if (ssn != pk.ssn) return false; return true; }

public int hashCode( ) { return lastName.hashCode( ) + (int)ssn; } } @Entity @IdClass(CustomerPK.class) public class Customer { private String firstName; private String lastName; private long ssn;

@Id public String getLastName( ) { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; }

@Id public long getSsn( ) { return ssn; } public void setSsn(long ssn) { this.ssn = ssn; } }

Requerimentos para a PK Class: . It must be serializable . It must have a public no-arg constructor . It must implement the equals( ) and hashCode( ) methods.

- PK Compostas: Por Embeddable Class

@Embeddable public class CustomerPK implements java.io.Serializable { private String lastName; private long ssn;

Página 10

Page 11: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt

public String getLastName( ) { return this.lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public long getSsn( ) { return ssn; } public void setSsn(long ssn) { this.ssn = ssn; }

public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof CustomerPK)) return false; CustomerPK pk = (CustomerPK)obj; if (!lastName.equals(pk.lastName)) return false; if (ssn != pk.ssn) return false; return true; }

public int hashCode( ) { return lastName.hashCode( ) + (int)ssn; } }

@Entity public class Customer { private String firstName; private CustomerPK pk;

@EmbeddedId public PK getPk( ) { return pk; } public void setPk(CustomerPK pk) { this.pk = pk; } } Obs.: Podemos sobrescrever as anotações @Column feitas na classe da PK (não podemos utilizar @Column na classe entidade, pois o nome da coluna á definida na classe de PK) @EmbeddedId @AttributeOverrides({ @AttributeOverride(name="lastName", column=@Column(name="LAST_NAME"), @AttributeOverride(name="ssn", column=@Column(name="SSN")) })

--------------------------------------------------------------------------------------------------------------------------

- Mapeando Atributos

@Transient Campo não é criado na base @Basic(fetch=FetchType.LAZY, optional=false) Se o campo é obrigatório, e permite lazy loading do campo (poréma especificação não garante o lazy loading real, depende da implementação) @Temporal(TemporalType.TIME) Define o tipo real a gerar na base para um tipo de data java (DATE, TIME, TIMESTAMP)

@Lob Define que será um tipo binário (blob) ou um tipo sequencial de caracteres (clob). O tipo real gerado depende do tipo de atributo: BLOB: byte[], Byte[], or java.io.Serializable CLOB: char[], Character[], or java.lang.String @Enumerated(EnumType.STRING)

Página 11

Page 12: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt Para mapear um atributo do tipo enum. Pode ser ORDINAL ou STRING, onde ORDINAL grava o numero do indice do campo no enum e STRING grava o proprio nome do enum.

--------------------------------------------------------------------------------------------------------------------------

- Mapeamentos Multi-Table

@Entity @SecondaryTable(name="ADDRESS_TABLE", pkJoinColumns={@PrimaryKeyJoinColumn(name="ADDRESS_ID")}) public class Customer { private long id; private String firstName; private String street; private String city; ... @Column(name="STREET", table="ADDRESS_TABLE") public String getStreet( ) { return street; } public void setStreet(String street) { this.street = street; }

@Column(name="CITY", table="ADDRESS_TABLE") public String getCity( ) { return city; } public void setCity(String city) { this.city = city; } ... }

Obs.: É suportado mais de uma tabela secundária: @SecondaryTables({ @SecondaryTable(name="ADDRESS_TABLE", pkJoinColumns={@PrimaryKeyJoinColumn (name="ADDRESS_ID")}), @SecondaryTable(name="CREDIT_CARD_TABLE", pkJoinColumns={@PrimaryKeyJoinColumn (name="CC_ID")}) })

--------------------------------------------------------------------------------------------------------------------------

- Campos de Embeddable Objects

@Embeddable public class Address { private String street; private String city; private String state; }

@Entity public class Customer { private long id; private String firstName; private String lastName; @Embedded private Address address; } Obs.: como as colunas geradas pela classe embedded são definidas dentro dela, também vale o conceito de @AttributeOverrides para definir outras caracteristicas de coluna dentroda classe utilizadora --------------------------------------------------------------------------------------------------------------------------

- Unidirecional "Um-Para-Um"

Página 12

Page 13: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt@Entitypublic class Customer {... @OneToOne(cascade={CascadeType.ALL}) private Address address;...}

<entity-mappings> <entity class="com.titan.domain.Customer" access="FIELD"> <!-- ou access="PROPERTY" --> <attributes> <id name="id"> <generated-value/> </id> <one-to-one name="address" targetEntity="com.titan.domain.Address" fetch="LAZY" optional="true"> <cascade>ALL</cascade> <!-- ou <cascade-all/> --> <join-column name="ADDRESS_ID"/> <!-- ou <primary-key-join-column/> --> </one-to-one> </attributes> </entity></entity-mappings>

--------------------------------------------------------------------------------------------------------------------------

- Bidirecional "Um-Para-Um"

@Entitypublic class Customer {... @OneToOne(cascade={CascadeType.ALL}) private CreditCard creditCard;...}

@Entitypublic class CreditCard {... @OneToOne(mappedBy="creditCard") private Customer customer;...}

<entity-mappings> <entity class="com.titan.domain.Customer" access="FIELD"> ... </entity> <entity class="com.titan.domain.CreditCard" access="FIELD"> <attributes> <id name="id"> <generated-value/> </id> <one-to-one name="customer" target-entity="com.titan.domain.Customer" mapped-by="creditCard"/> </attributes> </entity></entity-mappings>

--------------------------------------------------------------------------------------------------------------------------

- Unidirecional "Um-Para-Muitos"

@Entity

Página 13

Page 14: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txtpublic class Customer {... @OneToMany(cascade={CascadeType.ALL}) @JoinColumn(name="CUSTOMER_ID") private Collection<Phone> phoneNumbers = new ArrayList<Phone>( );...}

<entity-mappings> <entity class="com.titan.domain.Customer" access="FIELD"> <attributes> <id name="id"> <generated-value/> </id> <one-to-many name="phones" targetEntity="com.titan.domain.Phone"> <cascade-all/> <join-column name="CUSTOMER_ID"/> <!-- ou <join-table name="CUSTOMER_PHONE"> --> </one-to-many> </attributes> </entity></entity-mappings>

--------------------------------------------------------------------------------------------------------------------------

- Unidirecional "Muitos-Para-Um"

@Entitypublic class Cruise {... @ManyToOne @JoinColumn(name="SHIP_ID") private Ship ship;...}

<entity-mappings> <entity class="com.titan.domain.Cruise" access="FIELD"> <attributes> <id name="id"> <generated-value/> </id> <many-to-one name="ship" target-entity="com.titan.domain.Ship" fetch="EAGER"> <join-column name="SHIP_ID"/> </many-to-one> </attributes> </entity></entity-mappings>

--------------------------------------------------------------------------------------------------------------------------

- Bidirecional "Um-Para-Muitos" / "Muitos-Para-Um"

@Entitypublic class Reservation {... @ManyToOne @JoinColumn(name="CRUISE_ID") private Cruise cruise;...}

@Entitypublic class Cruise {

Página 14

Page 15: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt... @OneToMany(mappedBy="cruise") private Collection<Reservation> reservations = new ArrayList<Reservation>( );...}

<entity-mappings> <entity class="com.titan.domain.Cruise" access="FIELD"> <attributes> <id name="id"> <generated-value/> </id> <one-to-many name="ship" target-entity="com.titan.domain.Reservation" fetch="LAZY" mapped-by="cruise" /> </attributes> </entity> <entity class="com.titan.domain.Reservation" access="FIELD"> <attributes> <id name="id"> <generated-value/> </id> <many-to-one name="cruise" target-entity="com.titan.domain.Cruise" fetch="EAGER"> <join-column name="CRUISE_ID"/> </many-to-one> </attributes> </entity></entity-mappings>

--------------------------------------------------------------------------------------------------------------------------

- Unidirecional "Muitos-Para-Muitos"

@Entitypublic class Reservation {... @ManyToMany private Set<Customer> customers = new HashSet<Customer>( );... }

<entity-mappings> <entity class="com.titan.domain.Reservation" access="PROPERTY"> <attributes> <id name="id"> <generated-value/> </id> <many-to-many name="cabins" target-entity="com.titan.domain.Cabin" fetch="LAZY" /> </attributes> </entity></entity-mappings>

--------------------------------------------------------------------------------------------------------------------------

- Bidirecional "Muitos-Para-Muitos"

@Entitypublic class Reservation {... @ManyToMany @JoinTable(name="RESERVATION_CUSTOMER", joinColumns={@JoinColumn(name="RESERVATION_ID")}, inverseJoinColumns={@JoinColumn(name="CUSTOMER_ID")} )

Página 15

Page 16: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt private Set<Customer> customers = new HashSet<Customer>( );... }

@Entitypublic class Customer {... @ManyToMany(mappedBy="customers") private Collection<Reservation> reservations = new ArrayList<Reservation>( );...}

<entity-mappings> <entity class="com.titan.domain.Reservation" access="FIELD"> <attributes> <id name="id"> <generated-value/> </id> <many-to-many name="customers" target-entity="com.titan.domain.Customer" fetch="LAZY"> <join-table name="RESERVATION_CUSTOMER"> <join-column name="RESERVATION_ID"/> <inverse-join-column name="CUSTOMER_ID"/> </join-table> </many-to-many> </attributes> </entity> <entity class="com.titan.domain.Customer" access="FIELD"> <attributes> <id name="id"> <generated-value/> </id> <many-to-many name="cruise" target-entity="com.titan.domain.Reservation" fetch="LAZY" mapped-by="customers" /> </attributes> </entity></entity-mappings>

-------------------------------------------------------------------------------------------------------------------------- @PrimaryKeyJoinColumn Utilizado no OneToOne, quando queremos que a associação não utilize um campo de chave estrangeira, neste caso a associação será feita gravando IDs de mesmo valor nas duas tabelas @PrimaryKeyJoinColumns({ @PrimaryKeyJoinColumn(name="ADDR_ID"), @PrimaryKeyJoinColumn(name="ADDR_ZIP") }) @JoinColumn(name="TOTO_ID") Indica a coluna que receberá a chave primária da outra tabela. Se quiser que referencia outra coluna que não seja a chave primária da tabela, utilizar o atributo referencedColumnName (porem coluna nao pode ter repetição)

@JoinColumns({ @JoinColumn(name="ADDR_ID"), @JoinColumn(name="ADDR_ZIP") }) É utilizado para chaves primárias compostas por mais de uma coluna

Página 16

Page 17: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt @JoinTable É utilizada uma tabela de junção de IDs para relacionamentos Um-Para-Muitos e Muitos-Para-Um Um-Para-Muitos: @JoinTable é padrão Muitos-Para-Um: @JoinColumn é padrão Muitos-Para-Muitos: apenas @JoinTable @OrderBy("lastname ASC, firstname DESC") Permite ordenação, serve apenas para relacionamento com List

@MapKey(name="number") É utilizado para relacionamento com Map. O atributo name será o da key do Map, e a entidade relacionada será o value FetchType.EAGER e FetchType.LAZY (cuidados) Se a entidade estiver "detached" e seu relacionamento LAZY não for carregado, e tanter ser acessado, será lançada uma exceção do provedor de persistência (uma chamada ao .size() da coleção do relacionamento garante o load da coleção, ou o uso do operador FETCH JOIN da ejbql) Cruise detachedCruise = ... ; try { int numReservations = detachedCruise.getReservations().size(); } catch (SomeVendorLazyInitializationException ex) { } CascadeType - ALL, PERSIST, MERGE, REMOVE, REFRESH Realiza a respectiva operação do EntityManager para todas as entidades relacionadas. Aumenta a carga de calls na base e pode causar efeitos indesejáveis - Herança: Single Table Per Class

Schema: é gerada uma tabela contendo todos os atributos de toda a hierarquia, adicionando uma coluna discriminadora, que identifica qual é o tipo.

Person > Customer > Employee @Entity @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="DISCRIMINATOR", discriminatorType=DiscriminatorType.STRING) @DiscriminatorValue("PERSON") public class Person { ... }

@Entity @DiscriminatorValue("CUST") public class Customer extends Person { ... } @Entity public class Employee extends Customer { ... } Obs.: @DiscriminatorColumn Pode ser STRING, CHAR ou INTEGER. Não é obrigatório, se omitido o default é STRING e o nome é gerado pelo fornecedor. @DiscriminatorValue Não é obrigatório, se omitido utiliza o nome da classe. Vantagens: É simples e performática, não requer joins e é boa para selects polimorficos. Desvantagens: Todas as colunas de todas as subclasses precisam ser NULLABLE, e não possui um modelo normalizado.

Página 17

Page 18: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt- Herança: Table Per Concrete Class Schema: é gerada uma tabela para cada classe concreta, cada tabela contendo todos os atributos dessa classe e todos seus atributos herdados. Person > Customer > Employee @Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public class Person { ... }

@Entity public class Customer extends Person { ... } @Entity public class Employee extends Customer { ... }

Obs.: Vantagens: Pode ter constraints NOT NULL em qualquer campo, e o legado pode estar modelado dessa forma. Desvantagens: É mais lento, não é normalizado, possui campos redundantes e tem baixa performance num select polimorfico. - Herança: Table Per SubClass Schema: é gerada uma tabela para cada classe, cada tabela contendo apenas os atributos da classe, onde todas as tabelas são associadas pelas suas chaves primárias. Person > Customer > Employee @Entity @Inheritance(strategy=InheritanceType.JOINED) public class Person { ... }

@Entity public class Customer extends Person { ... } @Entity @PrimaryKeyJoinColumn(name="EMP_PK") public class Employee extends Customer { ... } Obs.: A anotação @PrimaryKeyJoinColumn é obrigatória se as colunas daschaves primárias possuirem nomes diferentes nas tabelas. Vantagens: Pode ter constraints NOT NULL em qualquer campo e seu modelo é normalizado. Desvantagens: É mais lento que a SINGLE_TABLE.

- Herança: Nonentity Base Classes

@MappedSuperclass public class Person { @Id @GeneratedValue private int id; private String lastname; ... }

Página 18

Page 19: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt @Entity @AttributeOverride(name="lastname", column=@Column(name="SURNAME")) public class Customer extends Person { ... } Obs.: A superclasse não é uma entidade e nem é persistida, ela apenas fornece atributos persistentes para as suas subclasses, que podem ser sobrecarregados com o @AttributeOverrides / @AttributeOverride - Metodos de Callback

@PrePersist - Quando uma entidade é agendada para inserção no banco de dados . Depois de persist() . Depois de merge() caso haja inserção aninhada em cascata

@PostPersist - Quando a inserção real no banco de dados ocorre efetivamente . Depois do flush() se houver inserção infileirada . Depois que o contexto de persistencia atualiza o bancode dados (se for FlushType.COMMIT, é no final da transação) @PostLoad - Depois da entidade ser hidradata com os dados da base . Depois do find(), getReference() ou uma consulta EJB-QL @PreUpdate - Antes da entidade ser atualizada no banco de dados . Antes do flush() ou antes de o contexto de persistencia atualizar o banco de dados @PostUpdate - Depois da entidade ser atualizada no banco de dados . Depois do flush() ou depois de o contexto de persistencia atualizar o banco de dados @PreRemove - Quando uma entidade é agendada para remoção do banco de dados . Depois de remove() . Depois de merge() caso haja remoção aninhada em cascata @PostRemove - Quando a exclusão real no banco de dados ocorre efetivamente . Depois do flush() se houver exclusão infileirada . Depois que o contexto de persistencia atualiza o bancode dados (se for FlushType.COMMIT, é no final da transação) Obs.: Na classe de entidade: qualquer método que retorne void e não receba argumentos Na classe listener: qualquer método que retorne void e receba como argumento um Object (conterá a instância da entidade em questão) --------------------------------------------------------------------------------------------------------------------------

- Listeners de Entidade

public class MeuListener1 { ... @PostPersist

Página 19

Page 20: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt public void postInsert(Object entity) { ... } ... } public class MeuListener2 { ... @PostPersist public void postPersist(Object entity) { ... } @PostLoad public void postLoad(Object entity) { ... } ... } @Entity @EntityListeners({MeuListener1.class, MeuListener2.class}) public class MyEntity { @PostPersist public void afterInsert() { ... } } Obs.: Chamados na ordem em que foram declarados em @EntityListeners ouno XML, por ultimo o da entidade postInsert() + postPersist() + afterInsert() - Herança de Listeners

@Entity @EntityListeners({MeuListener1.class}) public class Person { @PostPersist public void parentAfterInsert() { ... } } @Entity @EntityListeners({MeuListener2.class}) public class Customer extends Person { @PostPersist public void childAfterInsert() { ... } } Obs.: Ordem de chamada: PostPersist de MeuListener1 PostPersist de MeuListener2 PostPersist de Person PostPersist de Customer Outras anotations: @ExcludeDefaultListeners Ignora os "Listeners Padrão" setados na unidade de persistencia @ExcludeSuperclassListeners Ignora os listeners herdados - Declarando Listeners com XML <entity class="com.titan.domain.Cabin"> <entity-listeners> <entity-listener class="com.titan.listeners.TitanAuditLogger" /> <entity-listener class="com.titan.listeners.EntityJmxNotifier"> <pre-persist name="beforeInsert"/> <post-load name="afterLoading"/> </entity-listener>

Página 20

Page 21: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt </entity-listeners> </entity> - Declarando "Listeners Padrão"

Os listeners declarados dessa forma serão aplicados à todas entidades daunidade de persistencia: <entity-mappings> <entity-listeners> <entity-listener class="com.titan.listeners.EntityJmxNotifier"> <pre-persist name="beforeInsert"/> <post-load name="afterLoading"/> </entity-listener> </entity-listeners> </entity-mappings> - Conceitos Gerais EJBQL

. Pode comparar primitivo com Wrapper e comparar valores temporais . Comparação de entidades na base é feita pela chave primaria . Clausula IN no from: itera a lista e faz join (corresponde a INNER JOIN ou somente JOIN) . Operadores valem apenas no WHERE . Clausula IN no where: verifica se valor está dentro da lista de LITERAIS: IN('X', 'Y', 'Z') . Relacionamento "Um-Para-Um" ou campo basico: IS NULL . Relacionamento baseado em coleção (muitos): IS EMPTY . Cuidado INNER JOIN com IS EMPTY (pag 136) . Cuidado: order by e campos que pode (pag 141) . Operações em lote (chamar antes: flush e clear) - Interface Query

public interface Query { public List getResultList( ); public Object getSingleResult( ); public int executeUpdate( ); public Query setMaxResults(int maxResult); public Query setFirstResult(int startPosition); public Query setHint(String hintName, Object value); public Query setParameter(String name, Object value); public Query setParameter(String name, Date value, TemporalType temporalType); public Query setParameter(String name, Calendar value, TemporalType temporalType); public Query setParameter(int position, Object value); public Query setParameter(int position, Date value, TemporalType temporalType); public Query setParameter(int position, Calendar value, TemporalType temporalType); public Query setFlushMode(FlushModeType flushMode); } . Retornando Resultados Método getSingleResult try { Query query = entityManager.creatQuery( "from Customer c where c.firstName='Bill' and c.lastName='Burke'"); Customer cust = (Customer)query.getSingleResult(); } catch (EntityNotFoundException notFound) { } catch (NonUniqueResultException nonUnique) {} - Utilizado para retornar apenas um registro: . Não encontrou nenhum registro:

Página 21

Page 22: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txtEntityNotFoundException . Encontrou mais de um registro: NonUniqueResultException Método getResultList Query query = entityManager.creatQuery( "from Customer c where c.firstName='Bill' and c.lastName='Burke'"); List bills = query.getResultList( ); - Utilizado para retornar uma coleção de registros: . Não encontrou nenhum registro: retorna uma lista vazia . Parametros Parametros Nomeados Query query = entityManager.createQuery( "from Customer c where c.firstName=:first and c.lastName=:last"); query.setParameter("first", first); query.setParameter("last", last); Parametros Indexados Query query = entityManager.createQuery( "from Customer c where c.firstName=?1 and c.lastName=?2"); query.setParameter(1, first); query.setParameter(2, last);

. Parametros Temporais Query query = entityManager.createQuery( "from Customer c where c.dataNascimento=?1"); query.setParameter(1, new java.util.Date, TemporalType.DATE); //DATE, TIME, TIMESTAMP . Paginação de Registros setFirstResult: seta o índice do primeiro registro a trazer setMaxResults: seta a quantidade máxima de registros a trazer Query query = entityManager.createQuery("from Customer c"); List customers = query.setMaxResults(max).setFirstResult(index).getResultList( ); Obs.: é perigoso trazer muitos registros de uma vez, pois todos ficam gerenciados pelo EntityManager e o sistema fica pesado, recomenda-se trazer aos poucos dando clear() no EntityManager . Hints Utilizado para setar na query um atributo específico de fornecedor Query query = manager.createQuery("from Customer c"); query.setHint("org.hibernate.timeout", 1000); . FlushMode query.setFlushMode(FlushModeType.COMMIT); Indica que não deve haver nenhum flush antes da execuçãodesta query query.setFlushMode(FlushModeType.AUTO); É o default, deixa o container livre para fazer flush antes da query, se desejar --------------------------------------------------------------------------------

------------------------------------------

- Clausulas EJB-QL

Página 22

Page 23: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt . Considerações Gerais - As clausulas não são case-sensitive - Os nomes de classes e atributos são case-sensitive . Abstract Schema Name @Entity public class Customer {...} ->entityManager.createQuery("SELECT c FROM Customer AS c"); @Entity(name="Cust") public class Customer {...} ->entityManager.createQuery("SELECT c FROM Cust AS c");

. Simple Queryes SELECT OBJECT( c ) FROM Customer AS c SELECT c FROM Customer AS c SELECT c FROM Customer c ERRO: SELECT customer FROM Customer AS customer O identificador não pode ter nome igual ao nome da entidade, independente do case dos caracteres SELECT c.firstName, c.lastName FROM Customer AS c Obs.: se a entidade for mapeada como tipo FIELD, acessa por nome do atributo, se for como tipo PROPERTY, acessa pelo nome do método JavaBean transformado em nome de atributo

Obs.: Se a query retornar uma entidade, os registros retornam como um List de entidades Se a query retornar campos escalares, os registros retornam como um List de Object[] . Navegando Entidades SELECT c.creditCard.creditCompany.address FROM Customer AS c Efeito: Retorna o "address" da "creditCompany" da "creditCard" de todos "Customer" Obs.: Permite navegar por relacionamento "unário" ou poratributo @Embedded Exemplo 1: @Entity public class Address { private ZipCode zip; } ERRO: SELECT c.address.zip.mainCode FROM Customer AS c Para tornar o select válido, deveria modificar oatributo para: @Embedded private ZipCode zip; Exemplo 2: @Entity public class Customer { @OneToMany private List<Phone> phones; } ERRO: SELECT c.phones.number FROM Customer AS c Isso seria o mesmo que customer.getPhones( ).getNumber( ); o que é INVALIDO. . Constructor Expressions

Página 23

Page 24: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt public class Name { private String first; private String last;

public Name(String first, String last) { this.first = first; this.last = last; } } SELECT new myPackage.Name(c.firstName, c.lastName) FROM Customerc Efeito: Retorna uma List de objetos "Name" preenchidos como indicado no construtor . Clausula IN / INNER JOIN / JOIN / LEFT JOIN / XXX JOIN FETCH / DISTINCT SELECT r FROM Customer AS c, IN( c.reservations ) r Efeito: Retorna todas reservas de todos clientes Obs.: É idêndico a: = SELECT r FROM Customer AS c, INNER JOIN c.reservations r = SELECT r FROM Customer AS c, JOIN c.reservations r SELECT c.firstName, c.lastName, p.number FROM Customer c INNER JOIN c.phoneNumbers p Como no SQL, INNER JOIN irá retornar apenas campos onde existe associação não nula, ou seja, irá retornar apenas clientes que possuem telefones associados SELECT c.firstName, c.lastName, p.number FROM Customer c LEFT JOIN c.phoneNumbers p Como no SQL, LEFT JOIN irá retornar também campos onde existe associação nula, ou seja, irá retornar todos clientes e, caso não possua telefone associado, retornará null no objeto associativo SELECT c FROM Customer c LEFT JOIN FETCH c.phones Adicionando FETCH após o JOIN indica que se o relacionamento for LAZY, deverá carregar mesmo assim Evita o problema N+1, onde se executassemos getPhones() seriam feito N selects, desta forma é feito apenas um select. SELECT DISTINCT cust FROM Reservation AS res, IN (res.customers)cust Não retorna instancias duplicadas no resultado . Clausula WHERE / BETWEEN / IN / LIKE / IS NULL / IS EMPTY / MEMBER OF SELECT c FROM Customer AS c WHERE c.creditCard.creditCompany.name = 'Capital One' SELECT s FROM Ship AS s WHERE s.tonnage = 100000.00 SELECT c FROM Customer AS c WHERE c.hasGoodCredit = TRUE SELECT r FROM Reservation AS r WHERE (r.amountPaid * .01) > 300.00 SELECT r FROM Reservation r, IN ( r.customers ) AS cust WHERE cust = :specificCustomer

SELECT s FROM Ship AS s WHERE s.tonnage BETWEEN 80000.00 AND 130000.00 SELECT c FROM Customer AS c WHERE c.address.state IN ('FL', 'TX', 'MI', 'WI', 'MN') SELECT c FROM Customer AS c WHERE c.address.state NOT IN ('FL',

Página 24

Page 25: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt'TX', 'MI', 'WI', 'MN') SELECT c FROM Customer AS c WHERE c.address.state IN ( ?1, ?2, ?3, 'WI', 'MN') SELECT c FROM Customer AS c WHERE c.address IS NULL SELECT c FROM Customer AS c WHERE c.address IS NOT NULL SELECT crs FROM Cruise AS crs WHERE crs.reservations IS EMPTY SELECT crs FROM Cruise AS crs WHERE crs.reservations IS NOT EMPTY Obs.: Não pode utilizar IS EMPTY em um campo especificado no JOIN ERRO: SELECT r FROM Reservation AS r INNER JOIN r.customers AS c WHERE r.customers IS NOT EMPTY AND c.address.city = 'Boston' Obs.: Na clausula like, % indica N caracteres e _ indica um caractere SELECT OBJECT( c ) FROM Customer AS c WHERE c.lastName LIKE '%-%' SELECT OBJECT( c ) FROM Customer AS c WHERE c.lastName LIKE 'Joan_'

Obs.: Clausula MEMBER OF é como se fosse o IN para tipos de coleção (contains) SELECT crs FROM Cruise AS crs, IN (crs.reservations) AS res, Customer AS cust WHERE cust = :myCustomer AND cust MEMBER OF res.customers

. Clausulas Funcionais LOWER(String) UPPER(String) TRIM([[LEADING | TRAILING | BOTH] [trim_char] FROM] String) CONCAT(String1, String2) LENGTH(String) LOCATE(String1, String2 [, start]) SUBSTRING(String1, start, length) ABS(number) SQRT(double) MOD(int, int) CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP . Clausulas Agregadoras Obs.: se COUNT avalia uma coleção vazia, ele retorna zero SELECT COUNT( c ) FROM Customers AS c WHERE c.address.state = 'WI' SELECT COUNT(c.address.zip) FROM Customers AS c WHERE c.address.zip LIKE '554%' Obs.: MAX e MIN comparam qualquer tipo de dado (utiliza valor outamanho em bytes) SELECT MAX( r.amountPaid ) FROM Reservation AS r SELECT MAX( r.amountPaid ) FROM Reservation AS r Obs.: SUM e AVG servem apenas para numericos e wrappers SELECT SUM(r.amountPaid) FROM Cruise c join c.reservations r WHERE c = :cr Obs.: quando utilizado com agregação, o DISTINCT é aplicado antes de agregar os dados

Página 25

Page 26: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt SELECT DISTINCT COUNT(c.address.zip) FROM Customers AS c WHERE c.address.zip LIKE '554%' Efeito: conta apenas os registros com zip diferentes SELECT c FROM Customers AS c ORDER BY c.lastName SELECT c FROM Customers AS c WHERE c.address.city = 'Boston' ANDc.address.state = 'MA' ORDER BY c.lastName SELECT c FROM Customers AS c ORDER BY c.lastName DESC SELECT c FROM Customers AS c ORDER BY c.lastName ASC, c.firstName DESC

Cuidado: SELECT addr.zip FROM Address AS addr ORDER BY addr.zip SELECT c.address FOR Customer AS c WHERE c.lastName = 'Smith' ORDER BY c.address.zip ERRO: SELECT c FROM Customer AS c ORDER BY c.address.city Se a query retorna uma coleção, no campo order by podem ser utilizados apenas campos basicos desta coleção ERRO: SELECT c.address.city FROM Customer AS c ORDER BY c.address.state O campo especificado em order by precisa estar sendo trazido no select SELECT cr.name, COUNT (res) FROM Cruise cr JOIN cr.reservations res GROUP BY cr.name HAVING count(res) > 10 . Subqueries SELECT COUNT(res) FROM Reservation res WHERE res.amountPaid > (SELECT avg(r.amountPaid) FROM Reservation r)

FROM Cruise cr WHERE 100000 < ( SELECT SUM(res.amountPaid) FROM cr.reservations res )

FROM Cruise cr WHERE 0 < ALL ( SELECT res.amountPaid from cr.reservations res ) Efeito: Seleciona cruzeiros em que todas suas reservas possuam valor de pagamento FROM Cruise cr WHERE 0 = ANY ( SELECT res.amountPaid from cr.reservations res ) Efeito: Seleciona cruzeiros em que exista ao menos uma reserva com valor zerado Obs.: SOME = ANY = NOT ALL FROM Cruise cr WHERE EXISTS (SELECT res FROM cr.reservations WHERE res.amountPaid = 0) Obs.: Clausula EXISTS verifica se a subquery retornou algum registro Efeito: Seleciona os cruseiros que tenham alguma reservasem pagamento

. UPDATE e DELETE em lote UPDATE Reservation res SET res.amountPaid = (res.amountPaid + 10) WHERE EXISTS ( SELECT c FROM res.customers c WHERE c.firstName ='Bill' AND c.lastName='Burke' ) DELETE FROM Reservation res WHERE EXISTS ( SELECT c FROM res.customers c WHERE c.firstName = 'Bill' AND c.lastName='Burke' )

Página 26

Page 27: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt - Scalar Native Queries

Query createNativeQuery(String sql) . Usada para valores escalares, retorna um List de Object[] contendo os valores - Simple Entity Native Queries

Query createNativeQuery(String sql, Class entityClass)

Query query = manager.createNativeQuery("SELECT p.phone_PK, p.phone_number, p.type FROM PHONE AS p", Phone.class);

. Espera que os nomes dos campos retornados correspondam em nome e tipo com os atributos persistentes da entidade em questão, então a associação é feita automaticamente . É obrigatório retornar TODOS os atributos da entidade na query - Complex Native Queries

Query createNativeQuery(String sql, String mappingName) @Entity @SqlResultSetMapping(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 query = manager.createNativeQuery( "SELECT c.id, c.firstName, cc.id As CC_ID, cc.number FROM CUST_TABLE c, CREDIT_CARD_TABLE cc WHERE c.credit_card_id =cc.id", "customerAndCreditCardMapping"); . O mapeamento deve estar definido na entidade . Mapeamento via XML: <entity-mappings> <sql-result-set-mapping name="customerAndCreditCardMapping"> <entity-result entity-class="com.titan.domain.Customer"/> <entity-result entity-class="com.titan.domain.CreditCard"/> <field-result name="id" column="CC_ID"/> <field-result name="number" column="number"/> </entity-result> </sql-result-set-mapping> </entity-mappings>

. Misturando resultado de Entidade e resultado Escalar: @SqlResultSetMapping(name="reservationCount", entities=@EntityResult(name="com.titan.domain.Cruise", fields=@FieldResult(name="id", column="id")), columns=@ColumnResult(name="resCount")) @Entity public class Cruise {...}

--------------------------------------------------------------------------------

Página 27

Page 28: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt ------------------------------------------

- Queryes Nomeadas

. EJBQL Named Queryes @NamedQueries({ @NamedQuery(name="getAverageReservation", query="SELECT AVG( r.amountPaid) FROM Cruise As c, JOIN c.reservations r WHERE c = :cruise"), @NamedQuery(name="findFullyPaidCruises", query="FROM Cruise cr WHERE 0 < ALL (SELECT res.amountPaid from cr.reservations res)") }) @Entity public class Cruise {...}

Ou Via XML: <entity-mappings> <named-query name="getAverageReservation"> <query> SELECT AVG( r.amountPaid) FROM Cruise As c JOIN c.reservations r WHERE c = :cruise </query> </named-query> </entity-mappings>

. SQL Native Named Queryes @NamedNativeQuery(name="findCustAndCCNum", query="SELECT c.id, c.firstName, c.lastName, cc.number AS CC_NUM FROM CUST_TABLE c, CREDIT_CARD_TABLE cc WHERE c.credit_card_id = cc.id", resultSetMapping="customerAndCCNumMapping") @SqlResultSetMapping(name="customerAndCCNumMapping", entities={@EntityResult(entityClass=Customer.class)}, columns={@ColumnResult(name="CC_NUM")} ) @Entity public class Customer {...} Ou via XML: <entity-mappings> <named-native-query name="findCustAndCCNum" result-set-mapping="customerAndCCNumMapping"> <query> SELECT c.id, c.firstName, c.lastName, cc.number AS CC_NUM FROM CUST_TABLE c, CREDIT_CARD_TABLE cc WHERE c.credit_card_id = cc.id </query> </named-native-query> </entity-mappings> - Sistema JMS . Provedor JMS Sistema de rotamento de mensagens . Clientes JMS Produtor (envia) e consumidor (recebe) . Características JMS - Assíncrono (cliente não espera resposta) - Não é propagada transação do produtor pro receptor - Não é propagada segurança nem credenciais do produtor pro receptor - Se o receptor estiver desconectado, o roteador garante a

Página 28

Page 29: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txtentrega da mensagem - Ciclo de Vida: idêntico ao do Stateless Bean, também em pool de instâncias (também com @PostConstruct e @PreDestroy) @Resource(mappedName="ConnectionFactoryName") private ConnectionFactory connectionFactory; @Resource(mappedName="TopicName") private Topic topic; ... Connection connect = factory.createConnection( ); Session session = connect.createSession(true, 0); // 0 -> Session.AUTO_ACKNOWLEDGE

MessageProducer producer = session.createProducer(topic); TextMessage textMsg = session.createTextMessage( ); textMsg.setText("my message");

producer.send(textMsg); connect.close( );

. ConnectionFactory Fornece uma factory para criar conexões JMS com um provedor específico . Connection Conexão efetica com o provedor JMS . Session - Sessão para agrupar ações de envio/recebimento de mensagens - Método createSession(boolean transacted, int acknowledgeMode) - muitos provedores utilizam true e 0 (Session.AUTO_ACKNOWLEDGE) por padrão, porém não é garantido - Obs.: O objeto session não é thread-safe, pode apenas um objeto session JMS por Thread . Topic / Queue Nome do channel do Topic ou da Queue. - Topic . Tipo publish/subscribe . Muitos receptores (a mensagem é entregue à todos que assinam) . Modelo push (o receptor é notificado da mensagem) - Queue: . Tipo peer-to-peer . Um receptor (a mensagem é entregue apenas uma vez, ao primeiro que receber) . Conceitualmente é pull (receptor solicita a mensagem), mas também pode ser push, depende do fornecedor . Tipos de Mensagem - Sempre compostas por um Header e um Corpo: TextMessage textMsg = session.createTextMessage(); MapMessage mapMsg = session.createMapMessage(); ObjectMessage objMsg = session.createObjectMessage(); (outras...) - Exemplo de Header: textMessage.setJMSReplyTo(theAnotherQueue); . Cliente JMS Java SE ConnectionFactory factory = (ConnectionFactory) jndiContext.lookup("ConnectionFactoryNameGoesHere"); Topic topic = (Topic)jndiContext.lookup("TopicNameGoesHere"); Connection connect = factory.createConnection( ); Session session = connect.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer consumer = session.createConsumer(topic);

Página 29

Page 30: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt consumer.setMessageListener(this); //ou qualquer instancia que implemente javax.jms.MessageListener connect.start( );

public void onMessage(Message message) { TextMessage textMsg = (TextMessage)message; String text = textMsg.getText(); } - Message Driven Beans

. Bean especial para consumir mensagens . Não se deve utilizar um Session Bean para consumir mensagens (mas é possível, através dos métodos MessageConsumer.receive(), MessageConsumer.receive(long timeout) ou MessageConsumer.receiveNoWait() . Anotação @Target(TYPE) @Retention(RUNTIME) public @interface MessageDriven { String name() default ""; //nome do MDB Class messageListenerInterface default Object.class; //pode setar como javax.jms.MessageListener e não //implementar a interface explicitamente ActivationConfigProperty[] activationConfig() default {}; //configurações específicas de MDB String mappedName(); //se preferir pode especificar o destino aqui String description(); } . MessageDrivenContext - Extende o EJBContext, é semelhante ao SessionContext porém nãoadiciona nenhuma operação - Pode-se utilizar apenas os métodos transacionais. Os métodos de segurança lançam uma RuntimeException, pois na JMS não há propagação de segurança . Interface javax.jms.MessageListener Único método: public void onMessage(Message message) @MessageDriven( activationConfig={ @ActivationConfigProperty( propertyName="destinationType", propertyValue="javax.jms.Queue"), @ActivationConfigProperty( propertyName="destinationName", propertyValue="jms/TitanQueue"), @ActivationConfigProperty( propertyName="messageSelector", propertyValue="MessageFormat = 'Version 3.4'"), @ActivationConfigProperty( propertyName="acknowledgeMode", propertyValue="Auto-acknowledge") }) public class ReservationProcessorBean implements javax.jms.MessageListener {

@Resource(mappedName="ConnectionFactory") private ConnectionFactory connectionFactory;

public void onMessage(Message message) { try { MapMessage reservationMsg = (MapMessage)message;

Página 30

Page 31: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt int customerPk = reservationMsg.getInt("CustomerID"); int cruisePk = reservationMsg.getInt("CruiseID"); int cabinPk = reservationMsg.getInt("CabinID");

double price = reservationMsg.getDouble("Price"); } catch(Exception e) { throw new EJBException(e); } } } . Atributos ActivationConfigProperty - messageSelector Pode utilizar uma query sintaxe SQL para filtrar quais mensagens o bean vai consumir de acordo com propriedades setadas na mensagem - acknowledgeMode AUTO_ACKNOWLEDGE - é computado recebimento logo após a mensagem ser entregue e processada DUPS_OK_ACKNOWLEDGE - é computado o recebimento em lote,de forma otimizada (o MDB precisa ter preparo para tratar mensagens duplicatas) - subscriptionDurability Durable - tolerantes à desconexão do container, a mensagem é armazenada e entregue depois NonDurable - o contrário, qualquer mensagem recebida enquanto desconectado será perdida . Descritor XML <enterprise-beans> <message-driven> <ejb-name>ReservationProcessorBean</ejb-name> <ejb-class>com.titan.reservationprocessor.ReservationProcessorBean</ejb-class> <messaging-type>javax.jms.MessageListener</messaging-type> <transaction-type>Container</transaction-type> <message-destination-type>javax.jms.Queue</message-destination-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-property> <activation-property> <activation-config-property-name>destinationName</activation-config-property-name> <activation-config-property-value>jms/TitanQueue</activation-config-property-value> <activation-property> <activation-property> <activation-config-property-name>messageSelector</activation-config-property-name> <activation-config-property-value>MessageFormat = 'Version 3.4'</activation-config-property-value> <activation-property> <activation-property>

Página 31

Page 32: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt<activation-config-property-name>acknowledgeMode</activation-config-property-name> <activation-config-property-value>Auto-acknowledge</activation-config-property-value> <activation-property> </activation-config> </message-driven> </enterprise-beans></ejb-jar>

--------------------------------------------------------------------------------

------------------------------------------

- Ouvindo um Timer

@Stateless public class ShipMaintenanceBean implements ShipMaintenanceRemote implements javax.ejb.TimedObject { ... public void ejbTimeout(javax.ejb.Timer timer) { ... } }

ou... @Stateless public class ShipMaintenanceBean implements ShipMaintenanceRemote { ... @Timeout public void myTimeout(javax.ejb.Timer timer) { ... } }

- Criando um Timer

. O próprio bean se registra para ouvir o timer . O timer pode ser criado em Stateless e MessageDriven beans . CUIDADO: não se deve criar timers em @PostConstruct nem @PreDestroy (são chamados para cada instância do pool), nem utilizando variáveis estáticas para verificar sejá foi criado (problema do cluster) . O timer deve ser criado apenas através de métodos de negócio invocadospelo cliente . Um timer service pode ser obtido através do EJBContext.getTimerService(), ou injetado pelo container: @Resource TimerService timerService; . Interface TimerService - public Timer createTimer(Date expiration, Serializable info) . Ação única . Expira na data especificada - public Timer createTimer(long duration, Serializable info) . Ação única . Expira depois de passado o tempo especificado em milisegundos - public Timer createTimer(Date initialExpiration, long intervalDuration, Serializable info) . De intervalo . Expira na data especificada e subsequentemente a cada intervalo especificado em intervalDuration - public Timer createTimer(long initialDuration, long

Página 32

Page 33: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txtintervalDuration, Serializable info) . De intervalo . Expira depois de passado o tempo initialDuration e subsequentemente a cada intervalo especificado em intervalDuration - public Collection getTimers() . Retorna uma coleção contendo todos os timers agendadospara o beans em questão (apenas os timers do bean que chamou o método) Obs.: Todos os métodos TimerService lançam as exceções: . IllegalArgumentException: parâmetros negativos ou null . IllegalStateException: chamado de onde não é permitido . EJBException: encapsula qualquer outra exceção de sistema . Interface Timer - public void cancel() Cancela o timer - public Serializable getInfo() Recupera o objeto passado na criação do timer - public Date getNextTimeout() Recupera a data em que ocorrerá a próxima expiração - public long getTimeRemaining() Recupera o tempo restante para a próxima expiração - public TimerHandle getHandle() Recupera uma referência serializável à instância deste timer Obs.: Todos os métodos Timer lançam as exceções: . NoSuchObjectLocalException: se invocado qualquer método em um timer de ação única expirado ou um timer cancelado . EJBException: encapsula qualquer outra exceção de sistema . Reagendando temporizadores: precisa cancelar e criar um novo . Transação - É transacional no escopo da transação atual, ou seja, se ocorrer rollback em um método que cria o timer, sua criação será desfeita - É boa prática o método de @Timeout ser transacional RequiresNew, para assegurar que ele está no escopo transacional do container

- Interceptors

. Criando Classes Interceptadoras public class Profiler {

@AroundInvoke public Object profile(InvocationContext invocation) throws Exception { long startTime = System.currentTimeMillis( ); try { return invocation.proceed( ); } finally { long endTime = System.currentTimeMillis() - startTime; System.out.println("Method " +

Página 33

Page 34: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txtinvocation.getMethod( ) + " took " + endTime + " (ms)"); } } } . Interface InvocationContext public interface InvocationContext { public Object getTarget( ); public Method getMethod( ); public Object[] getParameters( ); public void setParameters(Object[] newArgs); public java.util.Map<String, Object> getContextData( ); public Object proceed( ) throws Exception; } . getTarget - retorna uma referência à instância do beanalvo . getMethod - retorna um objeto java.lang.reflect.Methoddo método que foi chamado . getParameters - retorna os parâmetros que foram enviados ao método . setParameters - modifica tais parâmetros (usar com cuidado) . getContextData - retorna um objeto Map que fica ativo durante toda a pilha de chamada, onde podemos compartilhar valores com outros interceptors . proceed - continua a pilha de chamada (próximo interceptor ou método original) . Aplicando Interceptors - Nível de Classe (intercepta todos os métodos do bean) @Stateless @Interceptors(Profiler.class) public class MyBean implements MyBeanRemote { ... }

- Nível de Método (intercepta apenas o método anotado) @Stateless public class MyBean implements MyBeanRemote { @Interceptors(Profiler.class) public void myMethod() { ... } } - Aplicando via XML <ejb-jar> <assembly-descriptor> <interceptor-binding> <ejb-name>TravelAgentBean</ejb-name> <!-- <exclude-default-interceptors> e <exclude-class-interceptors> --> <interceptor-class>com.titan.Profiler</interceptor-class> <method-name>bookPassage</method-name> <method-params> <method-param>com.titan.CreditCardDO</method-param> <method-param>double</method-param> </method-params>

Página 34

Page 35: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt </interceptor-binding> </assembly-descriptor> </ejb-jar> . Obs: - <method-name> é utilizado apenas para aplicar a nivel de método - <method-params> é útil se houver overload no método especificado - Interceptors Padrão . Recebem um curinga (*). São aplicados para todos os métodos de todos os beans do ejb-jar. <ejb-jar> <assembly-descriptor> <interceptor-binding> <ejb-name>*</ejb-name> <interceptor-class>com.titan.Profiler</interceptor-class> </interceptor-binding> </assembly-descriptor> </ejb-jar>

- Desativando Interceptors . @ExcludeDefaultInterceptors Ignora os interceptors-padrão da implantação . @ExcludeClassInterceptors Ignora os interceptors de nivel de classe do bean --------------------------------------------------------------------------------------------------------------------------

- Interceptors e Injeção de Dependência (ENC)

. O interceptor compartilha o mesmo JNDI ENC do bean que está interceptando . O EJBContext também é compartilhado . Injeção no Interceptor - Via Annotations public class AuditInterceptor { @Resource EJBContext ctx; @PersistenceContext(unitName="auditdb") EntityManager manager;

@AroundInvoke public Object audit(InvocationContext invocation) throws Exception { ... } } - Via XML <ejb-jar> <interceptors> <interceptor> <interceptor-class>com.titan.interceptors.AuditInterceptor</interceptor-class> <around-invoke>

Página 35

Page 36: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt<method-name>audit</method-name> </around-invoke> <persistence-context-ref> <persistence-context-name>com.titan.interceptors.AuditInterceptor/manager</persistence-context-name> <persistence-context-unit-name>auditdb</persistence-context-unit-name> <injection-target> <injection-target-class>com.titan.interceptors.AuditInterceptor</injection-target-class> <injection-target-name>manager</injection-target-name> </injection-target> </persistence-context-ref> </interceptor> </interceptors> </ejb-jar>

--------------------------------------------------------------------------------------------------------------------------

- Interceptors e Ciclo de Vida

. Possuem o mesmo ciclo de vida do bean que interceptam . Podem interceptar métodos de callback do bean @<callback-annotation> void myMethod(InvocationContext ctx) { ... } . Obs: - Não pode lançar exceções verificadas - Retorna void - Se o bean não tiver callback, a chamada ctx.getMethod() retornará null . Para abortar a chamada do método original, basta lançar uma exceção (no lugar do método proceed) . Para lançar exceptions verificadas, elas precisam estar declaradas na interface do bean --------------------------------------------------------------------------------------------------------------------------

- Interceptor na Própria Classe Bean . É o último interceptador chamado na pilha até chegar ao método . É aplicado para todos os métodos da classe que reside @Stateless public class MySessionBean implements MySessionRemote {

public void businessMethod( ) { ... }

@AroundInvoke public Object beanClassInterceptor(InvocationContext ctx) { ... } }

- Ordem de Execução de Interceptors

1 - Os default interceptors, declarados no deployment descriptor (xml) 2 - Os interceptors a nivel de classe, na ordem em que foram declarados em @Interceptors (em seguida os do XML) 3 - Os interceptors a nivel do método específico (em seguida os do XML) 4 - O interceptor declarado no bean

Página 36

Page 37: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt Obs: . Se um interceptor extende uma classe que também é interceptor,o @AroundInvoke da superclasse executa primeiro . Podemos utilizar uma tag <interceptor-order> para modificar a ordem <assembly-descriptor> <interceptor-binding> <ejb-name>org.jboss.tutorial.interceptor.bean.EmailSystemBean</ejb-name> <method-name>sendBookingCancellationMessage</method-name> <interceptor-order> <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class> <interceptor-class>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptor-class> <interceptor-class>org.jboss.tutorial.interceptor.bean.OtherInterceptor</interceptor-class> <interceptor-class>org.jboss.tutorial.interceptor.bean.TracingInterceptor</interceptor-class> </interceptor-order> </interceptor-binding> </assembly-descriptor> - JNDI ENC (Enterprise Naming Context) . É uma extensão do EJBContext para localizar recursos dentro de um específico EJB . Cada EJB possui seu próprio ENC, que não é compartilhado entre eles . Recursos disponíveis via JNDI ENC: - Outro EJB - Destino JMS - Connection Factories - Data Sources - Qualquer recurso JCA - UserTransaction - TimerService - org.omg.CORBA.ORB - Qualquer primitivo . Exemplo - Gravando ENC de outro EJB, via XML <ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <ejb-local-ref> <ejb-ref-name>ejb/ProcessPayment</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local>com.titan.processpayment.ProcessPaymentLocal</local> <ejb-link>ProcessPaymentBean</ejb-link> </ejb-local-ref> </session> </enterprise-beans> </ejb-jar> - Gravando ENC de outro EJB, via Annotations

Página 37

Page 38: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt @Stateful @EJB(name="ejb/ProcessPayment", beanInterface=ProcessPaymentLocal.class, beanName="ProcessPaymentBean") public class TravelAgentBean implements TravelAgentRemote { ... }

- Obtendo o recurso do ENC . Via InitialContext javax.naming.InitialContext ctx = new InitialContext( ); ProcessPaymentLocal payment = (ProcessPaymentLocal)ctx.lookup("java:comp/env/ejb/ProcessPayment");

. Via EJBContext @Resource private SessionContext ejbContext; ... ProcessPaymentLocal payment = (ProcessPaymentLocal)ejbContext.lookup("ejb/ProcessPayment"); - Injeção de Dependência ENC . Via Annotations - No atributo: @EJB private ProcessPaymentLocal payment; - No método setter: @EJB public void setProcessPaymentLocal(ProcessPaymentLocal payment) { this.payment = payment; } . Via XML <ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <ejb-local-ref> <ejb-ref-name>ProcessPayment</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local>com.titan.processpayment.ProcessPaymentLocal</local> <ejb-link>ProcessPaymentBean</ejb-link> <injection-target> <injection-target-class>com.titan.travelagent.TravelAgentBean</injection-target-class> <injection-target-name>payment</injection-target-name> </injection-target> </ejb-local-ref> </session> </enterprise-beans> </ejb-jar> - Nome ENC padrão

Página 38

Page 39: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt . Via Annotations - Atributo "name" - Na falta do "name": . Em atributo <nome qualificado da classe>/<nome do atributo> . Em setter <nome qualificado da classe>/<nome da transformação setter em atributo> - Nenhum atributo da annotation é obrigatório - Não pode ocorrer injeção de um atributo e um setter que resolvem o mesmo nome simultaneamente - No caso de herança, precisa definir o atributo"beanName" (annotation) ou <ejb-link> (xml) --------------------------------------------------------------------------------------------------------------------------

- Tipos de Referencia

. Referências EJB - Annotations public @interface EJB { String name( ) default ""; Class beanInterface( ) default Object.class; String beanName( ) default ""; String mappedName( ) default ""; } . name - nome que será gravano no ENC (relativo à java:comp/env) . beanInterface - interface a ser referenciada (distingue entre local e remote) . beanName - nome do ejb a ser referenciado (útil no caso de mais de um bean com a mesma interface, utiliza o dado @StateXXX.name() ou o <ejb-name>) . mappedName - recupera o recurso de um JNDI global . Obs.: - A nivel de classe: . é obrigatório "name" e "beanInterface" . para gravar mais de um EJB, utilizar @EJBs({ @EJB(...), @EJB(...) }) - A nivel de atributo ou setter: . nenhum dado é obrigatório - XML . Remoto <ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <ejb-ref> <ejb-ref-name>ejb/ProcessPaymentRemote</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <remote>com.titan.processpayment.ProcessPaymentRemote</remote> </ejb-ref>

Página 39

Page 40: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt </session> </enterprise-beans> </ejb-jar> . Local <ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <ejb-local-ref> <ejb-ref-name>ejb/ProcessPaymentRemote</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local>com.titan.processpayment.ProcessPaymentLocal</local> </ejb-local-ref> </session> </enterprise-beans> </ejb-jar>

. Obs.: - Obrigatório: <ejb-ref-name>, <ejb-ref-type>, <remote> ou <local> - Opcional: <description>, <home>, <ejb-link>, <mapped-name>, <injection-target> - Obs. Gerais . Caso de nome duplicado em dois JARs no mesmo EAR: @EJB(beanName="inventory-ejb.jar#InventoryEJB") private InventoryLocal inventory; . Referências EntityManagerFactory - Annotations public @interface PersistenceUnit { String name( ) default ""; String unitName( ) default ""; } . name - nome a ser gravado no ENC . unitName - nome da unidade de persistencia (obrigatório apenas se o persistence.xml definir mais de uma) . Obs.: - A nivel de classe: . atributo "name" é obrigatório . para gravar mais de um PersistenceUnit, utilizar @PersistenceUnits({ @PersistenceUnit(...), @PersistenceUnit(...) }) - A nivel de atributo ou setter: . apenas "unitName" que pode serobrigatório se houver mais de uma unidade definida no xml - XML <ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <persistence-unit-ref>

Página 40

Page 41: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt<persistence-unit-ref-name>persistence/TitanDB</persistence-unit-ref-name> <persistence-unit-name>TitanDB</persistence-unit-name> </persistence-unit-ref> </session> </enterprise-beans> </ejb-jar> - Obs. Gerais . Caso de persistence-unit duplicado em dois JARs ou WARno mesmo EAR: @PersistenceUnit(unitName="inventory.jar#InventoryDB") private EntityManagerFactory inventoryFactory; . Injeção xml possível via <injection-target> . Referências EntityManager - Annotations public @interface PersistenceContext { String name( ) default ""; String unitName( ) default ""; PersistenceContextType type( ) default TRANSACTION; PersistenceProperty[] properties( ) default {}; } public enum PersistenceContextType { TRANSACTION, EXTENDED }

public @interface PersistenceProperty { String name( ); String value( ); }

. name - nome a ser gravado no ENC . unitName - nome da unidade de persistencia (obrigatório apenas se o persistence.xml definir mais de uma) . PersistenceContextType - opcional, o default éTRANSACTION . PersistenceProperty - opcional, específico de fornecedor . Obs.: - A nivel de classe: . atributo "name" é obrigatório . para gravar mais de um PersistenceContext, utilizar @PersistenceContexts({ @PersistenceContext(...), @PersistenceContext(...) }) - A nivel de atributo ou setter: . apenas "unitName" que pode serobrigatório se houver mais de uma unidade definida no xml - XML <ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <persistence-context-ref> <persistence-context-ref-name>persistence/TitanDB</persistence-context-ref-name>

Página 41

Page 42: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt <persistence-unit-name>TitanDB</persistence-unit-name> <persistence-context-type>EXTENDED</persistence-context-ref> <persistence-property> <name>hibernate.show_sql</name> <value>true</value> </persistence-property> </persistence-context-ref> </session> </enterprise-beans> </ejb-jar> - Obs. Gerais . Caso de persistence-unit duplicado em dois JARs ou WARno mesmo EAR: @PersistenceContext(unitName="inventory.jar#InventoryDB") private EntityManager inventoryManager; . Injeção xml possível via <injection-target> . Referências Recursos Reutilizáveis - Annotations public @interface Resource { String name( ) default ""; Class type( ) default Object.class; AuthenticationType authenticationType( ) defaultAuthenticationType.CONTAINER; boolean shareable( ) default true; String description( ) default ""; String mappedName( ) default ""; }

public enum AuthenticationType { CONTAINER, APPLICATION }

. name - nome a ser gravado no ENC . type - nome qualificado da classe do recurso . mappedName - associa a um recurso JNDI global . shareable - define se o recurso vai ter sua conexão compartilhada entre diferentes beans (padrão é true) . authenticationType - define que é responsável pela autenticação no recurso em runtime . Obs.: - A nivel de classe: . atributos "name" e "type" são obrigatórios . para gravar mais de um Resource, utilizar @Resources({ @Resource(...), @Resource(...) }) - A nivel de atributo ou setter: . apenas "mappedName" pode ser obrigatório, se for um recurso JNDI global - XML <ejb-jar> <enterprise-beans> <session>

Página 42

Page 43: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt <ejb-name>TravelAgentBean</ejb-name> <resource-ref> <res-ref-name>jdbc/OracleDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <mapped-name>java:/DefaultDS</mapped-name> </resource-ref> </session> </enterprise-beans> </ejb-jar> - Obs. Gerais . Injeção xml possível via <injection-target> - Referências Recursos de Objetos Administrados Ambiente Exemplo: EJBContext, SessionContext, UserTransaction <ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <resource-env-ref> <resource-env-ref-name>UserTransaction</res-ref-name> <resource-env-ref-type>javax.transaction.UserTransaction</resource-env-ref-type> </resource-env-ref> </session> </enterprise-beans> </ejb-jar> - Referências Recursos de Constantes de Ambiente <ejb-jar> <enterprise-beans> <session> <ejb-name>ProcessPaymentBean</ejb-name> <env-entry> <env-entry-name>minCheckNumber</env-entry-name> <env-entry-type>java.lang.Integer</env-entry-type> <env-entry-value>2000</env-entry-value> </env-entry> </session> </enterprise-beans> </ejb-jar> . Obs: . Quase sempre utilizado em nível de atributo ousetter, pois não fornece metadados para inicializá-lo . Sempre primitivos e wrappers (java.lang) . Anotar o primitivo ou o setter não cria entrada no ENC, apenas puxa o valor, se houver - Referências Recursos de Destinos JMS <ejb-jar>

Página 43

Page 44: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt <enterprise-beans> <session> <ejb-name>TravelAgentBean</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>Distributor</message-destination-link> <mapped-name>topic/TicketTopic</mapped-name> </message-destination-ref> </session> </enterprise-beans> </ejb-jar>

. Obs: . Obrigatório - <message-destination-ref-name>, <message-destination-type>, <message-destination-usage>] . Para utilizar um destino específico de bean <message-destination-link> é obrigatório o uso de XML, porém para os casos mais comuns pode utilizar @Resource . O recurso sempre tem que ser obtido do JNDI global (mappedName) - Referências Web Services . N/A - Conceitos Transações ACID . Atomic Ou executa tudo com sucesso, ou não executa nada. .Consistent Os dados se mantém consistentes, com lógica para o modelo de negócio . Isolated Uma transação não influencia a outra . Durable Garantia que os dados são todos persistidos na base ao final da transação - Atributos de Transação

public @interface TransactionAttribute { TransactionAttributeType value( ) default TransactionAttributeType.REQUIRED; } public enum TransactionAttributeType { MANDATORY, REQUIRED, REQUIRES_NEW, SUPPORTS, NOT_SUPPORTED, NEVER }

. Via XML <ejb-jar> <assembly-descriptor> <container-transaction>

Página 44

Page 45: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt <method> <ejb-name>TravelAgentEJB</ejb-name> <method-name>*</method-name> </method> <trans-attribute>NotSupported</trans-attribute> </container-transaction> <container-transaction> <method> <ejb-name>TravelAgentEJB</ejb-name> <method-name>bookPassage</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar> . Obs. Gerais: - Por default, se não houver a anotação @TransactionAttribute, éadotado REQUIRED - Pode ser aplicado a nivel de classe, a nível de método ou com curinga para todos os beans. Se aplicado a nivel de classe em conjunto com método, o do método sobrescreve aquele método em particular . Tipos de Transação (ver imagens págs 266-268) - NOT_SUPPORTED A transação do chamador não é propagada, e o bean é executado sempre sem transação. - SUPPORTS Se o chamador tiver transação, ela é propagada. Caso contrário, o bean é executado sem transação. "Acompanha o chamador". - REQUIRED Se o chamador tiver transação, ela é propagada. Caso contrário, o bean cria uma transação própria. "Bean sempre tem transação". - REQUIRES_NEW O bean sempre cria uma transação própria, independentemente do chamador ter ou não transação. - MANDATORY Bean só executa se o chamador tiver transação. Caso contrário, lança EJBTransactionRequiredException. - NEVER Bean só executa se o chamador NÃO tiver transação. Caso contrário, lança EJBException.

. Message-Driven Beans Podem ter apenas NOT_SUPPORTED (onMessage é executado sem transação), ou REQUIRED (onMessage é executado em uma própria transação)

. Lembrete: Contexto de Persistência - TRANSACTION - é propagado junto com a transação - EXTENDED - dura o tempo de vida do Bean Statefull . Regras - Um bean com contexto TRANSACTION não pode invocar um bean com contexto EXTENDED - Um bean com contexto EXTENDED pode invocar um bean com contexto TRANSACTION (o contexto é propagado) - Um bean Statefull EXTENDED compartilha o contexto com outro bean Statefull EXTENDED apenas se o

Página 45

Page 46: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt segundo bean foi injetado

- Tipos de Problemas Comuns em Transações Concorrentes . Dirty reads . Repeatable reads . Phantom reads - Níveis de Isolamento . Read Uncommitted . Read Committed (é a que a especificação prevê) . Repeatable Read . Serializable - Optimistic Locking . É utilizado para garantir que não seja feito update concorrente em um objeto e as modificações sejam sobrepostas no banco . É a técnica de realizar a leitura sendo "otimista", adotando que ninguém alterou o registro. Então, no commit da transação, é verificado se este registro foi alterado ou não. Se sim, lança uma OptimisticLockException. . Para isso é criada uma nova coluna numérica na entidade, anotada com @Version, que será gerenciada pelo container . O @Version é incrementado automaticamente em cada update . Se você achar que este bloqueio irá ter um grande número de reversões,é mais performático utilizar o isolamento serializable - Locking Programático . É garantido apenas em entidades que possuem atributo @Version . Usa o método entityManager.lock(Object entity, LockModeType type) . O LockModeType pode ser: - READ - previne dirty-read e repetable-read - WRITE - idem READ, porém também realiza um incremento na coluna @Version (SELECT ... FOR UPDATE)

-------------------------------------------------------------------------------- ------------------------------------------

- Bean Managed Transaction (BMT)

. Quando a transação é gerenciada pelo própio cliente/bean, via código . Um cliente não-ejb pode demarcar uma transação obtendo o UserTransaction do container via JNDI . Cliente EJB BMT: @Stateless @TransactionManagement(TransactionManagerType.BEAN) public class HypotheticalBean implements HypotheticalLocal { ...}

. Obtendo UserTransaction - Via injeção: @Resource private UserTransaction utx; - Via EJBContext (ou SessionContext) ejbContext.getUserTransaction(); . Delimitando a Transação: utx.begin(); ... utx.commit();

. Objeto UserTransaction public interface javax.transaction.UserTransaction {

Página 46

Page 47: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt public abstract void begin( ) throws IllegalStateException, SystemException; public abstract void commit( ) throws IllegalStateException, SystemException, TransactionRolledbackException, HeuristicRollbackException, HeuristicMixedException; public abstract int getStatus( ); public abstract void rollback( ) throws IllegalStateException, SecurityException, SystemException; public abstract void setRollbackOnly( ) throws IllegalStateException, SystemException; public abstract void setTransactionTimeout(int seconds)throws SystemException; }

. Obs. Gerais - Para beans Stateless, begin() e commit() precisam estar no mesmo método - Para beans Statefull, podem estar em métodos diferentes (não usual) - Para beans MDB, há uma pequena diferença no uso de CMT e BMT: . CMT - a entrega da mensagem é incluída na transação . BMT - a entrega da mensagem não é incluída na transação (porém o JMS pode ainda contar com o acknowledge, pois se o onMessage lançar uma EJBException, o container tentará entregar novamente) - Não é permitido uso de begins e commits especificos de outras APIs (EntityManager, Connection, etc) - Beans CMT não podem utilizar UserTransaction

--------------------------------------------------------------------------------------------------------------------------

- Interface SessionSynchronization

. Um bean statefull pode implementar a interface SessionSynchronization public interface javax.ejb.SessionSynchronization { public abstract void afterBegin( ) throws RemoteException; public abstract void beforeCompletion( ) throws RemoteException; public abstract void afterCompletion(boolean committed) throws RemoteException; } . Ela adiciona um novo estado de ciclo-de-vida (Transactional Method-Ready), incluindo mais três métodos de callback, chamados quando um contexto de transação é criado no bean statefull - afterBegin Invocado quando o contexto é criado, ou seja, um método transacional é invocado e cria um novo contexto transacional - beforeCompletion Invocado se a transação for comitada - afterCompletion(boolean commited) Invocado quando a transação termina, recebendo um boolean indicando se foi comitada ou não . Obs. Gerais - Em um bean statefull, enquanto um contexto transacional não é completado, é proibido iniciar um novo

Página 47

Page 48: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt contexto transacional (RequiresNew, NotSupported ou Never) na mesma instância do bean, e também é proibido chamar o método @Remove sem terminar o contexto transacional (nos dois casos é lançada uma exceção) - Lembrete: um bean statefull com contexto de persistência EXTENDED pode interagir com o EntityManager mesmo fora de uma transação, enfileirando as ações até que haja uma transação (isso pode ser usado em conjunto com o Optimistic-Locking para não manter transações vivas por muito tempo durante diferentes chamadas de métodos no bean statefull), ou seja, interagimos à vontade sem contexto transacional, e utilizamos um único método transacional que efetua o "flush" no EntityManager - Lembrete: um bean com contexto de persistência EXTENDED utilizando um EntityManager em um método fora de um escopo transacional não pode propagar seu contexto de persistência para um bean de contexto TRANSACTION, para isso precisamos tornar esse segundo bean em statefull e utilizarnele um contexto EXTENDED --------------------------------------------------------------------------------------------------------------------------

- Exceções e Transações

. Exceções de Sistema - java.lang.RuntimeException - javax.ejb.EJBException - javax.rmi.RemoteException - Comportamento: . container empacota a exceção: - se o cliente propagou a transação, é empacotada em EJBTransactionRolledbackException - caso contrário, é empacotada em EJBException . container reverte a transação . container descarta a instancia do bean (fica pronta para coleta de lixo) . container registra log - Obs: . se o bean for statefull, o impacto no cliente é severo: qualquer invocação de método subsequente à exceção retorna uma NoSuchEJBException (subclasse de RuntimeException) . se o bean for MDB, se trata transações como BMT, a mensagem poderia não ser entregue novamente (acknowledge) . Exceções de Aplicativo - Qualquer outro tipo de exception de negócio - Comportamento: . container não empacota a exception, repassa ao clienteda forma que foi lançada . antes de devolver ao cliente, se a transação é CMT e foi criada pelo bean, o container tenta comitar . não reverte a transação nem mata o bean . se é um MDB, adotar como "cliente" do método onMessageo adaptador JCA do recurso JMS . @ApplicationException @ApplicationException(rollback=true) public class PaymentException extends java.lang.Exception { ... }

Página 48

Page 49: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt - Com essa anotação podemos fazer com que uma exceção de aplicativo reverta a transação - Podemos anotar exceções de sistema e fazer com que elas se comportem como exceções de aplicativo - Atributo roolback define se queremos reverter a transação - Exemplo de definição em XML: <ejb-jar> <assembly-descriptor> <application-exception> <exception-class>java.sql.SQLException</exception-class> <rollback>true</rollback> </application-exception> </assembly-descriptor> </ejb-jar> - Conceitos Gerais

. Autenticação Se o usuário é quem diz ser (validação username e senha) . Autorização Se um usuário, já autenticado, tem direito de acessar tal recurso . Confidencialidade e Integridade Se os dados trocados não vão ser lidos ou alterados durante o tráfego na rede . Obs. Gerais: - Beans de entidade ainda não suportam recursos de segurança, devemos utilizar os específicos do respectivo RDBMS - Auntenticação

. Via JNDI ou JAAS - JNDI: properties.put(Context.SECURITY_PRINCIPAL, userName); properties.put(Context.SECURITY_CREDENTIALS, userPassword);

InitialContext ctx = new InitialContext(properties); Object ref = jndiContext.lookup("TravelAgent"); TravelAgentRemote remote = (TravelAgentRemote) PortableRemoteObject.narrow(ref, TravelAgentRemote.class); - Autorização

. @RolesAllowed(String[] values) - Especifica as roles que podem acessar o recurso. Pode ser utilizado a nivel de bean ou de método . @PermitAll - Permite acesso a qualquer usuário autenticado . Especificando via XML <ejb-jar version="3.0"> <assembly-descriptor> <security-role> <description>This role represents an authorized merchant</description> <role-name>AUTHORIZED_MERCHANT</role-name> </security-role>

Página 49

Page 50: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt <method-permission> <role-name>AUTHORIZED_MERCHANT</role-name> <method> <ejb-name>ProcessPaymentBean</ejb-name> <method-name>byCredit</method-name> </method> </method-permission> <method-permission> <role-name>CHECK_FRAUD_ENABLED</role-name> <role-name>AUTHORIZED_MERCHANT</role-name> <method> <ejb-name>ProcessPaymentBean</ejb-name> <method-name>*</method-name> <method-intf>Remote</method-intf> </method> </method-permission> <method-permission> <unchecked/> <method> <ejb-name>ProcessPaymentBean</ejb-name> <method-name>byCheck</method-name> <method-params> <method-param>com.titan.domain.Customer</method-param> <method-param>com.titan.processpayment.CheckDO</method-param> <method-param>double</method-param> </method-params> </method> </method-permission> </assembly-descriptor> </ejb-jar> - Obs. do mapeamento via XML . A anotação @PermitAll é o equivalente do elemento <unchecked/> . No <method-name> podemos utilizar o curinga (*), que autoriza a nível do bean (todos métodos) . Para métodos em overload, existe o elemento <method-params>, que se não for especificado, aplica a autorização para todas as assinaturas sobrecarregadas . Por default, a autorização se aplica a todas interfaces de negócio do bean . Utilizar o elemento <method-intf> para definira interface de negócio que será aplicada a autorização (Remote, Local, ServiceEndpoint, Home e LocalHome)

. @DenyAll - Bloqueia o acesso ao recurso (nível de método ou de bean) - É mais utilizada via XML, com o elemento <exclude-list>: <ejb-jar> <assembly-descriptor> <exclude-list> <method> <ejb-name>ProcessPaymentBean</ejb-name>

Página 50

Page 51: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt <method-name>byCash</method-name> </method> </exclude-list> </assembly-descriptor> </ejb-jar>

. @RunAs(String value) - Determina uma role a qual o EJB utilizará para invocar outros beans eventualmente protegidos, sempre a nível de bean @Stateful @RunAs("AUTHORIZED_MERCHANT") public class TravelAgentBean implements TravelAgentRemote { ... }

- Via XML: <ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <security-identity> <run-as> <role-name>AUTHORIZED_MERCHANT</role-name> </run-as> </security-identity> </session> </enterprise-beans> </ejb-jar> - Para utilizar a mesma role do chamador, utilizar o elemento <user-caller-identity/>: <enterprise-beans> <session> <ejb-name>EmployeeService</ejb-name> <security-identity> <user-caller-identity/> </security-identity> </session> </enterprise-beans>

--------------------------------------------------------------------------------------------------------------------------

- Segurança Programática

. Existem dois métodos do EJBContext: Principal getCallerPrincipal(); boolean isUserInRole(String roleName); . getCallerPrincipal - Exemplo de uso: @Stateless public class ProcessPaymentBean implements ProcessPaymentLocal {

@Resource SessionContext ctx; ...

Página 51

Page 52: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt private boolean process() { Principal caller = ctx.getCallerPrincipal(); String username = caller.getName( ); ... } } . isUserInRole - Precisa usar uma role presente na anotação @DeclaredRoles, para que através da anotação, o container verifique se a role existe declarada no sistema - Exemplo de uso: @Stateless @DeclareRoles("JUNIOR_TRAVEL_AGENT") public class ProcessPaymentBean implements ProcessPaymentLocal {

@Resource SessionContext ctx; private boolean process() { if ( ctx.isCallerInRole("JUNIOR_TRAVEL_AGENT") ) { //do something } } } - Correspondente @DeclaredRoles em XML: <ejb-jar version="3.0"> <enterprise-beans> <session> <ejb-name>ProcessPaymentBean</ejb-name> <security-role-ref> <role-name>JUNIOR_TRAVEL_AGENT</role-name> </security-role-ref> </session> </enterprise-beans> </ejb-jar> . Obs: - Podemos utilizar roles virtuais no bean e mapear para uma role real: <security-role-ref> <role-name>JUNIOR_AGENT</role-name> <!-- nome usado no bean --> <role-link>JUNIOR_TRAVEL_AGENT</role-link> <!-- nome real da role --> </security-role-ref>

- Conceitos Gerais

. JAX-RPC API para criação de WebServices (Java API for XML-based RPC). Utiliza muitos descritores e arquivos mapeamento . JAX-WS Melhoria da API JAX-RPC (Java API for XML-based WebServices). Encapsula os descritores com uso de annotations - Expondo um WebService (JAX-WS)

Página 52

Page 53: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt . Utilizando o Próprio Bean @Stateless @WebService public class TravelAgentBean implements TravelAgentBeanRemote {

@WebMethod public String makeReservation(int cruiseId, int cabinId, int customerId, double price) { ... } } . Utilizando uma Interface Endpoint @WebService public interface TravelAgentEndpoint { public String makeReservation(int cruiseId, int cabinId, int customerId, double price); } @WebService(endpointInterface = "com.titan.webservice.TravelAgentEndpoint") public class TravelAgentBean implements TravelAgentEndpoint { ... }

. Regras: - Se nenhum método estiver anotado com WebMethod, todos os métodos do bean serão expostos como WebService - Se houver ao menos um método anotado, serão expostos apenas os métodos anotados - Ao utilizar uma interface de endpoint, todos os métodos da interface serão expostos . @WebService public @interface WebService { String name( ) default ""; String targetNamespace( ) default ""; String serviceName( ) default ""; String wsdlLocation( ) default ""; String portName( ) default ""; String endpointInterface( ) default ""; } - name: nome do webservice gerado (nome do portType), o default é o nome da classe/interface - targetNamespace: namespace dos elementos xml gerados para esse serviço, o default é o nome do package da classe/interface - wsdlLocation: usado para mapear o servico a umwsdl já existente - portName: wsdl port a ser usado - endpointInterface: para exposição via interface endpoint

. @WebMethod public @interface WebMethod { String operationName( ) default ""; String action( ) default ""; } - operationName: nome da operação no wsdl

Página 53

Page 54: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt . @SOAPBinding public @interface SOAPBinding { public enum Style {DOCUMENT, RPC}; public enum Use {LITERAL, ENCODED}; public enum ParameterStyle {BARE, WRAPPED} Style style( ) default Style.DOCUMENT; Use use( ) default Use.LITERAL; ParameterStyle parameterStyle( ) default ParameterStyle.WRAPPED; } - RPC + LITERAL: cada parametro é mapeado para wsdl:part, que contém o seu schema - DOCUMENT + LITERAL + BARE: a mensagem inteira é um único schema - DOCUMENT + LITERAL + WRAPPED: a mensagem é um schema, que é envolvido sob um elemento root com o mesmo nome da operação

. @WebParam public @interface WebParam { public enum Mode {IN, OUT, INOUT}; String name( ) default ""; String targetNamespace( ) default ""; Mode mode( ) default Mode.IN; boolean header( ) default false; } . @WebResult public @interface WebResult { String name( ) default ""; String targetNamespace( ) default ""; } . @OneWay - Pré-define que a operação não retorna nenhum valor, podendo otimizar a implementação através de uma chamada assíncrona (o wsdl não possui o elemento <output>)

- Interceptors . Mesmo ciclo de vida do bean . Acessa mesmos contextos do bean . Pode usar contexto de persistencia extended apenas se interceptar beanstatefull . Não deve ser declarado static nem final . Apenas a nivel de classe pode interceptar callbacks do bean . O bean não precisa ter o callback declarado para isso (getMethod retornará null) . No caso de um método AroundInvoke overrideado, o pai não é executado, e o filho é executado apenas se tiver a anotação também . Pode ter mais de um AroundInvoke na mesma classe (tanto interceptor quanto bean) . Os interceptadores de callback podem ter apenas um de cada tipo (poremno caso de herança de interceptors, usa a mesma regra) . Não pode ser um método da interface de negocio do bean . Não pode lançar uma application-exception que não seja declarada na interface de negocio . Assinatura: - Interceptor de método: <qualquer mod acesso> Object <METODO>(InvocationContext)

Página 54

Page 55: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt - Interceptor de callback: <qualquer mod acesso> void <METODO>(InvocationContext) ------------------------------------------------------------------------------------------------------

- JNDI ENC e Injeção . Um único ENC para cada bean (compartilhado apenas com seus interceptors) . O lookup sempre retorna uma nova instância do recurso, exceto para: - String - Objeto singleton - Objeto definido para ser compartilhavel (ex. java:comp/ORB) . O campo/método que recebe a injeção não pode ser static, e se for campo não pode ser final . Nome JNDI injetado a método segue a nomenclatura JavaBeans do método, independente do campo . Nomenclatura: java:comp/env/NOME_QUALIFICADO_CLASSE/NOME_JAVABEAN_ATRIBUTO_OU_METODO . No caso de herança, podem ser anotados campos na superclasse para serem injetados, porém as regras de override se aplicam (a injeção pode ser modificada ou anulada na classe filha) . Pode ser injetado um bean JEE 2.1, utilizando sua interface Home . Mesmo campos que não são herdados podem pedir injeção . Quando o tipo de referência de um campo não consegue especificar o tipo de recurso, é preciso especificar o tipo na anotação . A injeção é feita depois do EJBContext ser configurado

------------------------------------------------------------------------------------------------------

- Timer Service . Não pode ser criado para bean STATEFULL . O timer sobrevive a container-crash, server-shutdown, etc . É transacional no escopo da transação corrente (tanto a criação quantoo método de ejbTimeout) . Bean pode conter apenas um método de timeout . O método de timeout não deve ser static nem final . Não deve lançar application-exception . Devido ao trabalho do container, o metodo talvez não seja executado exatamente na hora certa . É executado pelo container, portanto não há contexto de segurança de chamador associado (o metodo getCallerPrincipal retorna um principal não-autenticado) . Podem ser comparados entre si com o método equals (o operador == não funciona) . A referencia retornada por getHandle() é local, e não deve ser passadopor uma chamada remota . No caso de herança, o metodo de timeout pode ser definido em qualquer superclasse do bean . Assinatura: - Usando anottation: <qualquer mod acesso> void <METODO>(Timer) - Implementando interface TimedObject: public void ejbTimeout(Timer timer)

------------------------------------------------------------------------------------------------------

- EJBContext . getTimerService não pode ser chamado em bean statefull (IllegalStateException)

- SessionContext . setRollbackOnly e getRollbackOnly podem ser chamados apenas em beans CMT (IllegalStateException) . getUserTransaction pode ser chamado apenas em bean BMT

Página 55

Page 56: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt(IllegalStateException) . getMessageContext pode ser chamado apenas em bean que implementa um endpoint WS . getBusinessObject pode ser chamado apenas em bean que utiliza interface EJB 3.0 . getEJBObject, getEJBLocalObject, getEJBHome, getEJBLocalHome pode ser chamado apenas por bean que implementa a respectiva interface . O método de lookup do EJBContext já encapsula o InitialContext e o narrow

- Interoperabilidade EJB 2.1 e EJB 3.0 . Cliente 3.0 / Bean 2.1: - Injeta a Home, e chama o método create(), depois utiliza a referência normalmente . Cliente 2.1 / Bean 3.0 - Adiciona a Home ao bean 3.0, faz lookup, chama create() e utiliza a referencia normalmente . Cliente 2.1 / EntityManager - Faz lookup ao EntityManager e utiliza normalmente

------------------------------------------------------------------------------------------------------

- Statefull vs Stateless . Apassivação de bean statefull: - apenas se ele não tiver em uma transação - se tiver contexto extendido, precisa: todas entities serem serializáveis e EntityManager ser serializável - Remote vs Local Interfaces . Requerimentos para Business Interfaces - a interface não pode extender EJBObject ou EJBLocalObject - não deve declarar throws RemoteException (apenas se a interface extender java.rmi.Remote) - se um bean implementa uma interface, ela é por padrão local sefor omitida a anotação - não pode anotar uma mesma interface como @Local e @Remote simultaneamente - se houver a definição da interface via metadata, o bean não precisa implementar literalmente a interface (porém é uma boa prática) - Session Bean . Precisa ser public . Não pode ser final nem abstract . Precisa de construtor sem argumentos . Não pode definir método finalize() . Precisa implementar toda a interface de negócio . Precisa ser uma Top Level Class (oposto de inner-class) . Não pode ter uma superclasse que é session bean . Precisam ser anotadas ou declaradas (apenas implementar SessionBean não vale) . Bean statefull não precisa implementar Serializable (container deve prover apassivação mesmo se não for) . Apenas statefull pode implementar SessionSynchronization interface - Callbacks . Se PrePassivate ou PostActivate for definido para bean stateless, seráignorado . Eles executam em um contexto não especificado de transação e segurança . Se o bean implementa a interface SessionBean, as anotação são permitidas somente aos métodos reais . Método @Remove fornece opção booleana retainIfException() que não remove se ocorrer

Página 56

Page 57: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt uma application-exception

- Message Driven Bean . Precisa ser public . Não pode ser final nem abstract . Precisa de construtor sem argumentos . Não pode definir método finalize() . Precisa ser uma Top Level Class (oposto de inner-class) . Pode implementar ejbCreate . Precisa implementar MessageDriven interface, porém é obrigatório a anotação @MessageDriven ou então a declaração no ejb-jar.xml . Pode ter mais de um método onMessage, porém o JCA determinará qual será chamado (apenas um) . As mensagens podem vir fora de ordem . Em caso de herança, pode definir os métodos de callback em qualquer superclasse . Acknowledge nunca pode ser setado programaticamente pela api JMS: - Se o bean for CMT: ocorre automaticamente pelo container, na hora do commit - Se o bean for BMT: o acknowledge não fará parte da transação, onde poderá ser setado: . AUTO_ACKNOWLEDGE (padrão) . DUPS_OK_ACKNOWLEDGE

------------------------------------------------------------------------------------------------------

- Persistence Entities . Precisa ter anotação @Entity ou declarada no xml . Precisa de construtor sem argumentos (public ou protected) . Precisa ser uma Top Level Class (oposto de inner-class) . Precisa ter uma primary key - @Id . Não pode ser final . Atributos persistentes não podem ser final . Atributos persistentes não podem ser public (não devem ser acessados diretamente por clientes da classe) . Para ser passada por invocação remota, precisa implementar Serializable . Entities podem ser concretas ou abstratas . Entities podem extender entities e non-entities . Non-entities podem extender entities . Não pode haver anotações de mapeamento em atributos / getters transientes . Não pode misturar definição field-based com property-based na mesma entitdade (comportamento indefinido) . Se usado acesso property-based, o provider pode executar validações que estejam no método . Coleções podem ser: Collection, Set, List, Map (e suas variações generics) . Erro de base causa rollback e lança uma PersistenceException ------------------------------------------------------------------------------------------------------

- Transações . BMT: - Bean stateless precisa terminar a transação antes de retornar o método (ou do último interceptor), caso contrário ocorre: log + rollback + EJBException + fim da instancia - Bean statefull pode manter a mesma transação entre chamadas demétodos diferentes - Bean BMT não deve usar EJBContext.setRollbackOnly nem EJBContext.getRollbackOnly (para isso servem UserTransaction.getStatus e UserTransaction.rollback)

Página 57

Page 58: Resumo Anotacoes Certificacao SCBCD 5

Resumo_Anotacoes_Certificacao_SCBCD_5.txt - O container deve disponibilizar UserTransaction para: . Interfaces de negócio (ou superinterfaces de negócio) . Método message-listener . Interceptor . Timeout - Não deve usar métodos de transação de APIs específicas dos recursos (apenas EntityManager) . CMT: - Não deve usar métodos de transação de APIs específicas dos recursos e não pode obter uma UserTransaction - Bean MDB: o contexto da transação é criado antes da entrega damensagem - Apenas o Bean Provider deve especificar os metadados de CMT - Quando uma transação não propaga (devido ao atributo de transação), a do cliente apenas fica suspensa, retornando na volta do método - Restrições, pode apenas: . onMessage - REQUIRED, NOT_SUPPORTED . @Timeout - REQUIRED, REQUIRES_NEW, NOT_SUPPORTED . SessionSyncronization - REQUIRED, REQUIRES_NEW, MANDATORY - Especificação do atributos de transação: . Nível de classe: é aplicado a todos os métodos da interface de negócio . Nível de Método: sobrescreve para aquele método . Superclasse: aplica aos métodos da int. de negócio definidos na superclasse, podendo ser sobrescritos pela subclasse - Se chamar setRollbackOnly, o container processa normalmente o método e efetua o rollback depois do retorno ser enviado ao cliente - Ocorre IllegalStateException se chamar setRollbackOnly ou getRollbackOnly para SUPPORTS, NOT_SUPPORTED e NEVER

- SessionSynchronization . Apenas para bean Statefull e CMT . afterBegin - Ocorre antes da primeira chamada transacional - Já está no escopo da transação . beforeCompletion - Ocorre no fim do método quando é para comitar, mas antes do commit efetivo da transação - Ainda está no escopo da transação - Chamar setRollbackOnly consegue reverter a transação . afterCompletion - Ocorre no fim do método sempre, enviando booleano falando de teve commit ou rollback

------------------------------------------------------------------------------------------------------

- Exception Handling . Aplication-exception: - Pode ser filha de Exception ou RuntimeException - Não pode ser filha de java.rmi.RemoteException - Propagada ao cliente sem mudanças - Não causa rollback (ao menos que seja filha de RuntimeException e não esteja anotada) . System-exception - Qualquer java.rmi.RemoteException ou RuntimeException não anotada - Causa rollback da exceção - Container: loga + lança EJBException + mata instancia

Página 58