Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0

2.667 visualizações

Publicada em

Java EE 6 tópicos avançados

Publicada em: Tecnologia
0 comentários
6 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
2.667
No SlideShare
0
A partir de incorporações
0
Número de incorporações
6
Ações
Compartilhamentos
0
Downloads
126
Comentários
0
Gostaram
6
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Java EE 6 JPA 2.0, EJB 3.1 e CDI 1.0

  1. 1. Java EE 6 Elvis Henrique Rocha Especialista JBoss elvis.rocha@tecnisys.com.br
  2. 2. JavaEE 6 Tópicos: • JavaEE 6 Overview • Java Persistence 2.0 • Enterprise JavaBeans 3.1 • Contexts and Dependency Injection for Java 1.0
  3. 3. JavaEE 6 Overview
  4. 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)
  5. 5. Container Architecture
  6. 6. Tiers
  7. 7. Profiles
  8. 8. Java Persistence API 2.0
  9. 9. • Arquitetura do Hibernate:
  10. 10. 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
  11. 11. 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; ... }
  12. 12. 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
  13. 13. 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
  14. 14. 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
  15. 15. 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(); ...
  16. 16. • 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
  17. 17. 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>
  18. 18. 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
  19. 19. 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( )
  20. 20. 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.
  21. 21. Relacionamento de entidades: @Embedded @OneToOne @OneToOne Bidirecional @OneToMany @OneToMany Bidirecional @ManyToMany
  22. 22. @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
  23. 23. @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)
  24. 24. @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)
  25. 25. @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
  26. 26. @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
  27. 27. 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.
  28. 28. Table per Class (SINGLE_TABLE): ✔Melhor performance ✔Melhor representação de polimorfismo ✘Não normalizado ✘Requer uma coluna para especificar o tipo de classe
  29. 29. 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
  30. 30. 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
  31. 31. 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{ . . }
  32. 32. Table per Concrete Class: @Entity @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public class BillingDetails implements Serializable, Comparable { . . . } @Entity public class CreditCard extends BillingDetails{ . . }
  33. 33. 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
  34. 34. 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>(); ... }
  35. 35. Entity Manager e ciclo de vida das entidades:
  36. 36. Entity Manager e ciclo de vida das entidades:
  37. 37. 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( )
  38. 38. 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( )
  39. 39. Caso de uso: Detachar / Reatachar Entitidades
  40. 40. Caso de uso: Modo Extendido
  41. 41. 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)
  42. 42. 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); } }
  43. 43. Cache
  44. 44. 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
  45. 45. 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
  46. 46. 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
  47. 47. 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)
  48. 48. 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
  49. 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) 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
  50. 50. 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();
  51. 51. 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
  52. 52. Enterprise JavaBeans 3.1
  53. 53. 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
  54. 54. 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
  55. 55. 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
  56. 56. 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; } }
  57. 57. 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
  58. 58. 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) { // . . . } }
  59. 59. 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
  60. 60. Singleton Session Beans @Startup @Singleton public class MySingleton { public void delivery() { // . . . } }
  61. 61. 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
  62. 62. 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) { // . . . } } }
  63. 63. 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
  64. 64. 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); } }
  65. 65. 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
  66. 66. 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) ); } }
  67. 67. EJB.Lite Um EJB Lite é um componente de negócio com recursos limitados para execução no Web Profile JavaEE
  68. 68. 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
  69. 69. 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
  70. 70. Contexts and Dependency Injection
  71. 71. 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
  72. 72. 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; } }
  73. 73. 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; } }
  74. 74. 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 }
  75. 75. 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
  76. 76. 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 { ... }
  77. 77. 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
  78. 78. 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(); }
  79. 79. 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(); } }
  80. 80. 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>
  81. 81. 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"; } }
  82. 82. 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.
  83. 83. 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.
  84. 84. 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. } }
  85. 85. Obrigado!

×