11. 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
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 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
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 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();
...
17. •
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
19. 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
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
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)
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 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
27. @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
28. 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.
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 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
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 Concrete Class:
@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class BillingDetails implements Serializable, Comparable { . . . }
@Entity
public class CreditCard extends BillingDetails{ . . }
35. 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>();
...
}
38. 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( )
39. 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( )
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);
}
}
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:
✔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
47. 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
48. 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)
49. 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
50. 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
51. 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();
52. 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
54. 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
55. 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
56. 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
57. 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;
}
}
58. 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
59. 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) {
// . . .
}
}
60. 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
62. 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
64. 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
65. 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);
}
}
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
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
70. 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
72. 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
73. 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;
}
}
74. 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;
}
}
75. 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
}
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 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 {
...
}
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
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();
}
80. 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();
}
}
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 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.
85. 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.
}
}