Java EE 6

Elvis Henrique Rocha
Especialista JBoss
elvis.rocha@tecnisys.com.br
JavaEE 6

Tópicos:
•

JavaEE 6 Overview

•

Java Persistence 2.0

•

Enterprise JavaBeans 3.1

•

Contexts and Dependency Injection for Java 1.0
JavaEE 6 Overview
•

Desenvolvimento Simplificado (+ Annotations, + POJO)

•

Perfis: (Web Profile e Full Profile)

•

Novidades:
JAX-RS
Managed Beans
CDI
Bean Validation
EJB 3.1 (Interceptors 1.1)
Container Architecture
Tiers
Profiles
Java Persistence API 2.0
•

Arquitetura do Hibernate:
Hibernate / JPA Entity (EJB 3) – Regras:
Classes anotadas com @Entity e com pelo menos um @Id definido
Classes devem seguir a convenção JavaBeans
Classes, métodos ou variáveis não podem usar final
Deve ter um constructor sem argumentos (public ou protected)
Collections devem ser interfaces (não podem ser implementações)
Classes de alto nível (não pode ser classe interna ou aninhada)
Um Enum ou uma Interface não podem ser classes persistentes
Classes abstratas e concretas podem ser persistentes
Usar serializable para objetos detachados
Sem interface para implementar ou classes para extender
Sem programação intrusiva nas classes
JPA Entity:
@Entity
@Table(name = "messages")
public class Message {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String text;
@ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@JoinColumn(name = "message_sender_id")
private Sender sender;
...
}
Tipos de dados:
- Componentes
@Embedded ou @Embeddable (Classes embutidas, as colunas da
classe embeddable ficam na Entity)
@ElementCollection (Coleção de componentes)
- Tipos básicos da JDK:
integer, long, short, float, double, big_decimal, big_integer,
character, string, byte, boolean, yes_no, true_false
- Date/Time:
date, time, timestamp, calendar, calendar_date
- Binary e Large Objects:
binary, text, serializable, clob, blob
- Outros tipos da JDK:
class, locale, timezone, currency
Identidade:
- @Id
Geralmente Integer ou Long
Pode ser gerado através das seguintes estratégias:
GenerationType.SEQUENCE
GenerationType.TABLE
GenerationType.IDENTITY
GenerationType.AUTO
- Quando uma entidade é igual a outra?
Implementar os métodos equals( ) e hashcode( )
equals: Deve verificar a diferença das entidades comparando os
campos de acordo com o objetivo do negócio
Outras anotações:
@Transient - A propriedade não será persistida
@Basic - Para definir a estratégia de Fetch
@Columns - Usado para sobrescrever configurações padrão para
colunas do banco de dados
@Lob - Usado para definir uma especialização do tipo Lob
@Temporal - Usado para definir uma especialização do tipo Date
@Version – Para controle de concorrência na entidade, deve ser
usada em conjunto com uma configuração específica de Lock
LockModeType.OPTIMISTIC_FORCE_INCREMENT ou
LockModeType.PESSIMISTIC_FORCE_INCREMENT
JPA Entity:
public class Item implements Serializable {
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long id = null;
@Version
@Column(name = "OBJ_VERSION")
private int version = 0;
@Column(name = "ITEM_NAME", length = 255, nullable = false, updatable = false)
private String name;
@Embedded
@AttributeOverrides( {
@AttributeOverride(name = "street", column = @Column(name="HOME_STREET", length = 255) ),
@AttributeOverride(name = "city", column = @Column(name="HOME_CITY", length = 255) )
})
private Address homeAddress;
@Temporal(TemporalType.TIMESTAMP)
private Date created = new Date();
...
•

Abordagem para mapeamento:
Top Down: hbm2dll
Bottom up: hbm2java
Middle out: Ambos

•

Configuração:
persistence.xml (JPA)
hibernate.cfg.xml (Hibernate)

•

Persistence Context:
Estado em que as entidades são gerenciadas pelo JPA

•

Persistence Unit:
Unidade agrupadora de entidades e configuração
persistence.xml:
<persistence>
<persistence-unit name="samplePU" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source/>
<class>com.jboss.sample.Message</class>
<class>com.jboss.sample.Sender</class>
<exclude-unlisted-classes/>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
</properties>
</persistence-unit>
</persistence>
Entity Manager:
final EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.persist(new Message("Hello world");
em.getTransaction().commit();
} catch (RuntimeException relevantException) {
if (em.getTransaction().isActive()) {
try {
em.getTransaction().rollback();
} catch (PersistenceException rollBackException) {
logger.warn("Rollback of open transaction failed", RollBackException);
}
throw relevantException;
}
} finally {
em.close();
}

EntityManager:
- Não reutilizar
- Fechar no final - close()
- Em caso de erro dar rollback na transação
para liberar recursos do banco de dados
Métodos do Entity Manager:
sender.setName("Correct name");
final EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Sender newSenderInstance = em.merge(sender);
em.getTransaction().commit();
em.close();
// Hibernate
Session session = (Session) em.getDelegate();
session.update(sender);
// alternatively
session.buildLockRequest(LockOptions.NONE).lock(sender);

- Inserir:
persist( ), save( )
- Atualizar:
update( ), merge( ), saveOrUpdate( )
- Reatachar um objeto não modificado:
lock( )
Métodos do Entity Manager:
final EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Sender sender = em.find(Sender.class, '1');
em.remove(sender);
em.getTransaction().commit();
em.close();
// Hibernate
Session session = (Session) em.getDelegate();
Sender sender = session.get(Sender.class, '1');
session.delete(sender);

- Remover:
remove( ), delete( )
- A entidade precisa estar atachada para ser removida.
Relacionamento de entidades:
@Embedded
@OneToOne
@OneToOne Bidirecional
@OneToMany
@OneToMany Bidirecional
@ManyToMany
@OneToOne:
@Entity
public class Address {
@OneToOne
@JoinColumn(name="user_id")
private User user;

@Entity
public class User {
@Id
@GeneratedValue(generator = "foreign_id")
private Integer id;

Exemplo 1:
@OneToOne(mappedBy=”user”)
private Address address;

Usando uma Foreign Key
Exemplo 1:
Usando o mesmo valor de Primary Key
@PrimaryKeyJoinColumn
Usa o mesmo valor de Id para ambas as tabelas
@ManyToOne e @OneToMany:
@Entity
public class Item {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "SELLER_ID", nullable = false, updatable = false)
private User seller;
...
}

@Entity
public class User {
@OneToMany(mappedBy = "seller")
private Collection<Item> itemsForSale = new ArrayList<Item>();
...
}

Exemplo 1:
ManyToOne Unidirecional
Exemplo 2:
ManyToOne Bidirecional (mappedBy)
@ManyToMany:
@Entity
public class Category {
@ManyToMany
@JoinTable(name = "CATEGORY_ITEM",
joinColumns = @JoinColumn(name = "CATEGORY_ID"),
InverseJoinColumns = @JoinColumn(name = "ITEM_ID") )
private List<Item> items = new ArrayList<Item>();
...
}
@Entity
public class Item {
@ManyToMany(mappedBy="items")
private Set<Category> categories = new HashSet<Category>();
...
}

Exemplo 1:
ManyToMany Unidirecional
Exemplo 2:
ManyToMany Bidirecional (mappedBy)
@ManyToMany com campo adicional:
public class StudentCourse {
private StudentCourseID pk = new StudentCourseID();
@Column(name = "CAPACITY", nullable = false, length = 10)
private String capacity;
@EmbeddedId
public StudentCourseID getPk() {
return pk;
}
@Embeddable
public class StudentCourseID implements java.io.Serializable {
private Student student;
private Course course;
@ManyToOne
public Course getCourse() {
return course;
}
@ManyToOne
public Student getStudent() {
return student;
}

Exemplo 1:
Classe Associativa com o campo adicional capacity
Exemplo 2:
Classe embutida definida como EmbeddableId
@IndexColumn e @OrderBy:
@Entity
public class Item {
...
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "ITEM_ID", nullable = false)
@org.hibernate.annotations.IndexColumn(name = "BID_POSITION")
private List<Bid> bids = new ArrayList<Bid>();
}
@Entity
public class Category implements Serializable, Comparable<Object> {
...
@OneToMany(mappedBy="parentCategory", cascade={CascadeType.PERSIST, CascadeType.MERGE})
@org.hibernate.annotations.OrderBy(clause="CATEGORY_NAME asc")
private List<Category> childCategories = new ArrayList<Category>();

Exemplo 1:
@IndexColumn para definir o campo índice na lista
e evitar entidades duplicadas (bag semantics)
Exemplo 2:
@OrderBy define o ordenamento padrão
Estratégias de Herança:
Table per Class:
As classes são mapeadas em uma única tabela, a coluna que
define a entidade é configurada através da anotação
@DiscriminatorColumn
Table per Subclass:
Schema normalizado, cada subclasse na hierarquia tem sua
própria tabela e o relacionamento é definido através de Foreign
Keys.
Table per Concrete Class:
Cada tabela concreta tem sua própria tabela, não há o conceito
de herança a nível de banco de dados, os campos da tabela pai
são duplicados em cada uma das tabelas.
Table per Class (SINGLE_TABLE):
✔Melhor performance
✔Melhor representação de polimorfismo
✘Não normalizado
✘Requer uma coluna para especificar o tipo de classe
Table per Subclass (JOINED):
✔Schema claro e conciso
✔Totalmente normalizado
✔Fácil de implementar e de entender
✘Queries polimórficas podem ter um desempenho ruim se a
hierarquia for muito grande
✘Maior dificuldade na escrita de consultas SQL
Table per Concrete Class (TABLE_PER_CLASS):
✔Sem noção de herança a nível de banco de dados
✔Sem detalhes de herança no mapeamento
✘Complexidade em evoluir o schema
✘Não suporta Queries JPA totalmente polimórficas
Table per Class:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name=”BILLING_TYPE”, discriminatorType = DiscriminatorType.STRING)
public class BillingDetails implements Serializable, Comparable { . . . }
@Entity
public class CreditCard extends BillingDetails{ . . }

Table per Subclass:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class BillingDetails implements Serializable, Comparable { . . . }
@Entity
public class CreditCard extends BillingDetails{ . . }
Table per Concrete Class:
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class BillingDetails implements Serializable, Comparable { . . . }
@Entity
public class CreditCard extends BillingDetails{ . . }
Cascade:
JPA:
MERGE
PERSIST
REMOVE
REFRESH
DETACH

@OneToMany(cascade={
javax.persistence.CascadeType.PERSIST,
javax.persistence.CascadeType.MERGE})
@org.hibernate.annotations.Cascade(value = {
CascadeType.SAVE_UPDATE,
CascadeType.PERSIST,
CascadeType.MERGE})
private Set<Item> items = new HashSet<Item>();

Hibernate:
MERGE
PERSIST
REMOVE
REFRESH
DELETE
SAVE_UPDATE
REPLICATE
DELETE_ORPHAN
LOCK
EVICT
Fetch:
EAGER:
Traz as entidades filhas quando a entidade pai é carregada.
LAZY:
Traz as entidades filhas somente quando o método for
chamado (sob demanda).

@Entity
public class Item {
...
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "ITEM_ID", nullable = false)
private List<Bid> bids = new ArrayList<Bid>();
...
}
Entity Manager e ciclo de vida das entidades:
Entity Manager e ciclo de vida das entidades:
Entity Manager e ciclo de vida das entidades:

✔Persistence Context é o cache de 1º nível onde estão todas as
entidades gerenciadas pelo Hibernate
✔Inicia no entityManager.open() e se encerra no
entityManager.close()
✔Pode ser usado no modo extendido para escopo de
Conversação
✔Faz Dirty Checking automaticamente (verifica se o objeto foi
alterado por outra thread antes do commit)
✔Sincronizado automaticamente com o banco de dados no fim
da transação ou quando chamado o método flush()
(FlushMode.AUTO), outros modos: (FlushMode.COMMIT,
FlushMode.MANUAL)
✔É possível excluir objetos do cache através dos métodos
evict( ) e clear( )
Entity Manager e ciclo de vida das entidades:

✔Entidades passam de Transient para Persistent através do
save( ) ou persist( )
✔Entidades obtidas através de Query também são Persistent
✔Quando Persistent elas são gerenciadas e transacionais se
houver transação
✔Passam de Persistent para Transient através do remove( ) ou
quando perdem a referência, exemplo: Orphan delete
✔São detachadas através do evict( ), clear( ) ou close( )
✔Recarregadas do banco através do refresh( )
Caso de uso: Detachar / Reatachar Entitidades
Caso de uso: Modo Extendido
Transações (ACID)

✔Atomicidade, Consistência, Isolamento e Durabilidade
✔Forma programática:
Hibernate Transaction API
JPA Entity Transaction API
Standard JTA UserTransaction API
JDBC API
✔Forma declarativa (requer uma infraestrutura necessária):
EJB
Spring
Interceptors / AOP (Customizada)
Transações
// Programática
UserTransaction utx = (UserTransaction) new InitialContext().lookup(“java:comp/UserTransaction”);
EntityManager em = null;
try {
utx.begin();
em = get().createEntityManager();
concludeAuction(session);
em.flush();
utx.commit();
}
...
// Declarativa
@Stateless
public class ManageAuctionBean implements ManageAuction{
@PersistenceContext
private EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void endAuction( Item item) {
em.merge(item);
}
}
Cache
Cache
1st level cache (sempre ativo)
Recomendações:
Não carregar objetos demais na memória
Não usar ORM para uma carga muito grande, usar Stored
procedures ou SQL
Use scroll( ) para carregar objetos incrementalmente (cursor)
Use evict( ) e clear( ) em processos batch
javax.persistence.cache.retrieveMode
CacheRetrieveMode.USE
CacheRetrieveMode.BYPASS
javax.persistence.cache.storeMode
CacheStoreMode.USE
CacheStoreMode.BYPASS
CacheStoreMode.REFRESH
Cache
2nd level cache
Recomendações:
✔Usar para dados compartilhados entre usuários e não
específicos de um usuário
✔Usar para dados que mudam raramente
✔Usar para dados não críticos e que não são compartilhados
com outras aplicações
✔Não utilizar para um número muito grande de objetos
Providers:
EhCache
OpenSymphony OSCache
JBossCache
Infinispan
Cache
Estratégia de Concorrência
transactional
Isolamento total acima de repeatable-read, usar quando for
crítico preservar o estado dos dados em transações
concorrentes
read-write
Isolamento read-commited, em ambientes não-clusterizados, usa
um mecanismo de timestamp para a maioria dos dados
nonstrict-read-write
Não garante a consistência, tem um tempo de expiração
read-only
Para dados que nunca mudam, dados usados como referência
Isolation-levels
SERIALIZABLE
Lock de read e write na transações
Se houver colisão somente um faz o commit
Nível mais alto de confiabilidade, não ocorre phantom reads
REPEATABLE_READ
Lock de read e write na transações
Pode ocorrer phantom reads (ler no início da transação e no
final o dado já ter sido alterado por outra transação)
READ_COMMITED
Lock de read em selects e write em transações
Pode ocorrer phantom reads, mas só lê o que foi feito commit de
outras transações
READ_UNCOMMITED
Não faz lock
Faz Dirty Reads (lê dados de outras transações que ainda não
sofreram commit)
Estratégias de Fetch
@Fetch(FetchMode.SELECT)
Estratégia default de fetch
@Fetch(FetchMode.JOIN)
Traz a Entity pai e suas collections com um único select através
de Join quando a Entity pai é carregada
@Fetch(FetchMode.SUBSELECT)
Traz a Entity pai e suas collections com um único select através
de subselect quando a Entity pai é carregada
@BatchSize(size = 10)
Para cada elemento que possui uma collection, ele faz (1+n)
selects, sendo n o size da collection, o Batch vai fazer com que faça
um select para trazer 10 elementos de uma vez ao invés de um
select para cada elemento
Estratégias de Fetch
@Fetch(FetchMode.SELECT)
Estratégia default de fetch
@Fetch(FetchMode.JOIN)
Traz a Entity pai e suas collections com um único select através
de Join quando a Entity pai é carregada
@Fetch(FetchMode.SUBSELECT)
Traz a Entity pai e suas collections com um único select através
de subselect quando a Entity pai é carregada
@BatchSize(size = 10)
Problema: Para cada elemento que possui uma collection, ele faz
(1+n) selects, sendo n o size da collection, o Batch vai fazer com que
faça um select para trazer 10 elementos de uma vez ao invés de um
select para cada elemento
Extra Lazy Collections
@LazyCollection(LazyCollectionOption.EXTRA)
Não traz o conteúdo da collection se somente os métodos size( )
ou contains( ) foram chamados.
Solução para o problema n+1
Usar o Fetch quando necessário de acordo com a necessidade
de negócio

// CRITERIA
List results = session.createCriteria(Item.class).setFetchMode("bids", FetchMode.JOIN).list();
// HQL
List results = session.createQuery("select i from Item i left
join fetch i.bids").list();
// DISTINCT
session.createCriteria(Item.class)
.setFetchMode("bids", FetchMode.JOIN)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
Tuning e melhores práticas
Um join é mais rápido que dois selects?
Complexidade das queries, HQL, SQL ou Criteria? Recuperar pelo id
Quantidade de hits no banco, usar cache?
Compressão no cliente e no servidor ( - Memória = + CPU )
Onde e quais objetos devo guardar? ( escopos, 2nd level cache )
@RequestScoped - Acaba no fim da requisição, não tem lembrança
@ViewScoped - Escopo de tela (mantem os componentes, ajax)
@SessionScoped - Não guardar listas, só dados de usuário, perfil, etc.
@ApplicationScoped - Comum para a aplicação
@Conversation - Não esquecer do @End
Usar DAO? Usar DTO?
Usar estratégias de Fetch
Enterprise JavaBeans 3.1
Enterprise Java Beans
Session Beans
Message Driven Beans
Entity Beans
Benefícios:
Foco na lógica de negócio, segurança, acesso remoto, suporte a
transação e concorrência, multithreading, connection pool, gerência do
cico de vida dos objetos
Novidades EJB 3.1
Interfaces são opcionais
Singleton Beans
EJB Assíncrono
Timer
EJB.Lite
Suporte para EJBs no servlet container (deploy de um EJB em um
arquivo WAR)
Suporte para Stateful Web Services via Stateful Endpoints
Entity Beans = Entidades JPA
Stateful Session Beans
Mantem estado conversacional com o cliente
Objetos POJO Based
Para acesso local não é necessário implementar uma interface,
somente usar a anotação @Stateful
Se for acessado remotamente deve ser criada uma interface e anotada
com @Remote
Um método deve ser anotado com @Remove para indicar onde se
encerra o contexto conversacional
Utiliza por padrão o EntityManager no modo EXTENDED
Métodos do ciclo de vida:
@PreDestroy, @PostContruct
@PrePassivate, @PostActivate
Stateful Session Beans
@Stateful
public class Cart {
List<String> items;
public ShoppingCart() {
items = new ArrayList<Item>();
}
public void addItem(String item) {
items.add(item);
}
public void removeItem(String item) {
items.remove(item);
}
public void purchase() {
// . . .
}
@Remove
public void remove() {
items = null;
}
}
Stateless Session Beans
Não mantém estado conversacional
Objetos POJO Based
Para acesso local não é necessário implementar uma interface,
somente usar anotação @Stateless
Se for acessado remotamente deve ser criada uma interface e anotada
com @Remote
Métodos do ciclo de vida:
@PreDestroy, @PostContruct
Stateless Session Beans
@Remote
public interface Account {
public float withdraw();
public void deposit(float amount);
}

@Stateless
public class AccountSessionBean implements Account {
public float withdraw() {
// . . .
}
public void deposit(String item) {
// . . .
}
}
Singleton Session Beans
Instanciado uma vez na aplicação, provê acesso compartilhado
Uma instância por JVM, suporte a concorrência
Não é necessário implementar uma interface, somente usar anotação
@Singleton
O Container automaticamente inicializa o EJB Singleton mas pode ser
anotado com @Startup para inicialização no modo Eager
A concorrência é definida de forma declarativa em cada método com
@Lock(LockType.READ) ou @Lock(LockType.WRITE)
Para forma programática deve ser usado synchronized e volatile
Métodos do ciclo de vida:
@PreDestroy, @PostContruct
Singleton Session Beans
@Startup
@Singleton
public class MySingleton {
public void delivery() {
// . . .
}
}
Message-Driven Beans
Provê objetos de negócio para suporte a messages assíncronas
JMS Based, Stateless
É preciso implementar a interface MessageListener e utilizar a
anotação @MessageDriven, a interface provê o método: onMessage( )
Configuração do MDB através de @ActivationConfigProperty
Métodos do ciclo de vida:
@PreDestroy, @PostContruct
Message-Driven Beans
@MessageDriven(mappedName="jms/Queue", activationConfig = {
@ActivationConfigProperty(propertyName = "acknowledgeMode",
propertyValue = "Auto-acknowledge"),
@ActivationConfigProperty(propertyName = "destinationType",
propertyValue = "javax.jms.Queue")
@ActivationConfigProperty(propertyName = "subscriptionDurability",
propertyValue = "Durable")
})
public class MyMessageBean implements MessageListener {
@Override
public void onMessage(Message message) {
try {
// process the message
} catch (JMSException ex) {
// . . .
}
}
}
EJB Assíncrono
Um EJB Stateless pode ser definido como assíncrono através da
anotação @Asynchronous
A assinatura do método deve retornar a interface Future que contém
na sua API a lógica para saber se o resultado está disponível através do
método isDone( ) ou cancelar a execução através do método cancel( )
A transação não é propagada nesse tipo de EJB, então por padrão
seus métodos sempre vão ser do tipo REQUIRES_NEW
Métodos do ciclo de vida:
@PreDestroy, @PostContruct
EJB Assíncrono
@Stateless
@Asynchronous
public class MyAsyncBean {
public Future<Integer> addNumbers(int n1, int n2) {
Integer result;
result = n1 + n2;
// simulate a long running query
...
return new AsyncResult(result);
}
}
Timers
Um EJB Timer é um serviço de execução de tarefa agendada definido
com uma anotação @Schedule em um de seus métodos.
O tempo/período de execução pode ser definido através da anotação
@Schedule ou da interface TimerService
O método que vai fazer a execução da tarefa pode ser o método
ejbTimeout(Timer t) da interface TimerService ou um método qualquer
anotado com @Timeout que tenha como argumento (Timer t)
Métodos do ciclo de vida:
initTimer
Timers
@Stateless
public class MyTimer {
@Schedule(hour=”*”, minute=”*”, second=”*/10”)
public void printTime( ) {
// . . .
}
}

public class MyTimer implements TimedObject {
@Resource TimerService timerService;
@PostConstruct
public void initTimer() {
timerService.createCalendarTimer(
new ScheduleExpression().
hour(“*”).
minute(“*”).
second(“*/10”),
new TimerConfig(“myTimer”, true)
);
}
}
EJB.Lite
Um EJB Lite é um componente de negócio com recursos limitados para
execução no Web Profile JavaEE
Nomes Globais JNDI
EJBs podem ser acessados via JNDI através de endereço global:
java:global[ /app-name ] /module-name /bean-name
[ !fully-qualified-interface-name ]
Exemplos:
java:global/bank/AccountSession ou
java:global/bank/AccountSession!org.sample.AccountSessionBean
Outros nomes JNDI:
java:global/bank/AccountSessionBean
java:app/AccountSessionBean
java:module/AccountSessionBean
Transações - @TransactionAttribute
MANDATORY
Sempre deve ser chamado em um contexto de transação
REQUIRED
Se estiver em um contexto de transação ele propaga, se não
estiver ele cria uma nova transação
REQUIRES_NEW
Sempre cria uma nova transação, se já estiver em um contexto
transacional ele suspende e retorna após a nova transação
SUPPORTS
Se já existir uma transação ele suporta, se não existir ele não cria
NOT_SUPPORTED
Se já existir uma transação ele suspende e retorna após o método
NEVER
Se já existir uma transação ele gera javax.ejb.EJBException
Contexts and Dependency Injection
Contexts and Dependency Injection
Mecanismo de injeção de dependências da plataforma JavaEE
Permite a inclusão de componentes com resolução segura de tipos e
validação das dependências em tempo de deploy, promove o baixo
acoplamento tirando a responsabilidade do desenvolvedor de cuidar do
componente
Um Bean CDI ao ser criado tem seu ciclo de vida gerenciado e bem
definido de acordo com qual contexto foi atribuído
EJBs e outros componentes de negócio são tratados pelo JSF como os
Managed Beans criando uma integração da camada Web com a camada
transacional
A Integração se extende também para Expression Language (EL)
permitindo a qualquer objeto ser usado diretamente da camada de
integração até o JSF ou JSP
Definição de um CDI Bean
Praticamente qualquer POJO pode ser definido como Bean CDI, EJBs,
Entidades JPA, recursos JNDI, basta colocar um arquivo beans.xml na
pasta META-INF e cada Bean do pacote pode ser definido como um
bean CDI
// Interface Shipping
public interface Shipping {
public String rate(String name);
}
// Implementação de Shipping
public class PriorityShipping implements Shipping {
public String rate(String name) {
return “Hello ” + name;
}
}
Pontos de Injeção
Um Bean é injetado usando a anotação @Inject que pode ser definida
no campo, no método ou no construtor da classe
@Stateless
public class ShippingService {
// Campo
@Inject Shipping shipping;
...
// Método Set
@Inject
public setShipping(Shipping shipping) {
this.shipping = shipping;
}
...
// Construtor
@Inject
public SimpleShipping(Shipping shipping) {
this.shipping = shipping;
}
}
Qualificadores
Um Qualificador serve para dizer ao CDI qual implementação entre
várias de uma determinada interface deve ser usada
public interface Shipping {
public String getRate( );
}

public class ExpressShipping implements Shipping {
. . . // Por padrão essa classe tem o @Default, é a implementação padrão de Shipping
}

public class PriorityShipping implements Shipping {
. . . // Com essa implementação o Inject não vai funcionar pois são duas
// implementações da mesma interface
}
Qualificadores
@Qualifier
@Retention(RUNTIME)
@Target( { TYPE, METHOD, PARAMETER, FIELD })
public @interface Express{ }
...
public class PriorityShipping implements Shipping {
...
}
@Express
public class ExpressShipping implements Shipping {
...
}
As seguintes injeções podem ser usadas:
@Inject Shipping shipping;
@Inject @Any @Default Shipping shipping;
@Inject @Any @Express Shipping shipping;
@Inject @Any Shipping shipping;
@Inject @Default Shipping shipping
@Inject @Express Shipping shipping

-> Injeta priority
-> Injeta pirority
-> Injeta express
-> Vai dar erro
-> também injeta priority
-> também injeta express
Qualificadores
@New
@RequestScoped
public class PriorityShipping implements Shipping {
...
}
Ao usar o qualificar @New a classe vai para o escopo @Dependent e perde os qualificadores
@Any e @Default
@Inject @New Shipping shipping;

@Named
Permite ao Bean ser acessado via EL (JSF), recomenda-se a
anotação @Named na classe e não no ponto de injeção
@Default
@Named
public class PriorityShipping implements Shipping {
...
}
Alternatives
Com alternatives você pode escolher qual Bean utilizar em tempo
de deploy sem alterar a aplicação
public class PriorityShipping implements Shipping {
...
}
@Alternative
public class ExpressShipping implements Shipping {
...
}
@Inject Shipping shipping; -> Dessa forma irá injetar PriorityShipping
Definir no beans.xml:
<beans ... >
<alternatives>
<class>shipping.ExpressShipping</class>
</alternatives>
</beans>
@Inject Shipping shipping; -> A Injeção agora irá injetar o ExpressShipping
Obs.: Se só houver a implementação @Alternative e não tiver definido no beans.xml a
injeção não vai funcionar
Producer e Disposer
Com alternatives você tem injeção estática, se precisar de
injeção dinâmica você precisa usar Producer
@Produces
public List<String> getShippings() {
List<String> response = new ArrayList<String>();
return response;
}
Por padrão o escopo é @Depedent, producer pode vir com o escopo definido:
@Produces @RequestScoped
public List<String> getShippings() {
List<String> response = new ArrayList<String>();
return response;
}
@Inject List<String> listShippings;
Objetos criados com Producer precisam de uma distruição explícita @Disposes:
void close(@Disposes Connection connection) {
connection.close();
}
Interceptors
Interceptors tem a função de aplicar implementação automática
em um Bean e fazer com que o código seja executado durante o
ciclo de vida do objeto
@InterceptorBinding
@Retention(RUNTIME)
@Target({METHOD,TYPE})
public @interface Logging { . . . }
@Interceptor
@Logging
public class LoggingInterceptor {
@AroundInvoke
// Irá interpor os métodos de negócio
public Object log(InvocationContext context) throws Exception {
Logger.getLogger(getClass().getName().info(context.getMethod().getName());
return context.proceed();
}
}
Interceptors
@Logging
public class ExpressShipping { . . . }
ou
public class ExpressShipping {
@Logging
public String greet(String name) { . . . }
}
@Interceptor
@Transactional
public class TransactionInterceptor {
@Resource UserTransaction tx;
@AroundInvoke
public Object manageTransaction(InvocationContext context) {
tx.begin();
Object response = context.proceed();
tx.commit();
return response;
}
}
É preciso habilitar no beans.xml:
<interceptors>
<class>org.sample.TransactionInterceptor</class>
</interceptors>
Decorators
Um Decorator é uma implementação adicional ao Bean, para os
conceitos relacionados ao negócio, contém ainda um ponto de
injeção com @Delegate que indica onde ele vai delegar essa
implementação
@Decorator
public abstract class ShippingDecorator implements Shipping {
@Inject
@Delegate
@Any
Shipping shipping;
public String labelString(String s, int tval) {
int len = s.length();
return """ + s + "" label " + """ + coder.labelString(s, tval) + len + " length";
}
}
Escopos
Um Bean é criado em um escopo e associado a um contexto, o contexto
gerencia e define o seu ciclo de vida e visibilidade.
@RequestScoped
Disponível durante o request, destruído quando o request tem fim.
@SessionScoped
Compartilhado entre requests da mesma sessão, destruído quando a
sessão dá timeout ou é destruida.
@ApplicationScoped
Criado quando a aplicação sobe, destruído quando ela é derrubada.
@ConversationScoped: Transient e Long-running.
Transient (default): O Bean é criado num request JSF e destruído no fim
do request, pode ser convertido para um long-running através de
Conversation.begin( ) e destruído no Conversation.end( )
@Dependent
Pseudo-escopo, os beans que não tem nenhum escopo declarado.
Stereotype
Encapsula e agrupa papéis em um único local, reduz a quantidade
de anotações necessárias e cria anotações condizentes com o
Bean
@Stereotype
@Retention(RUNTIME)
@Target(TYPE)
@Transactional
@Logging
public @interface MyShippingService { . . . }
Obs.: @Interceptor, @Decorator e @Model são Stereotypes pré-definidos.
Eventos
Eventos provê um modelo de eventos baseado em anotações
como o Pattern Observer, quem gera o evento e quem consome
são desacoplados e se comunicam na mudança de estado
Definindo um evento:
@Inject @Any Event<ServiceShipping> shippingEvent;
ServiceShipping service = new ServiceShipping(product, address);
shippingEvent.fire(service);

Escutando o evento:
public class ProcessItems {
public void processItems(@Observes ServiceShipping service) {
// ... Processa os items a serem entregues.
}
}
Obrigado!

Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0

  • 1.
    Java EE 6 ElvisHenrique Rocha Especialista JBoss elvis.rocha@tecnisys.com.br
  • 2.
    JavaEE 6 Tópicos: • JavaEE 6Overview • Java Persistence 2.0 • Enterprise JavaBeans 3.1 • Contexts and Dependency Injection for Java 1.0
  • 3.
  • 4.
    • Desenvolvimento Simplificado (+Annotations, + POJO) • Perfis: (Web Profile e Full Profile) • Novidades: JAX-RS Managed Beans CDI Bean Validation EJB 3.1 (Interceptors 1.1)
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
    Hibernate / JPAEntity (EJB 3) – Regras: Classes anotadas com @Entity e com pelo menos um @Id definido Classes devem seguir a convenção JavaBeans Classes, métodos ou variáveis não podem usar final Deve ter um constructor sem argumentos (public ou protected) Collections devem ser interfaces (não podem ser implementações) Classes de alto nível (não pode ser classe interna ou aninhada) Um Enum ou uma Interface não podem ser classes persistentes Classes abstratas e concretas podem ser persistentes Usar serializable para objetos detachados Sem interface para implementar ou classes para extender Sem programação intrusiva nas classes
  • 12.
    JPA Entity: @Entity @Table(name ="messages") public class Message { @Id @GeneratedValue private Long id; @Column(nullable = false) private String text; @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST}) @JoinColumn(name = "message_sender_id") private Sender sender; ... }
  • 13.
    Tipos de dados: -Componentes @Embedded ou @Embeddable (Classes embutidas, as colunas da classe embeddable ficam na Entity) @ElementCollection (Coleção de componentes) - Tipos básicos da JDK: integer, long, short, float, double, big_decimal, big_integer, character, string, byte, boolean, yes_no, true_false - Date/Time: date, time, timestamp, calendar, calendar_date - Binary e Large Objects: binary, text, serializable, clob, blob - Outros tipos da JDK: class, locale, timezone, currency
  • 14.
    Identidade: - @Id Geralmente Integerou Long Pode ser gerado através das seguintes estratégias: GenerationType.SEQUENCE GenerationType.TABLE GenerationType.IDENTITY GenerationType.AUTO - Quando uma entidade é igual a outra? Implementar os métodos equals( ) e hashcode( ) equals: Deve verificar a diferença das entidades comparando os campos de acordo com o objetivo do negócio
  • 15.
    Outras anotações: @Transient -A propriedade não será persistida @Basic - Para definir a estratégia de Fetch @Columns - Usado para sobrescrever configurações padrão para colunas do banco de dados @Lob - Usado para definir uma especialização do tipo Lob @Temporal - Usado para definir uma especialização do tipo Date @Version – Para controle de concorrência na entidade, deve ser usada em conjunto com uma configuração específica de Lock LockModeType.OPTIMISTIC_FORCE_INCREMENT ou LockModeType.PESSIMISTIC_FORCE_INCREMENT
  • 16.
    JPA Entity: public classItem implements Serializable { @Id @GeneratedValue @Column(name = "ITEM_ID") private Long id = null; @Version @Column(name = "OBJ_VERSION") private int version = 0; @Column(name = "ITEM_NAME", length = 255, nullable = false, updatable = false) private String name; @Embedded @AttributeOverrides( { @AttributeOverride(name = "street", column = @Column(name="HOME_STREET", length = 255) ), @AttributeOverride(name = "city", column = @Column(name="HOME_CITY", length = 255) ) }) private Address homeAddress; @Temporal(TemporalType.TIMESTAMP) private Date created = new Date(); ...
  • 17.
    • Abordagem para mapeamento: TopDown: hbm2dll Bottom up: hbm2java Middle out: Ambos • Configuração: persistence.xml (JPA) hibernate.cfg.xml (Hibernate) • Persistence Context: Estado em que as entidades são gerenciadas pelo JPA • Persistence Unit: Unidade agrupadora de entidades e configuração
  • 18.
    persistence.xml: <persistence> <persistence-unit name="samplePU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <non-jta-data-source/> <class>com.jboss.sample.Message</class> <class>com.jboss.sample.Sender</class> <exclude-unlisted-classes/> <properties> <propertyname="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/> <property name="javax.persistence.jdbc.user" value="sa"/> <property name="javax.persistence.jdbc.password" value=""/> <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> <property name="cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/> </properties> </persistence-unit> </persistence>
  • 19.
    Entity Manager: final EntityManagerem = emf.createEntityManager(); try { em.getTransaction().begin(); em.persist(new Message("Hello world"); em.getTransaction().commit(); } catch (RuntimeException relevantException) { if (em.getTransaction().isActive()) { try { em.getTransaction().rollback(); } catch (PersistenceException rollBackException) { logger.warn("Rollback of open transaction failed", RollBackException); } throw relevantException; } } finally { em.close(); } EntityManager: - Não reutilizar - Fechar no final - close() - Em caso de erro dar rollback na transação para liberar recursos do banco de dados
  • 20.
    Métodos do EntityManager: sender.setName("Correct name"); final EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Sender newSenderInstance = em.merge(sender); em.getTransaction().commit(); em.close(); // Hibernate Session session = (Session) em.getDelegate(); session.update(sender); // alternatively session.buildLockRequest(LockOptions.NONE).lock(sender); - Inserir: persist( ), save( ) - Atualizar: update( ), merge( ), saveOrUpdate( ) - Reatachar um objeto não modificado: lock( )
  • 21.
    Métodos do EntityManager: final EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Sender sender = em.find(Sender.class, '1'); em.remove(sender); em.getTransaction().commit(); em.close(); // Hibernate Session session = (Session) em.getDelegate(); Sender sender = session.get(Sender.class, '1'); session.delete(sender); - Remover: remove( ), delete( ) - A entidade precisa estar atachada para ser removida.
  • 22.
    Relacionamento de entidades: @Embedded @OneToOne @OneToOneBidirecional @OneToMany @OneToMany Bidirecional @ManyToMany
  • 23.
    @OneToOne: @Entity public class Address{ @OneToOne @JoinColumn(name="user_id") private User user; @Entity public class User { @Id @GeneratedValue(generator = "foreign_id") private Integer id; Exemplo 1: @OneToOne(mappedBy=”user”) private Address address; Usando uma Foreign Key Exemplo 1: Usando o mesmo valor de Primary Key @PrimaryKeyJoinColumn Usa o mesmo valor de Id para ambas as tabelas
  • 24.
    @ManyToOne e @OneToMany: @Entity publicclass Item { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "SELLER_ID", nullable = false, updatable = false) private User seller; ... } @Entity public class User { @OneToMany(mappedBy = "seller") private Collection<Item> itemsForSale = new ArrayList<Item>(); ... } Exemplo 1: ManyToOne Unidirecional Exemplo 2: ManyToOne Bidirecional (mappedBy)
  • 25.
    @ManyToMany: @Entity public class Category{ @ManyToMany @JoinTable(name = "CATEGORY_ITEM", joinColumns = @JoinColumn(name = "CATEGORY_ID"), InverseJoinColumns = @JoinColumn(name = "ITEM_ID") ) private List<Item> items = new ArrayList<Item>(); ... } @Entity public class Item { @ManyToMany(mappedBy="items") private Set<Category> categories = new HashSet<Category>(); ... } Exemplo 1: ManyToMany Unidirecional Exemplo 2: ManyToMany Bidirecional (mappedBy)
  • 26.
    @ManyToMany com campoadicional: public class StudentCourse { private StudentCourseID pk = new StudentCourseID(); @Column(name = "CAPACITY", nullable = false, length = 10) private String capacity; @EmbeddedId public StudentCourseID getPk() { return pk; } @Embeddable public class StudentCourseID implements java.io.Serializable { private Student student; private Course course; @ManyToOne public Course getCourse() { return course; } @ManyToOne public Student getStudent() { return student; } Exemplo 1: Classe Associativa com o campo adicional capacity Exemplo 2: Classe embutida definida como EmbeddableId
  • 27.
    @IndexColumn e @OrderBy: @Entity publicclass Item { ... @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "ITEM_ID", nullable = false) @org.hibernate.annotations.IndexColumn(name = "BID_POSITION") private List<Bid> bids = new ArrayList<Bid>(); } @Entity public class Category implements Serializable, Comparable<Object> { ... @OneToMany(mappedBy="parentCategory", cascade={CascadeType.PERSIST, CascadeType.MERGE}) @org.hibernate.annotations.OrderBy(clause="CATEGORY_NAME asc") private List<Category> childCategories = new ArrayList<Category>(); Exemplo 1: @IndexColumn para definir o campo índice na lista e evitar entidades duplicadas (bag semantics) Exemplo 2: @OrderBy define o ordenamento padrão
  • 28.
    Estratégias de Herança: Tableper Class: As classes são mapeadas em uma única tabela, a coluna que define a entidade é configurada através da anotação @DiscriminatorColumn Table per Subclass: Schema normalizado, cada subclasse na hierarquia tem sua própria tabela e o relacionamento é definido através de Foreign Keys. Table per Concrete Class: Cada tabela concreta tem sua própria tabela, não há o conceito de herança a nível de banco de dados, os campos da tabela pai são duplicados em cada uma das tabelas.
  • 29.
    Table per Class(SINGLE_TABLE): ✔Melhor performance ✔Melhor representação de polimorfismo ✘Não normalizado ✘Requer uma coluna para especificar o tipo de classe
  • 30.
    Table per Subclass(JOINED): ✔Schema claro e conciso ✔Totalmente normalizado ✔Fácil de implementar e de entender ✘Queries polimórficas podem ter um desempenho ruim se a hierarquia for muito grande ✘Maior dificuldade na escrita de consultas SQL
  • 31.
    Table per ConcreteClass (TABLE_PER_CLASS): ✔Sem noção de herança a nível de banco de dados ✔Sem detalhes de herança no mapeamento ✘Complexidade em evoluir o schema ✘Não suporta Queries JPA totalmente polimórficas
  • 32.
    Table per Class: @Entity @Inheritance(strategy= InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name=”BILLING_TYPE”, discriminatorType = DiscriminatorType.STRING) public class BillingDetails implements Serializable, Comparable { . . . } @Entity public class CreditCard extends BillingDetails{ . . } Table per Subclass: @Entity @Inheritance(strategy = InheritanceType.JOINED) public class BillingDetails implements Serializable, Comparable { . . . } @Entity public class CreditCard extends BillingDetails{ . . }
  • 33.
    Table per ConcreteClass: @Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public class BillingDetails implements Serializable, Comparable { . . . } @Entity public class CreditCard extends BillingDetails{ . . }
  • 34.
  • 35.
    Fetch: EAGER: Traz as entidadesfilhas quando a entidade pai é carregada. LAZY: Traz as entidades filhas somente quando o método for chamado (sob demanda). @Entity public class Item { ... @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "ITEM_ID", nullable = false) private List<Bid> bids = new ArrayList<Bid>(); ... }
  • 36.
    Entity Manager eciclo de vida das entidades:
  • 37.
    Entity Manager eciclo de vida das entidades:
  • 38.
    Entity Manager eciclo de vida das entidades: ✔Persistence Context é o cache de 1º nível onde estão todas as entidades gerenciadas pelo Hibernate ✔Inicia no entityManager.open() e se encerra no entityManager.close() ✔Pode ser usado no modo extendido para escopo de Conversação ✔Faz Dirty Checking automaticamente (verifica se o objeto foi alterado por outra thread antes do commit) ✔Sincronizado automaticamente com o banco de dados no fim da transação ou quando chamado o método flush() (FlushMode.AUTO), outros modos: (FlushMode.COMMIT, FlushMode.MANUAL) ✔É possível excluir objetos do cache através dos métodos evict( ) e clear( )
  • 39.
    Entity Manager eciclo de vida das entidades: ✔Entidades passam de Transient para Persistent através do save( ) ou persist( ) ✔Entidades obtidas através de Query também são Persistent ✔Quando Persistent elas são gerenciadas e transacionais se houver transação ✔Passam de Persistent para Transient através do remove( ) ou quando perdem a referência, exemplo: Orphan delete ✔São detachadas através do evict( ), clear( ) ou close( ) ✔Recarregadas do banco através do refresh( )
  • 40.
    Caso de uso:Detachar / Reatachar Entitidades
  • 41.
    Caso de uso:Modo Extendido
  • 42.
    Transações (ACID) ✔Atomicidade, Consistência,Isolamento e Durabilidade ✔Forma programática: Hibernate Transaction API JPA Entity Transaction API Standard JTA UserTransaction API JDBC API ✔Forma declarativa (requer uma infraestrutura necessária): EJB Spring Interceptors / AOP (Customizada)
  • 43.
    Transações // Programática UserTransaction utx= (UserTransaction) new InitialContext().lookup(“java:comp/UserTransaction”); EntityManager em = null; try { utx.begin(); em = get().createEntityManager(); concludeAuction(session); em.flush(); utx.commit(); } ... // Declarativa @Stateless public class ManageAuctionBean implements ManageAuction{ @PersistenceContext private EntityManager em; @TransactionAttribute(TransactionAttributeType.REQUIRED) public void endAuction( Item item) { em.merge(item); } }
  • 44.
  • 45.
    Cache 1st level cache(sempre ativo) Recomendações: Não carregar objetos demais na memória Não usar ORM para uma carga muito grande, usar Stored procedures ou SQL Use scroll( ) para carregar objetos incrementalmente (cursor) Use evict( ) e clear( ) em processos batch javax.persistence.cache.retrieveMode CacheRetrieveMode.USE CacheRetrieveMode.BYPASS javax.persistence.cache.storeMode CacheStoreMode.USE CacheStoreMode.BYPASS CacheStoreMode.REFRESH
  • 46.
    Cache 2nd level cache Recomendações: ✔Usarpara dados compartilhados entre usuários e não específicos de um usuário ✔Usar para dados que mudam raramente ✔Usar para dados não críticos e que não são compartilhados com outras aplicações ✔Não utilizar para um número muito grande de objetos Providers: EhCache OpenSymphony OSCache JBossCache Infinispan
  • 47.
    Cache Estratégia de Concorrência transactional Isolamentototal acima de repeatable-read, usar quando for crítico preservar o estado dos dados em transações concorrentes read-write Isolamento read-commited, em ambientes não-clusterizados, usa um mecanismo de timestamp para a maioria dos dados nonstrict-read-write Não garante a consistência, tem um tempo de expiração read-only Para dados que nunca mudam, dados usados como referência
  • 48.
    Isolation-levels SERIALIZABLE Lock de reade write na transações Se houver colisão somente um faz o commit Nível mais alto de confiabilidade, não ocorre phantom reads REPEATABLE_READ Lock de read e write na transações Pode ocorrer phantom reads (ler no início da transação e no final o dado já ter sido alterado por outra transação) READ_COMMITED Lock de read em selects e write em transações Pode ocorrer phantom reads, mas só lê o que foi feito commit de outras transações READ_UNCOMMITED Não faz lock Faz Dirty Reads (lê dados de outras transações que ainda não sofreram commit)
  • 49.
    Estratégias de Fetch @Fetch(FetchMode.SELECT) Estratégiadefault de fetch @Fetch(FetchMode.JOIN) Traz a Entity pai e suas collections com um único select através de Join quando a Entity pai é carregada @Fetch(FetchMode.SUBSELECT) Traz a Entity pai e suas collections com um único select através de subselect quando a Entity pai é carregada @BatchSize(size = 10) Para cada elemento que possui uma collection, ele faz (1+n) selects, sendo n o size da collection, o Batch vai fazer com que faça um select para trazer 10 elementos de uma vez ao invés de um select para cada elemento
  • 50.
    Estratégias de Fetch @Fetch(FetchMode.SELECT) Estratégiadefault de fetch @Fetch(FetchMode.JOIN) Traz a Entity pai e suas collections com um único select através de Join quando a Entity pai é carregada @Fetch(FetchMode.SUBSELECT) Traz a Entity pai e suas collections com um único select através de subselect quando a Entity pai é carregada @BatchSize(size = 10) Problema: Para cada elemento que possui uma collection, ele faz (1+n) selects, sendo n o size da collection, o Batch vai fazer com que faça um select para trazer 10 elementos de uma vez ao invés de um select para cada elemento
  • 51.
    Extra Lazy Collections @LazyCollection(LazyCollectionOption.EXTRA) Nãotraz o conteúdo da collection se somente os métodos size( ) ou contains( ) foram chamados. Solução para o problema n+1 Usar o Fetch quando necessário de acordo com a necessidade de negócio // CRITERIA List results = session.createCriteria(Item.class).setFetchMode("bids", FetchMode.JOIN).list(); // HQL List results = session.createQuery("select i from Item i left join fetch i.bids").list(); // DISTINCT session.createCriteria(Item.class) .setFetchMode("bids", FetchMode.JOIN) .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
  • 52.
    Tuning e melhorespráticas Um join é mais rápido que dois selects? Complexidade das queries, HQL, SQL ou Criteria? Recuperar pelo id Quantidade de hits no banco, usar cache? Compressão no cliente e no servidor ( - Memória = + CPU ) Onde e quais objetos devo guardar? ( escopos, 2nd level cache ) @RequestScoped - Acaba no fim da requisição, não tem lembrança @ViewScoped - Escopo de tela (mantem os componentes, ajax) @SessionScoped - Não guardar listas, só dados de usuário, perfil, etc. @ApplicationScoped - Comum para a aplicação @Conversation - Não esquecer do @End Usar DAO? Usar DTO? Usar estratégias de Fetch
  • 53.
  • 54.
    Enterprise Java Beans SessionBeans Message Driven Beans Entity Beans Benefícios: Foco na lógica de negócio, segurança, acesso remoto, suporte a transação e concorrência, multithreading, connection pool, gerência do cico de vida dos objetos
  • 55.
    Novidades EJB 3.1 Interfacessão opcionais Singleton Beans EJB Assíncrono Timer EJB.Lite Suporte para EJBs no servlet container (deploy de um EJB em um arquivo WAR) Suporte para Stateful Web Services via Stateful Endpoints Entity Beans = Entidades JPA
  • 56.
    Stateful Session Beans Mantemestado conversacional com o cliente Objetos POJO Based Para acesso local não é necessário implementar uma interface, somente usar a anotação @Stateful Se for acessado remotamente deve ser criada uma interface e anotada com @Remote Um método deve ser anotado com @Remove para indicar onde se encerra o contexto conversacional Utiliza por padrão o EntityManager no modo EXTENDED Métodos do ciclo de vida: @PreDestroy, @PostContruct @PrePassivate, @PostActivate
  • 57.
    Stateful Session Beans @Stateful publicclass Cart { List<String> items; public ShoppingCart() { items = new ArrayList<Item>(); } public void addItem(String item) { items.add(item); } public void removeItem(String item) { items.remove(item); } public void purchase() { // . . . } @Remove public void remove() { items = null; } }
  • 58.
    Stateless Session Beans Nãomantém estado conversacional Objetos POJO Based Para acesso local não é necessário implementar uma interface, somente usar anotação @Stateless Se for acessado remotamente deve ser criada uma interface e anotada com @Remote Métodos do ciclo de vida: @PreDestroy, @PostContruct
  • 59.
    Stateless Session Beans @Remote publicinterface Account { public float withdraw(); public void deposit(float amount); } @Stateless public class AccountSessionBean implements Account { public float withdraw() { // . . . } public void deposit(String item) { // . . . } }
  • 60.
    Singleton Session Beans Instanciadouma vez na aplicação, provê acesso compartilhado Uma instância por JVM, suporte a concorrência Não é necessário implementar uma interface, somente usar anotação @Singleton O Container automaticamente inicializa o EJB Singleton mas pode ser anotado com @Startup para inicialização no modo Eager A concorrência é definida de forma declarativa em cada método com @Lock(LockType.READ) ou @Lock(LockType.WRITE) Para forma programática deve ser usado synchronized e volatile Métodos do ciclo de vida: @PreDestroy, @PostContruct
  • 61.
    Singleton Session Beans @Startup @Singleton publicclass MySingleton { public void delivery() { // . . . } }
  • 62.
    Message-Driven Beans Provê objetosde negócio para suporte a messages assíncronas JMS Based, Stateless É preciso implementar a interface MessageListener e utilizar a anotação @MessageDriven, a interface provê o método: onMessage( ) Configuração do MDB através de @ActivationConfigProperty Métodos do ciclo de vida: @PreDestroy, @PostContruct
  • 63.
    Message-Driven Beans @MessageDriven(mappedName="jms/Queue", activationConfig= { @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue") @ActivationConfigProperty(propertyName = "subscriptionDurability", propertyValue = "Durable") }) public class MyMessageBean implements MessageListener { @Override public void onMessage(Message message) { try { // process the message } catch (JMSException ex) { // . . . } } }
  • 64.
    EJB Assíncrono Um EJBStateless pode ser definido como assíncrono através da anotação @Asynchronous A assinatura do método deve retornar a interface Future que contém na sua API a lógica para saber se o resultado está disponível através do método isDone( ) ou cancelar a execução através do método cancel( ) A transação não é propagada nesse tipo de EJB, então por padrão seus métodos sempre vão ser do tipo REQUIRES_NEW Métodos do ciclo de vida: @PreDestroy, @PostContruct
  • 65.
    EJB Assíncrono @Stateless @Asynchronous public classMyAsyncBean { public Future<Integer> addNumbers(int n1, int n2) { Integer result; result = n1 + n2; // simulate a long running query ... return new AsyncResult(result); } }
  • 66.
    Timers Um EJB Timeré um serviço de execução de tarefa agendada definido com uma anotação @Schedule em um de seus métodos. O tempo/período de execução pode ser definido através da anotação @Schedule ou da interface TimerService O método que vai fazer a execução da tarefa pode ser o método ejbTimeout(Timer t) da interface TimerService ou um método qualquer anotado com @Timeout que tenha como argumento (Timer t) Métodos do ciclo de vida: initTimer
  • 67.
    Timers @Stateless public class MyTimer{ @Schedule(hour=”*”, minute=”*”, second=”*/10”) public void printTime( ) { // . . . } } public class MyTimer implements TimedObject { @Resource TimerService timerService; @PostConstruct public void initTimer() { timerService.createCalendarTimer( new ScheduleExpression(). hour(“*”). minute(“*”). second(“*/10”), new TimerConfig(“myTimer”, true) ); } }
  • 68.
    EJB.Lite Um EJB Liteé um componente de negócio com recursos limitados para execução no Web Profile JavaEE
  • 69.
    Nomes Globais JNDI EJBspodem ser acessados via JNDI através de endereço global: java:global[ /app-name ] /module-name /bean-name [ !fully-qualified-interface-name ] Exemplos: java:global/bank/AccountSession ou java:global/bank/AccountSession!org.sample.AccountSessionBean Outros nomes JNDI: java:global/bank/AccountSessionBean java:app/AccountSessionBean java:module/AccountSessionBean
  • 70.
    Transações - @TransactionAttribute MANDATORY Sempredeve ser chamado em um contexto de transação REQUIRED Se estiver em um contexto de transação ele propaga, se não estiver ele cria uma nova transação REQUIRES_NEW Sempre cria uma nova transação, se já estiver em um contexto transacional ele suspende e retorna após a nova transação SUPPORTS Se já existir uma transação ele suporta, se não existir ele não cria NOT_SUPPORTED Se já existir uma transação ele suspende e retorna após o método NEVER Se já existir uma transação ele gera javax.ejb.EJBException
  • 71.
  • 72.
    Contexts and DependencyInjection Mecanismo de injeção de dependências da plataforma JavaEE Permite a inclusão de componentes com resolução segura de tipos e validação das dependências em tempo de deploy, promove o baixo acoplamento tirando a responsabilidade do desenvolvedor de cuidar do componente Um Bean CDI ao ser criado tem seu ciclo de vida gerenciado e bem definido de acordo com qual contexto foi atribuído EJBs e outros componentes de negócio são tratados pelo JSF como os Managed Beans criando uma integração da camada Web com a camada transacional A Integração se extende também para Expression Language (EL) permitindo a qualquer objeto ser usado diretamente da camada de integração até o JSF ou JSP
  • 73.
    Definição de umCDI Bean Praticamente qualquer POJO pode ser definido como Bean CDI, EJBs, Entidades JPA, recursos JNDI, basta colocar um arquivo beans.xml na pasta META-INF e cada Bean do pacote pode ser definido como um bean CDI // Interface Shipping public interface Shipping { public String rate(String name); } // Implementação de Shipping public class PriorityShipping implements Shipping { public String rate(String name) { return “Hello ” + name; } }
  • 74.
    Pontos de Injeção UmBean é injetado usando a anotação @Inject que pode ser definida no campo, no método ou no construtor da classe @Stateless public class ShippingService { // Campo @Inject Shipping shipping; ... // Método Set @Inject public setShipping(Shipping shipping) { this.shipping = shipping; } ... // Construtor @Inject public SimpleShipping(Shipping shipping) { this.shipping = shipping; } }
  • 75.
    Qualificadores Um Qualificador servepara dizer ao CDI qual implementação entre várias de uma determinada interface deve ser usada public interface Shipping { public String getRate( ); } public class ExpressShipping implements Shipping { . . . // Por padrão essa classe tem o @Default, é a implementação padrão de Shipping } public class PriorityShipping implements Shipping { . . . // Com essa implementação o Inject não vai funcionar pois são duas // implementações da mesma interface }
  • 76.
    Qualificadores @Qualifier @Retention(RUNTIME) @Target( { TYPE,METHOD, PARAMETER, FIELD }) public @interface Express{ } ... public class PriorityShipping implements Shipping { ... } @Express public class ExpressShipping implements Shipping { ... } As seguintes injeções podem ser usadas: @Inject Shipping shipping; @Inject @Any @Default Shipping shipping; @Inject @Any @Express Shipping shipping; @Inject @Any Shipping shipping; @Inject @Default Shipping shipping @Inject @Express Shipping shipping -> Injeta priority -> Injeta pirority -> Injeta express -> Vai dar erro -> também injeta priority -> também injeta express
  • 77.
    Qualificadores @New @RequestScoped public class PriorityShippingimplements Shipping { ... } Ao usar o qualificar @New a classe vai para o escopo @Dependent e perde os qualificadores @Any e @Default @Inject @New Shipping shipping; @Named Permite ao Bean ser acessado via EL (JSF), recomenda-se a anotação @Named na classe e não no ponto de injeção @Default @Named public class PriorityShipping implements Shipping { ... }
  • 78.
    Alternatives Com alternatives vocêpode escolher qual Bean utilizar em tempo de deploy sem alterar a aplicação public class PriorityShipping implements Shipping { ... } @Alternative public class ExpressShipping implements Shipping { ... } @Inject Shipping shipping; -> Dessa forma irá injetar PriorityShipping Definir no beans.xml: <beans ... > <alternatives> <class>shipping.ExpressShipping</class> </alternatives> </beans> @Inject Shipping shipping; -> A Injeção agora irá injetar o ExpressShipping Obs.: Se só houver a implementação @Alternative e não tiver definido no beans.xml a injeção não vai funcionar
  • 79.
    Producer e Disposer Comalternatives você tem injeção estática, se precisar de injeção dinâmica você precisa usar Producer @Produces public List<String> getShippings() { List<String> response = new ArrayList<String>(); return response; } Por padrão o escopo é @Depedent, producer pode vir com o escopo definido: @Produces @RequestScoped public List<String> getShippings() { List<String> response = new ArrayList<String>(); return response; } @Inject List<String> listShippings; Objetos criados com Producer precisam de uma distruição explícita @Disposes: void close(@Disposes Connection connection) { connection.close(); }
  • 80.
    Interceptors Interceptors tem afunção de aplicar implementação automática em um Bean e fazer com que o código seja executado durante o ciclo de vida do objeto @InterceptorBinding @Retention(RUNTIME) @Target({METHOD,TYPE}) public @interface Logging { . . . } @Interceptor @Logging public class LoggingInterceptor { @AroundInvoke // Irá interpor os métodos de negócio public Object log(InvocationContext context) throws Exception { Logger.getLogger(getClass().getName().info(context.getMethod().getName()); return context.proceed(); } }
  • 81.
    Interceptors @Logging public class ExpressShipping{ . . . } ou public class ExpressShipping { @Logging public String greet(String name) { . . . } } @Interceptor @Transactional public class TransactionInterceptor { @Resource UserTransaction tx; @AroundInvoke public Object manageTransaction(InvocationContext context) { tx.begin(); Object response = context.proceed(); tx.commit(); return response; } } É preciso habilitar no beans.xml: <interceptors> <class>org.sample.TransactionInterceptor</class> </interceptors>
  • 82.
    Decorators Um Decorator éuma implementação adicional ao Bean, para os conceitos relacionados ao negócio, contém ainda um ponto de injeção com @Delegate que indica onde ele vai delegar essa implementação @Decorator public abstract class ShippingDecorator implements Shipping { @Inject @Delegate @Any Shipping shipping; public String labelString(String s, int tval) { int len = s.length(); return """ + s + "" label " + """ + coder.labelString(s, tval) + len + " length"; } }
  • 83.
    Escopos Um Bean écriado em um escopo e associado a um contexto, o contexto gerencia e define o seu ciclo de vida e visibilidade. @RequestScoped Disponível durante o request, destruído quando o request tem fim. @SessionScoped Compartilhado entre requests da mesma sessão, destruído quando a sessão dá timeout ou é destruida. @ApplicationScoped Criado quando a aplicação sobe, destruído quando ela é derrubada. @ConversationScoped: Transient e Long-running. Transient (default): O Bean é criado num request JSF e destruído no fim do request, pode ser convertido para um long-running através de Conversation.begin( ) e destruído no Conversation.end( ) @Dependent Pseudo-escopo, os beans que não tem nenhum escopo declarado.
  • 84.
    Stereotype Encapsula e agrupapapéis em um único local, reduz a quantidade de anotações necessárias e cria anotações condizentes com o Bean @Stereotype @Retention(RUNTIME) @Target(TYPE) @Transactional @Logging public @interface MyShippingService { . . . } Obs.: @Interceptor, @Decorator e @Model são Stereotypes pré-definidos.
  • 85.
    Eventos Eventos provê ummodelo de eventos baseado em anotações como o Pattern Observer, quem gera o evento e quem consome são desacoplados e se comunicam na mudança de estado Definindo um evento: @Inject @Any Event<ServiceShipping> shippingEvent; ServiceShipping service = new ServiceShipping(product, address); shippingEvent.fire(service); Escutando o evento: public class ProcessItems { public void processItems(@Observes ServiceShipping service) { // ... Processa os items a serem entregues. } }
  • 86.