Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Enterprise Web App. Development (5): JPA + JTA with CDI Training

Enterprise Web App. Development (5): JPA + JTA with CDI Training

This is the fifth course of a series of courses for Enterprise Web Application development based on several Open Source products. As we finished JSF with CDI course, we are going to move on to “JPA + JTA with CDI” as the second course of Jakarta EE framework specification. Later we are taking care of “JAX-RS” and “Jakarta Batch” as minimum skills to develop Enterprise Web Application. In those courses, we refer to some “Application Architecture Design Patterns”. Therefore this series require the basic skills of Windows 10, CentOS, Eclipse IDE, Java SE (Oracle JDK or OpenJDK), Payara Server and PostgreSQL. Regarding the Payara Server, we can use another Web Application Server conforming to Jakarta EE specification. As for PostgreSQL, we might be able to use another RDBMS product instead. We can also make use of another Linux distribution instead of CentOS.

E7d0d73badb1cc1df2bc44f58d51aaff?s=128

Koichi NAKAGAWA

November 26, 2020
Tweet

Transcript

  1. JAKARTA PERSISTENCE API (JPA) &TRANSACTION API (JTA) WITH CDI A

    part of Jakarta EE specification O-R Mapper and Transaction Framework 1 By Koichi NAKAGAWA
  2. JPA + JTA with CDI Jakarta Persistence API (JPA) and

    Jakarta Transaction API (JTA) with CDI 2
  3. EWA development course curriculum Object Oriented Development Methodology JSF with

    CDI JPA + JTA with CDI JAX-RS Application Architecture Design Patterns Eclipse IDE™ Version Control Tool with Git™ Build Tool with Apache Maven™ Payara Server™ Administration Windows 10™ + Linux (CentOS™) Total EWA Development Exercise Jakarta Batch Java SE (Oracle JDK™/OpenJDK™) Required Skills to take courses Test Tool with JUnit5 PostgreSQL™ Administration 3
  4. Trademarks Notice • Jakarta™ EE and its logo( ) are

    trademarks of the Eclipse Foundation. • PostgreSQL™ and its logo( ) are registered trademarks of the PostgreSQL Community Association of Canada. • Apache Derby™ and its logo ( ) are trademarks of the Apache Software Foundation. • Payara™ Server and their logo( ) are trademarks of Payara Services® LTD. • EclipseLink™, EclipseLink™ logo ( ), Eclipse IDE for Enterprise Java Developer™, the Eclipse IDE for Enterprise Java Developer ™ logo( ), Eclipse M2Eclipse™, M2Eclipse™, Eclipse GitTeam Provider™, Eclipse EGit™, EGit™, Eclipse Java development tools™, Java development tools™, Eclipse JDT™, JDT™ are trademarks of the Eclipse Foundation. • Apache Maven™, Maven™ are trademarks of the Apache Software Foundation (ASF). • Git™ and the Git™ logo( ) are either registered trademarks or trademarks of Software Freedom Conservancy, Inc., corporate home of the Git Project, in the United States and/or other countries. • Java™ is trademark of Oracle Corporation. 4
  5. Assumption for this course • The trainees who take this

    course are required the following skills in advance • PostgreSQL (Version: 12.0) – Basic Administration Operations • Payara Server (Version: 5.2020.5) – Basic Administration Operations • Oracle JDK/OpenJDK (Version: 8) • Eclipse IDE for Enterprise Java Developers (Version: 2020-09 (4.17.0)) • Build Tool Training Course • Version Control Tool Training Course • Test Tool Training Course • JSF with CDI Training Course 5
  6. Objectives This course is aimed to obtain the following skills

    • Jakarta Persistence API (JPA) and Jakarta Transaction API (JTA) technology • Jakarta Context Dependency Injection (CDI) technology as components in business layer • Development persistence interface applications using JPA and JTA with CDI 6
  7. JPA + JTA with CDI • Design Patterns in Business

    Layer and Jakarta Persistence API (JPA) • Database Transaction Basics and Jakarta Transaction API (JTA) • Locking Mechanism and Isolation Control and Jakarta Persistence API (JPA) • Design Patterns in Data Access Layer and Jakarta Persistence API (JPA) as O-R Mapper • DB Exception Handling • First JPA DB Application • JPA Entity Relationship Programming • JPA & JTA for CDI Programming • JPA in Jakarta EE Container Programming 7
  8. Design Patterns in Business Layer and Jakarta Persistence API (JPA)

    8
  9. Design Patterns in Business Layer • Analysis Models 9 Retail

    Sale - name - address - tel. Order - number - date - status OrderItem - count - status 1 * 1 * Ship - count - shipping date - status 1 * Vendor Product HealthCare Product Food Product *
  10. Design Patterns in Business Layer • 2 Types of Design

    Patterns in Business Layer 10 Business Layer Design Patterns Transaction Script Pattern Domain Model Pattern (*) Both patterns of Domain Model and Transaction Script are parts of PofEAA Patterns.
  11. Design Patterns in Business Layer • Transaction Script 11 Data

    Access DAO Business Business Class Name: Vendor: ABC XYZ Update Update Results: Presentation DTO DTO DTO DTO DTO DTO RDB Name ABC Vendor XYZ
  12. Design Patterns in Business Layer • Domain Model 12 Data

    Access O-R Mapper Business Domain Service Presentation Entity/VO Entity/VO RDB Entity/VO Entity/VO Name: Vendor: ABC XYZ Update Update Results: Name ABC Vendor XYZ DTO DTO
  13. Design Patterns in Business Layer • Adopt Domain Driven Design

    (DDD) Architecture to Domain Model 13 Data Access O-R Mapper Business Infrastructure Presentation Entity/VO Entity/VO RDB Entity/VO Entity/VO Name: Vendor: ABC XYZ Update Update Results: Name ABC Vendor XYZ DTO DTO Domain Use Case (Application) Entity/VO Entity/VO Entity/VO Entity/VO
  14. Data Access JPA Engine (O-R Mapper) Persistence Context Jakarta Persistence

    API (JPA) • Entity Manager and Persistence Context 14 Business Domain Service / Infrastructure Entity/VO Entity/VO RDB Entity/VO Entity/VO Entity Manager
  15. Jakarta Persistence API (JPA) • Entity Instance Life Cycle 15

    Entity State Machine of Entity Instance NEW MANAGED DETACHED REMOVED Product product = new Product() EntityManager#find( Product.class, Primary_Key) EntityManager#persist(product) EntityManager#merge(product) EntityManager#detach(product) EntityManager#clear() EntityManager#persist(product) EntityManager#remove(product)
  16. Database Transaction Basics and Jakarta Transaction API (JTA) 16

  17. Database Transaction • 2 Transaction Types 17 Short Transaction (Default)

    • Ex. 1-Click Transaction Long Transaction • Ex. Menu Transition Name: Vendor: ABC XYZ Ltd. Create RDB RDB Name: Vendor: ABC XYZ Ltd. Update Write 1. Read Name: Vendor: A123 AAA Ltd. Save 3. Write 2. After a few minutes
  18. Database Transaction • ACID Properties in DBMS for Short Transaction

    (1) 18 Atomicity • A transaction finishes all the processes inside as completed or rollbacked Consistency • No logical contradiction happens by specifying “Constrains” for RDBMS Order Inventory Transaction Rollback Order Order Detail Consistent
  19. Database Transaction • ACID Properties in DBMS for Short Transaction

    (2) 19 Isolation • Even if multiple transactions for the same entity are executed in parallel, each transaction is not affected each other and processed in serial Durability • Once Data is written into RDBMS, even if it goes down, the Data is never lost Transaction #1 Transaction #2 Each transaction is processed in serial. Order Transaction System Fail! Can be recovered from backups or replications Entity
  20. Java Transaction • 2 Java Transaction Types 20 Java Transaction

    Types JDBC Transaction (with Java SE) JTA Transaction (with Jakarta EE) JTA Transaction Type: RESOURCE_LOCAL Application manages: JTA Transaction Type: JTA Jakarta EE Container manages: -Transactions (Using EntityTransaction obtained from EntityManager) - Persistence Context life cycles (Calling EntityManager#close()/clear()) - Only a Single Persistent Unit in a transaction -Transactions (Transaction behaviors can be declared in CDI or EJB) - Persistence Context life cycles (Application does not need to care) - Multiple Persistent Units or Systems (like JMS, JCA, etc.) in a transaction
  21. Java Transaction • JTA Transaction [Managed by Application ] 21

    Jakarta EE Container Non-Transactional CDI @Dependent public class orderServiceCDI { @PersistenceContext(…) private EntityManager em; : public void doBusiness(..) { EntityTransaction tx = em.getTransaction(); tx.begin(); try { EntityA entityA = new EntityA(…); em.persist(entityA); : } catch (Exception e) { tx.rollback(); } tx.commit(); } Begin! Commit! RDB SQL #1 SQL #2 ・ ・ ・ Rollback!
  22. Java Transaction • JTA Transaction [Managed by Jakarta EE Container]

    22 Jakarta EE Container Transactional CDI @ApplicationScoped @Transactional public class orderServiceCDI { @PersistenceContext(…) private EntityManager em; : public void doBusiness(..) { EntityA entityA = new EntityA(…); em.persist(entityA); : } Begin! Commit! RDB SQL #1 SQL #2 ・ ・ ・ Rollback! Declare Transactional CDI XXXXX Done by Jakarta EE Container
  23. Java Transaction • Typical 2 JTA Transaction Attributes [@Transactional(TxType.REQUIRED or

    TxType.REQUIRED_NEW)] 23 Transaction Attribute Caller has not begun Tx yet Caller has already begun Tx TxType.REQUIRED (Default) TxType.REQUIRES_NEW Begin Tx2 Commit Tx2 Begin Tx1 Commit Tx1 Begin Tx2 Commit Tx2 Begin Tx1 Commit Tx1 Begin Tx2 Commit Tx2 Pause Tx1 Resume Tx1 Caller Target Method Caller Target Method Caller Target Method Caller Target Method
  24. Transaction and Database Connection • Connection Pool for Performance Improvement

    • Data Source for Mappings between Transactions and Physical Connections 24 Jakarta EE Container Connection Pool ・ ・ ・ RDB Data Source Jakarta EE Container Connection Pool ・ ・ ・ RDB Data Source 2. PhysicalConnection is kept for a next logical connection Logical Connection (Light Weight) Physical Connection (Heavy Weight) 1. Logical Connection is closed Application Application Manage Mapping Information between Transactions and Physical Connections. (1 Transaction uses 1 Physical Connection)
  25. Locking Mechanism and Isolation Control and Jakarta Persistence API (JPA)

    25
  26. Locking Mechanism and Isolation Control • 2 types of Locking

    Method and 4 types of Isolation Level 26 Pessimistic Lock • Lock by RDB’s Lock Mechanism (Pessimistic Offline Lock Pattern defined in PofEAA) Optimistic Lock • Lock by Application Logic (Optimistic Offline Lock Pattern defined in PofEAA) Locking Methods • Prevent inconsistency while updating an entity by multiple transactions simultaneously Isolation Level • Prevent illegal transaction interactions SERIALIZABLE REPEATABLE_READ READ_COMMITTED READ_UNCOMMITTED
  27. Locking Mechanism • Lock Method [Pessimistic Lock] 27 Transaction A

    Transaction B Bank Account SELECT FOR UPDATE Balance = 10,000 Balance = Balance + 5,000 UPDATE + COMMIT SELECT FOR UPDATE Wait … Balance = 18,000 Balance = Balance + 3,000 UPDATE + COMMIT Balance = 10,000 SUCCESSFULLY DONE SUCCESSFULLY DONE Balance = 15,000
  28. Locking Mechanism • Lock Method [Optimistic Lock] 28 Transaction A

    Transaction B Bank Account SELECT Balance = 10,000 Balance = Balance + 5,000 UPDATE + COMMIT SELECT Balance = 15,000 Balance = Balance + 3,000 UPDATE + COMMIT Balance = 10,000 Balance = 10,000 SUCCESSFULLY DONE FAILURE
  29. Locking Mechanism • Comparison between Lock Methods 29 Lock Type

    Pessimistic Lock Optimistic Lock When to select? There are a lot of cases where the same “Entity(a row)” is updated by many transactions at the same time. Otherwise. Especially for Long Transaction. Dead Lock Possible (Prevent by locking Root Entity or Shared Entity first) Not possible Transaction A Transaction B Entity X Entity Y SELECT FOR UPDATE SELECT FOR UPDATE Wait … Wait … SELECT FOR UPDATE SELECT FOR UPDATE Dead Lock
  30. How to set Lock Methods • JPA Programming for Pessimistic

    Lock 30 Product product = entityManager.find(Product.class, 123, LockModeType.PESSIMISTIC_WRITE); entityManager.flush(); • JPA Programming for Optimistic Lock @Entity public class Product { : @Version private long version; : }
  31. Long Transaction and Optimistic Lock • Demo – Long Transaction

    and Optimistic Lock 31 Order OrderItem 1 * User A User B 2. App: READ 5. App: READ 8. App: WRITE 10. App: WRITE Fail !!! 1. User A: Select an Entity and Click UPDATE 4. User B: Select the same Entity and Click UPDATE 7. User A: Click UPDATE 9. User B: Click UPDATE 3. App: SHOW 6. App: SHOW
  32. Short Transaction and Optimistic Lock • Demo – Short Transaction

    and Optimistic Lock 32 Order User A User B 2. App: INCREMENT 4. App: INCREMENT Fail !!! 1. User A: Select an Entity and Click 3. User B: Select the same Entity and Click in the middle of Step 2
  33. Short Transaction and Pessimistic Lock • Demo – Short Transaction

    and Pessimistic Lock 33 Order User A User B 2. App: INCREMENT 4. App: INCREMENT (Start AFTER Step 2) 1. User A: Select an Entity and Click 3. User A: Select the same Entity and Click in the middle of Step 2 Done
  34. Isolation Control • 3 Illegal Transaction Interactions [ANSI/ISO SQL Standard

    SQL92] 34 Dirty Read • A transaction can read uncommitted data changed by another transaction Non-repeatable Read • A transaction rereads data committed by another transaction and sees the new data Phantom Read • When a query again in a transaction, it can discover new rows inserted or lost existed rows deleted by another transaction
  35. Isolation Control • Transaction Interaction [Dirty Read] 35 Transaction A

    Transaction B Bank Account SELECT Balance = 10,000 Balance = Balance + 5,000 UPDATE SELECT Balance = 10,000 Balance = Balance + 3,000 UPDATE + COMMIT Balance = 15,000 SUCCESSFULLY DONE COMMIT SUCCESSFULLY DONE SUCCESSFULLY DONE Read Before Committed! Balance = 15,000
  36. Isolation Control • Transaction Interaction [Non-repeatable Read] 36 Transaction A

    Transaction B Bank Account SELECT Balance = 10,000 Balance = Balance + 5,000 UPDATE + COMMIT SELECT Balance = 10,000 Balance = Balance + 3,000 UPDATE + COMMIT Balance = 10,000 SUCCESSFULLY DONE SUCCESSFULLY DONE Read Before Committed! SELECT Balance = 15,000 Different data are read in 1 transaction Balance = 18,000
  37. Isolation Control • Transaction Interaction [Phantom Read] 37 Transaction A

    Transaction B Bank Account INSERT ‘A123’ INTO ACCOUNT + COMMIT SELECT * FROM ACCOUNT Account ‘A123’ does NOT EXIST SUCCESSFULLY DONE Read Before Committed! Different data are read in 1 transaction SELECT * FROM ACCOUNT Account ‘A123’ does EXIST (*) The same thing happens for DELETE operation
  38. Isolation Control • Comparison among Isolation Levels 38 Isolation Level

    Dirty Read Non-repeatable Read Phantom Read READ_UNCOMMITTED Possible Possible Possible READ_COMMITTED Not Possible Possible Possible REPEATABLE_READ Not Possible Not Possible Possible SERIALIZABLE Not Possible Not Possible Not Possible Very High High Slow Very Slow Performance (*) Possible cases must be taken care of by applications
  39. How to set Isolation Level • Isolation Level Configuration for

    Jakarta EE (In case of Payara Server) 39
  40. Design Patterns in Data Access Layer and Jakarta Persistence API

    (JPA) as O-R Mapper 40
  41. Modeling Domains in Data Access Layer • Logical Object Model

    and Physical ER Model 41 Vendor Product Impedance Mismatching VENDOR Table PRODUCT Table HealthCare Product Food Product [Object Model] [ER Model] *
  42. Design Patterns in Data Access Layer • 2 PofEAA Design

    Patterns in Data Access Layer 42 Table Data Gateway Pattern • DAO based pattern • OSS Framework: MyBatis Data Mapper Pattern • O-R Mapper based pattern • Jakarta EE Framework: JPA Design Patterns for Data Access Layer
  43. Data Mapper Design Pattern • Example of Data Mapper Design

    Pattern 43 PRODUCT Table ID VER TYPE NAME 1 1 HEALTH Pedometer X1 2 1 FOOD Healthy Drink A 3 2 HEALTH Weight Scale W278 Health Product Pedometer X1 Weight Scale W278 Food Product Healthy Drink A Product O-R Mapper Product HealthCare Product Food Product
  44. O-R Mapper Architecture • JPA – Jakarta Persistence API 44

    Jakarta EE Container / Java SE JPA Engine Configuration File (persistence.xml) Persistent Context Entity A Entity B Entity C Entity Manager RDB Application CDI EJB
  45. O-R Mapper Configuration • JPA Configuration File 45 Configuration File

    (persistence.xml) <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="defaultUnit" transaction-type="JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/DemoDS</jta-data-source> <properties> <property name="eclipselink.logging.level" value="INFO" /> <property name="eclipselink.ddl-generation" value="create-tables"/> <property name="eclipselink.target-database" value="PostgreSQL"/> </properties> </persistence-unit> </persistence> JPA Configuration for Jakarta EE <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="defaultUnit" transaction-type=“RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>org.example.project.domain.Department</class> <class>org.example.project.domain.Employee</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/dbname" /> <property name="javax.persistence.jdbc.user" value=“user" /> <property name="javax.persistence.jdbc.password" value="password" /> <property name="eclipselink.logging.level" value="INFO" /> <property name="eclipselink.ddl-generation" value="create-tables"/> <property name="eclipselink.target-database" value="PostgreSQL"/> </properties> </persistence-unit> </persistence> JPA Configuration for Java SE Transaction Type must be “RESOURCE_LOCAL” and Provider, Entity Classes and DB Connection information should be specified. Provider and Data Source should be specified instead.
  46. How to obtain EntityManager in CDI? • 2 ways to

    obtain EntityManager 46 @Dependent public class XXX_Service { : @PersistenceUnit(unitName=“defaultUnit”) private EntityManagerFactory emf; private EntityManager entityManager; : @PostConstruct public void prepare() { entityManager = emf.createEntityManager(); } @PreDestroy public void after(){ entityManager.close(); } public method() { : entityManager.createQuery(“SELECT …”); : } } JTA Transaction Type: RESOURCE_LOCAL (Transaction: Managed by Application) JTA Transaction Type: JTA (Transaction: Managed by Jakarta EE Container) @Dependent @Transactional public class XXX_Service { : @PersistenceContext(unitName=“defaultUnit”) private EntityManager entityManager ; : public method() { : entityManager.createQuery(“SELECT …”); : } } Non-Transactional CDI Transactional CDI Factory Injection Manager Injection Create Close
  47. State Machine of JPA Entity Instance • JPA State Transitions

    of Entity Instance 47 Persistent Context Entity A Entity B Entity C NEW State product = New Product() MANAGED State product = EntityManager.find (Product.class, keyId) DETACHED State EntityManager.persist(product) EntityManager.detach(product) EntityManager.clear() product = EntityManager.merge(product) REMOVED State EntityManager.remove(product) EntityManager.persist(product)
  48. JPA Annotations • 2 Ways to define JPA Annotations for

    Entity Properties (Columns) 48 Persistent Context Entity A Entity B Entity C @Entity public class Product { : @Id private int id; : } @Entity @Table (name=“PRODUCT”) public class Product { : private int id; : @Id @Column(name=“ID”) public int getId() { return id; } : } Annotations for Properties Annotations for Getter Methods Table Name can be specified. Column Name can be specified.
  49. JPA Annotations • Auto numbering for Primary Key 49 AUTO

    IDENTITY SEQUENCE TABLE Strategy In each Entity Class: @Entity public class Product { : @Id  Specify for Primary Key @GeneratedValue(strategy = GenerationType.AUTO) private long id; : } (*) @Id and @GeneratedValue annotation should be specified for the primary key property or getter accessor for it. Specify Auto Numbering Strategy
  50. JPA Annotations • Pessimistic Lock and Optimistic Lock (Review) 50

    LockType How to use each Lock Type with JPA Pessimistic Lock Product product = entityManager.find (Product.class, productId, LockModeType.PRESSIMISTIC_WRITE); entityManager.flush(); This flush() function call is required to send “SELECT FOR UPDATE” to DB soon. Optimistic Lock In each Entity Class: @Entity public class Product { : @Version private long version; : } This version property or getter accessor for this property with @Version annotation is required. Usually “long” or “int” type is used for this property.  Automatically count up this version field.  Once “Update” on the same Entity by another transaction is detected, “OptimisticLockException” is thrown.
  51. JPA Annotations • Relationships (Definition) 51 Product - name -

    model - description Vendor - Name - address - tel. 1 * @Entity public class Vendor { : @OneToMany(targetEntity = Product.class, mappedBy = “vendor”) private List<Product> products; : } @Entity public class Product { : @ManyToOne(targetEntity = Vendor.class) private Vendor vendor; : } The targetEntity is not necessarily specified, as Product.class is defined using Java Generics. This targetEntity is also not necessarily specified, as Vendor.class is the default class in this case. For two-way visibility.
  52. . JPA Annotations • Relationships (Manipulation) 52 Product - name

    - model - description Vendor - name - address - tel. 1 * public void makeNewProduct (name, model, description, venderId) { : Product product = new Product(name, model, description); entityManager.persist(product); Vendor vendor = entityManager.find(Vendor.class, venderId); vendor.getProducts().add(product); product.setVendor(vendor); : } In a function of Transactional CDI Component Set both Entities for two-way visibility.
  53. JPA Annotations • Relationships (fetch option) 53 Product - name

    - model - description Vendor - Name - address - tel. 1 * @Entity public class Vendor { : @OneToMany(targetEntity = Product.class, mappedBy = “vendor”, fetch = FetchType.LAZY) private List<Product> products; : } @Entity public class Product { : @ManyToOne(targetEntity = Vendor.class, fetch = FetchType.EAGER) private Vendor vendor; : } 1. Product product = entityManager.find(Product.class, id); 2. Vendor vendor = product.getVendor(); SQL for Vendor Entity is executed at step 1. 1. Vendor vendor = entityManager.find(Vendor.class, id); 2. List<Product> products = vendor.getProducts(); SQL for Product Entity is executed at step 2. Default for each Annotation
  54. JPA Annotations • Relationships (cascade option) 54 Product - name

    - model - description Vendor - name - address - tel. 1 * @Entity public class Vendor { : @OneToMany(targetEntity = Product.class, mappedBy = “vendor”, cascade = CascadeType.ALL) private List<Product> products; : } @Entity public class Product { : @ManyToOne(targetEntity = Vendor.class) private Vendor vendor; : } 1. Vendor vendor = new Vendor(“ABC Ltd.”, “1-2-3”); 2. Product product = new Product(“AXY”, “A-123”); 3. product.setVendor(vendor); 4. vendor.getProducts().add(product); 5. entityManager.persist(vendor); After vendor is inserted, product is also inserted automatically. (No need to execute entityManager.persist(product).) Select from “ALL”, “PERSIST”, “REMOVE” and “MERGE”
  55. JPA Annotations • Relationships (orphanRemoval option) 55 @Entity public class

    Vendor { : @OneToMany(targetEntity = Product.class, mappedBy = “vendor”, orphanRemoval = true) private List<Product> products; : } @Entity public class Product { : @ManyToOne(targetEntity = Vendor.class) private Vendor vendor; : } Product Drink A Vendor ABC Ltd. 2. Drink A becomes Orphan 3. Remove Drink A automatically 1. Remove a relationship with Drink A vendor.getProducts().remove(product);
  56. JPA Annotations • Relationships (Inheritance : 3 Strategies) 56 Product

    HealthCare Product Food Product Single Table Inheritance Product Type Common Fields Healthcare Product Specific Fields Food Product Specific Fields Joined Multiple Table Inheritance ProductType Common Fields Healthcare Product Specific Fields Food Product Specific Fields PRODUCT Table PRODUCT Table HEALTHCARE Table FOOD Table Table Per Class Inheritance All Healthcare Product Fields All Food Product Fields HEALTHCARE Table FOOD Table
  57. JPA Annotations • Relationships (Single Table Inheritance) 57 @Inheritance(strategy =

    InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = “PRODUCT_TYPE", discriminatorType = DiscriminatorType.STRING) @Entity public class Product { … } @DiscriminatorValue(value = “HEALTHCARE") @Entity public class HealthCareProduct extends Product { … } Product HealthCare Product Food Product @DiscriminatorValue(value = “FOOD") @Entity public class FoodProduct extends Product { … } Single Table Inheritance Product Type Common Fields Healthcare Product Specific Fields Food Product Specific Fields PRODUCT Table
  58. JPA Annotations • Relationships (Joined Multiple Table Inheritance) 58 @Inheritance(strategy

    = InheritanceType.JOINED) @DiscriminatorColumn(name = “PRODUCT_TYPE", discriminatorType = DiscriminatorType.STRING) @Entity public class Product { … } @DiscriminatorValue(value = “HEALTHCARE") @Entity public class HealthCareProduct extends Product { … } Product HealthCare Product Food Product @DiscriminatorValue(value = “FOOD") @Entity public class FoodProduct extends Product { … } Class Table Inheritance PRODUCT Table Product Type Common Fields Healthcare Product Specific Fields Food Product Specific Fields HEALTHCARE Table FOOD Table
  59. JPA Annotations • Relationships (Table Per Class Inheritance) 59 @Inheritance(strategy

    = InheritanceType.TABLE_PER_CLASS) @Entity public class Product { … } @Entity public class HealthCareProduct extends Product { … } Product HealthCare Product Food Product @Entity public class FoodProduct extends Product { … } Concrete Table Inheritance All Healthcare Product Fields All Food Product Fields HEALTHCARE Table FOOD Table
  60. JPA Annotations • Relationships (Embeddable Class and Embedded Properties for

    Value Object) 60 Vendor Address ID NAME ZIP_CODE CITY STREET VENDOR Table Embedded Columns Embeddable Class @Embeddable public class Address { … String zipCode; String city; String street; …} @Entity public class Vendor { : @Embedded @AttributeOverrides({ @AttributeOverride(name = “zipCode", column = @Column(name = “ZIP_CODE") ), @AttributeOverride(name = “city", column = @Column(name = “CITY") ), @AttributeOverride(name = “street", column = @Column(name = “STREET") }) private Address address; : } - zipCode - city - street Optional
  61. JPA Annotations • Relationships (Element Collection with Embeddable Class for

    Collection of Value Objects) 61 Vendor Address ID NAME A1 ABC VENDOR Table Element Collection Embeddable Class @Embeddable public class Address { … @Column(name=“ZIP_CODE") String zipCode; String city; String street; …} @Entity public class Vendor { : @ElementCollection @CollectionTable( name=“ADDRESS", joinColumns=@JoinColumn(name=“COMP_ID")) private List<Address> addresses; : } - zipCode - city - street * Collection COMP_ID ZIP_CODE CITY STREET A1 111-1111 Tokyo 1-1-1 A1 222-2222 Osaka 2-2-2 A1 333-3333 Nagoya 3-3-3 A1 444-4444 Sapporo 4-4-4 ADDRESS Table Optional Optional
  62. JPA DB Manipulation Language • 2 Ways to manipulate DB

    with JPA 62 JPQL (Jakarta Persistence Query Language) • Similar to SQL, so it’s very Easy to Use. Criteria API • Typesafe API, so it’s very Safe to Use.
  63. JPA DB Manipulation Language • JPQL(Jakarta Persistence Query Language) 63

    Product Query query = entityManager.createQuery( “SELECT p FROM Product p “ + “WHERE p.price <= :maxPrice”) .setParameter(“maxPrice”, 10000); List<Product> resultList = query.getResultList(); - int id - String name - String number - int price - String category Query JPQL • Database product independent Query Language  High Portability • Execute complex queries • Execute batch CRUD operations • Possible to execute Database product-native SQLs  But… Low Portability
  64. JPA DB Manipulation Language • JPQL – Aggregate Function &

    Grouping 64 Query query = entityManager.createQuery(“SELECT COUNT(p) FROM Product p”); Long result = (Long)query.getSingleResult(); • Support Grouping with GROUP BY, HAVING Query query = entityManager.createQuery(“SELECT p.category, COUNT(p) “ + “FROM Product p GROUP BY p.category HAVING COUNT(p) > 5”); List resultList = query.getResultList(); Map<String, Long> resultMap = new HashMap<String, Long>(); for (Object[] result: resultList) resultMap.put((String)result[0]), (Long)result[1]); • Supported Aggregate Functions: COUNT, SUM, AVG, MAX, MIN
  65. JPA DB Manipulation Language • JPQL – Sorting & Eliminating

    Duplications 65 Query query = entityManager.createQuery(“SELECT p FROM Product p “ + “ORDER BY p.category, p.price DESC”); List<Product> resultList = query.getResultList(); • Support sorting with ORDER BY • Eliminate duplications with DISTINCT Query query = entityManager.createQuery(“SELECT DISTINCT p.category “ + “FROM Product p”); List resultList<String> = query.getResultList();
  66. JPA DB Manipulation Language • JPQL – Paging for query

    results 66 Query query = entityManager.createQuery(“SELECT p FROM Product p ORDER BY p.price DESC”) .setFirstResult(300) .setMaxResults(100); List<Product> resultList = query.getResultList(); • Support paging
  67. Category Operators/Expressions/Functions Navigation operator . Arithmetic operators +, - (unary

    plus and minus) *, / (multiplication and division) +, - (addition and subtraction) Comparison operators =, >, >=, <, <=, <> (not equal), [NOT] BETWEEN, [NOT] LIKE, [NOT] IN, IS [NOT] NULL, IS [NOT] EMPTY, [NOT] MEMBER [OF] Logical operators NOT AND OR Expressions [NOT] EXISTS (subquery), ALL | ANY | SOME (subquery) String Functions CONCAT(string_primar y, string_primary) | SUBSTRING(string_primar y, simple_arithmetic_expression, simple_arithmetic_expression) | TRIM([[trim_specification] [trim_character] FROM] string_primary) | LOWER(string_primar y) | UPPER(string_primar y) | LENGTH(string_primar y) | LOCATE(string_primar y, string_primar y[, simple_arithmetic_expression]) Arithmetic Functions ABS(simple_arithmetic_expression) | SQRT(simple_arithmetic_expression) | MOD(simple_arithmetic_expression, simple_arithmetic_expression) | SIZE(collection_valued_path_expression) Datetime Functions CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP JPA DB Manipulation Language • JPQL – Other Operators/Expressions/Functions 67
  68. JPA DB Manipulation Language • JPQL – Relationship with JOIN

    • Inner Join with [INNER] JOIN Query query = entityManager.createQuery(“SELECT v. name, p.name, “ + “FROM Vendor v INNER JOIN v.products p WHERE p.id = :productId”).setParameter(“productId”, 567); • Outer Join with LEFT [OUTER] JOIN Query query = entityManager.createQuery(“SELECT v. name, p.name, “ + “FROM Vendor v LEFT OUTER JOIN v.products p WHERE p.id = :productId”).setParameter(“productId”, 567); • Fetch Join with [LEFT [OUTER] | INNER] JOIN FETCH Query query = entityManager.createQuery(“SELECT v, “ + “FROM Vendor v JOIN FETCH v.products WHERE v.id = :vendorId”).setParameter(“vendorId”, 123); 68
  69. JPA DB Manipulation Language • JPQL – LAZY (N+1 SELECT

    Problem) 69 Product - name - model - description Vendor - name - address - tel. 1 * Query query = entityManager.createQuery(“SELECT v FROM Vendor AS v”); List<Vendor> vendors = query.gerResultList(); for (Vendor vendor: vendors) { List<Product> products = vendor.getProducts();  Execute SQL N times for (Product product: products) { String name = product.getName(); : } } Query query = entityManager.createQuery(“SELECT v FROM Vendor AS v JOIN FETCH v.products”); LAZY fetch Change to use JOIN FECH
  70. JPA DB Manipulation Language • JPQL – Batch Delete and

    Update operations 70 • Batch Deletion with DELETE Query query = entityManager.createQuery(“DELETE FROM Product p WHERE p.price < :price“) .setParameter(“price”, 10000); int hitCount = query.executeUpdate(); • Batch Update with UPDATE Query query = entityManager.createQuery(“UPDATE Product p SET p.price = p.price + :increment “ + “WHERE p.price > :price”).setParameter(“increment”, 100).setParameter(“price”, 10000); int hitCount = query.executeUpdate();
  71. JPA DB Manipulation Language • JPQL – Native Query 71

    Query query = entityManager.createNativeQuery(“SELECT v.id AS V_ID, v.name AS V_NAME, “ + “p.name AS P_NAME FROM Product p, Vendor v WHERE p.price < :price“, DTOResult.class ) .setParameter(“price”, 10000); List<DTOResult> resultList = query.getResultList(); @Entity Public class DTOResult { @Id @Column(name = “V_ID”) private Integer resultId; @Column(name = “V_NAME”) private String resultVName; @Column(name = “P_NAME”) private String resultPName; : }
  72. DB Exception Handling 72

  73. DB Exception Handling • Sequence Model for Exception Handling 73

    Browser Web Application Server Jakarta EE Container RDBMS HTTP Request Fail! SQL Exception HTTP Response Rollback or CommitTx Jakarta EE Container Exception Jakarta EE Container Begin Tx Transaction Boundary Exception Business (Tx CDI) Presentation (Named CDI)
  74. Exception Handling in Transaction • Error Types in Transaction and

    how Jakarta EE Container handles them 74 Expected Error Unexpected Error Unexpected Business Error System Error Infrastructure Error IOException, SQLException, … (Checked Exception) NullPointerException, … (Unchecked Exception) -> Rollback causing Unchecked Exception -> Commit causing Checked Exception in general, otherwise Rollback causing Unchecked Exception Business Rule Error, OptimisticLockException (Unchecked Exception), … Exceptions in data inconsistency, …
  75. DB Exception Handling • EJB Exceptions 75 Thrown Exception Class

    Process Class Type @ApplicationException Rollback attribute *2 Exception which caller receives Transaction MyException1 Checked Don’t Use - MyException1 Commit MyException2 Unchecked Don’t Use - *1 Rollback MyException3 Checked Use False (CDI default) MyException3 Commit MyException4 Checked Use True MyException4 Rollback MyException5 Unchecked Use False MyException5 Commit MyException6 Unchecked Use True (CDI default) MyException6 Rollback *1 MyException2 is wrapped with either javax.ejb.EJBException, java.rmi.RemoteException, javax.ejb.TransactionRolledbackLocalException or javax.transaction.TransactionRolledbackException. *2 For CDI Component, there are “rollbackOn” and “dontRollbackOn” attribute for @Transational to assign specified Exception Classes as rollback class or not rollback class. As default behavior, commit while finishing the method normally or happening checked exceptions, otherwise rollback in case of runtime exception happens.
  76. First JPA DB Application Exercise 76

  77. Example of First JPA DB Application Exercise • Domain Class

    Model “Department” Entity has a relationship with “Employee” Entity (One-to-Many). 77 Employee - name Department - name * 1 Exercise: Let’s make the First JPA DB Application on Java SE for this Domain Model.
  78. Example of First JPA DB Application Exercise • Process Flows

    1. Have Eclipselink JPA product create a “simpleDb” Database with Apache Derby™ DBMS and “EMPLOYEE” and “DEPARTMENT” Tables in the DB, which are associated with “Employee” and “Department” Entities respectively. 2. Create a “Department” Entity Instance and 2 “Employee” Entity Instances. 78 Employee name: Jakab Gipsz Department name: java name: Captain Nemo ID NAME DEPARTMENT_ID 2 Jakab Gipsz 1 3 Captain Nemo 1 ID NAME 1 java DEPARTMENTTable EMPLOYEETable simpleDb Database DBMS Eclipselink JPA Product(R.I.) Entity Instance Relationships
  79. First JPA DB Application Development Exercise • Development Procedure on

    Eclipse™ 1. Switch Eclipse Workspace to “ws3”, if current Workspace is not “ws3”. 2. Create a project named “jpaproject” using the Archetype (Group Id: com.github.lalyos, Artifact Id: standalone-jpa-eclipselink-archetype, Version: 0.0.2). As for “Group Id” and “Version”, accept as it is. 3. Modify “pom.xml” to add properties of “project.build.sourceEncoding”, “maven.compiler.source” and “maven.compiler.target” setting “UTF-8”, “1.8” and “1.8” respectively, and update the Maven project. 4. Change the Version of “Java” Project Facet to “1.8” by selecting “Project Facets” on Properties of the project. 5. Build the “jpaproject” project and execute “JpaTest” main class as “Java Application”, and confirm it has done successfully. Moreover, check the source files to understand how Entities are defined and manipulated. 79 <To execute Derby prompt connecting “simpleDb” Database (Proceed from step 1 to 3 below for the first time only)> 1. Right click on the project “jpaproject” and execute “Run As”  “Run Configurations…” menu and select “Java Application”. 2. Press “New launch configuration” button and set the name to “derby tool” and confirm “jpaproject” is selected and select “org.apache.derby.tools.ij” as “Main Class”. 3. Select “Arguments” tab and enter “-p ij.properties” in the “Program Arguments” field and click “Run” button. 4. Type “set SCHEMA JPAPROJECT;” on “ij>” prompt. Then you can use any SQL commands on the prompt. 5. When you finish, type “disconnect;” command without fail.
  80. First JPA DB Application Development Exercise • Project Explorer New

    Derby Database Folder created automatically Provided Department Entity Class Provided Employee Entity Class Modify 80 Provided Main Class Provided JPA Configuration File
  81. JPA Entity Relationship Programming Exercise 81

  82. JPA Relationship Programming Exercise • Relationships (cascade option) 82 Employee

    - name Department - name 1 * @Entity public class Department { : @OneToMany(mappedBy = “department”,cascade = PERSIST) private List<Employee> employees = new ArrayList<Employee>(); : } @Entity public class Employee { : @ManyToOne private Department department; : } department = new Department("java"); manager.persist(department); manager.persist(new Employee("Jakab Gipsz",department)); manager.persist(new Employee("Captain Nemo",department)); PERSIST cascade is defined, but not used
  83. JPA Relationship Programming Exercise • Relationships (cascade option) 83 @Entity

    public class Department { : @OneToMany(mappedBy = “department”,cascade = PERSIST) private List<Employee> employees = new ArrayList<Employee>(); : } @Entity public class Employee { : @ManyToOne private Department department; : } department = new Department("java"); manager.persist(department); manager.persist(new Employee("Jakab Gipsz",department)); manager.persist(new Employee("Captain Nemo",department)); How to make use of “PERSIST” cascade option? Exercise: Let’s modify the previous JPA DB Application to make use of “PERSIST” cascade option.
  84. JPA Relationship Programming Exercise • Development Procedure on Eclipse™ 1.

    Switch Eclipse Workspace to “ws3”, if current Workspace is not “ws3”. 2. Modify “JpaTest.java” of the “jpaproject” project to make use of “PERSIST” cascade option for “Employee” Entity Class. 3. Build the “jpaproject” project. 4. Remove the “simpleDb” Derby Database folder and execute “JpaTest” main class as “Java Application”, and confirm it has done successfully. 84 <Successful Output> num of employess:2 next employee: Employee [id=3, name=Captain Nemo, department=java] next employee: Employee [id=2, name=Jakab Gipsz, department=java] .. done
  85. JPA Relationship Programming Exercise • Project Explorer Delete Derby Database

    Folder before test 85 Modify Main Class
  86. JPA & JTA for CDI Programming Exercise 86

  87. Presentation Named CDI Business Domain Service Transactional CDI JPA &

    JTA for CDI Unit Test Exercise • Domain Model 87 Data Access O-R Mapper Entity Entity RDB Entity Entity Name: Vendor: ABC XYZ Update Update Results: Name ABC Vendor XYZ Entity Entity CDI Unit Test Java SE
  88. JPA & JTA for CDI Unit Test Exercise • Check

    if the “manageEmployees()” method of a new “EnterpriseService” CDI class works correctly with “JUnit5” Testing Framework and “Weld-JUnit5” for testing the CDI with JUnit5. @ApplicationScoped public class EnterpriseService { public List<Employee> manageEmployees() { try { createEmployees(); } catch (Exception e) { e.printStackTrace();} List<Employee> resultList = listEmployees(); return resultList;} } EnterpriseService.java 88 Exercise: Let’s modify the previous JPA DB Application to make the above new CDI class and test it.
  89. JPA & JTA for CDI Unit Test Exercise • Procedure

    of the Exercise Edit pom.xml Create the EnterpriseService Java Class Make a JUnit Test Class for the EnterpriseService Execute JUnit from Eclipse Execute JUnit from Maven 89
  90. JPA & JTA for CDI Unit Test Exercise • Modify

    the created Maven Object Model file (pom.xml) Add the <build> tag to specify the version “maven-surefire-plugin” to “2.22.2” to support JUnit5 natively.  Add “junit-jupiter-api”, “junit-jupiter-engine” and “hamcrest” as dependency for the JUnit5 testing framework. <dependencies> : <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> <build> <pluginManagement> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> </plugins> </pluginManagement> </build> <dependency> <groupId>org.hamcrest</groupId> <artifactId>hamcrest</artifactId> <version>2.2</version> <scope>test</scope> </dependency> </dependencies> 90
  91. JPA & JTA for CDI Unit Test Exercise • Modify

    the Maven Object Model file (pom.xml) Add “weld-junit5” for JUnit CDI Test and “weld-se-core” for CDI on Java SE as dependency. <dependencies> : <dependency> <groupId>org.jboss.weld</groupId> <artifactId>weld-junit5</artifactId> <version>2.0.1.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.weld.se</groupId> <artifactId>weld-se-core</artifactId> <version>3.1.5.Final</version> </dependency> : </dependencies> 91
  92. JPA & JTA for CDI Unit Test Exercise • Modify

    the Maven Object Model file (pom.xml) Delete “eclipselink” and “javax.persistence” and add “org.eclipse.persistence.jpa” for the latest Eclipselink (JPA Product) as dependency. <dependencies> : <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>2.2.1</version> </dependency> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>javax.persistence</artifactId> <version>2.0.3</version> </dependency> : </dependencies> 92 <dependencies> : <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa</artifactId> <version>2.7.7</version> </dependency> : </dependencies>
  93. JPA & JTA for CDI Unit Test Exercise • Procedure

    of the Exercise Edit pom.xml Create the EnterpriseService Java Class Make a JUnit Test Class for the EnterpriseService Execute JUnit from Eclipse Execute JUnit from Maven 93
  94. JPA & JTA for CDI Unit Test Exercise • Create

    a new CDI Java source file (EnterpriseService.java) (1)  The CDI defines EntityManager property and its accessors package org.example.jpaproject.service; import java.util.List; import javax.enterprise.context.ApplicationScoped; import javax.persistence.EntityManager; import org.example.jpaproject.domain.Department; import org.example.jpaproject.domain.Employee; 94 @ApplicationScoped public class EnterpriseService { private EntityManager manager; public EnterpriseService() { super(); } public EntityManager getManager() { return manager; } public void setManager(EntityManager manager) { this.manager = manager; }
  95. JPA & JTA for CDI Unit Test Exercise • Create

    a new CDI Java source file (EnterpriseService.java) (2)  In the CDI class, add the “manageEmployees()” and “createEmployees()” methods based on the associated functions in “JpaTest.java”. public List<Employee> manageEmployees() { try { createEmployees(); } catch (Exception e) { e.printStackTrace();} List<Employee> resultList = listEmployees(); System.out.println(".. done"); return resultList; } 95 private void createEmployees() { int numOfEmployees = manager.createQuery("Select a From Employee a", Employee.class).getResultList().size(); Department department; if (numOfEmployees == 0) { department = new Department("java"); department.getEmployees().add(new Employee("Jakab Gipsz", department)); department.getEmployees().add(new Employee("Captain Nemo", department)); manager.persist(department);} }
  96. JPA & JTA for CDI Unit Test Exercise • Create

    a new CDI Java source file (EnterpriseService.java) (3)  In the CDI class, add the “listEmployees()” method based on the associated function in “JpaTest.java” and modify it to return Employee list as the result of JPQL Query. • Delete a class file of “JpaTest.java” and its package named “org.example.jpaproject.jpa”. 96 private List<Employee> listEmployees() { List<Employee> resultList = manager.createQuery("Select a From Employee a", Employee.class).getResultList(); System.out.println("num of employess:" + resultList.size()); for (Employee next : resultList) { System.out.println("next employee: " + next); } return resultList; } <package> • org.example.jpaproject.jpa <class> • JpaTest.java Delete
  97. JPA & JTA for CDI Unit Test Exercise • Procedure

    of the Exercise 97 Edit pom.xml Create the EnterpriseService Java Class Make a JUnit Test Class for the EnterpriseService Execute JUnit from Eclipse Execute JUnit from Maven
  98. JPA & JTA for CDI Unit Test Exercise • Create

    a Test Class folder named “src/test/java”  Right click on the project and select “Properties”.  Select “Java Build Path” from left-hand menu of the Properties dialog.  Check a box of “Maven Dependencies” and click “Apply and Close” button. 98
  99. JPA & JTA for CDI Unit Test Exercise • Create

    a Test Class folder named “src/test/resources”  Right click on the project and select “New”  “Source Folder”.  Enter “src/test/resources” and click “Finish” button. 99
  100. JPA & JTA for CDI Unit Test Exercise • Create

    a Test Class file for the created Java source file named “JpaCDITest.java” Right click on the “src/test/java” and select “New  Other…”, then select “Java  JUnit  JUnit Test Case”. Fill “org.example.jpaproject.test” in the Package field and “JpaCDITest” in the Name field and click “Finish” button. 100
  101. JPA & JTA for CDI Unit Test Exercise • Modify

    the Java Test source file (JpaCDITest.java) (1) For the “JpaCDITest” class, add “@EnableWeld”annotation. In the “JpaCDITest” class, setup Weld with “@WeldSetup” and add a property injecting “EnterpriseService” CDI with “@Inject” annotation. package org.example.jpaproject.test; import javax.inject.Inject; import javax.enterprise.context.ApplicationScoped; import static org.junit.jupiter.api.Assertions.*; import java.util.List; import org.junit.jupiter.api.Test; import org.example.jpaproject.domain.Employee; import org.example.jpaproject.service.EnterpriseService; import org.jboss.weld.junit5.EnableWeld; import org.jboss.weld.junit5.WeldSetup; import org.jboss.weld.junit5.WeldInitiator; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; @EnableWeld class JpaCDITest { @WeldSetup public WeldInitiator weld = WeldInitiator.from(EnterpriseService.class).activate( ApplicationScoped.class).build(); @Inject EnterpriseService service; : 101
  102. JPA & JTA for CDI Unit Test Exercise • Modify

    the Java Test source file (JpaCDITest.java) (2)  In the “JpaCDITest” class, create a method of “testEmployees()” with “@Test” annotation.  Obtain an “EntityManager” and pass it to the “EnterpriseService” CDI.  Add JTA transactional statements before and after executing “EnterpriseService#manageEmployee()”. : @Test void testEmployees() { EntityManager manager = Persistence.createEntityManagerFactory("persistenceUnit").createEntityManager(); service.setManager(manager); EntityTransaction tx = manager.getTransaction(); tx.begin(); List<Employee> list = service.manageEmployees(); tx.commit(); assertEquals(2, list.size()); manager.close(); } : } 102
  103. JPA & JTA for CDI Unit Test Exercise • Modify

    the Java Test source file (JpaCDITest.java) (3) In the “JpaCDITest” class, create methods of “setup()” with “@BeforeAll” annotation and “clearup()” with “@AfterAll” annotation and call a private function “clearupDB()” in both methods. Add the “clearupDB()” method above like the following to clear up Entities in the DB. : @BeforeAll static void setup() { clearupDB(); } : @AfterAll static void clearup() { clearupDB(); } : 103 : private static void clearupDB() { EntityManager manager = Persistence.createEntityManagerFactory("persistenceUnit").createEntityManager(); EntityTransaction tx = manager.getTransaction(); tx.begin(); manager.createQuery("DELETE FROM Employee e").executeUpdate(); manager.createQuery("DELETE FROM Department d").executeUpdate(); tx.commit(); manager.close(); } :
  104. JPA & JTA for CDI Unit Test Exercise • Copy

    the JPA configuration file of “persistence.xml” to “src/test/resources” folder. Right click on the “META-INF” in “src/main/resources” and click “Copy” and then select “src/test/resources” and click “Paste”. Modify the copied “persistence.xml” under “src/test/resources/META-INF” commenting out the <exclude-unlisted-classes> tag and defining target 2 JPA Entity classes with <class> tag. 104 src/test/resources/META-INF/persistence.xml
  105. JPA & JTA for CDI Unit Test Exercise • Procedure

    of the Exercise 105 Edit pom.xml Create the EnterpriseService Java Class Make a JUnit Test Class for the EnterpriseService Execute JUnit from Eclipse Execute JUnit from Maven
  106. JPA & JTA for CDI Unit Test Exercise • Execute

    JUnit directly for the created Java Test source file  Right click on the project and select “Run As”  “2 JUnit Test”  Confirm that JUnit finished successfully checking “Green” flag on “JUnit” tag menu. 106
  107. JPA & JTA for CDI Unit Test Exercise • Procedure

    of the Exercise Edit pom.xml Edit the Score and Calculator Java Class Make a JUnit Test Class for the Score Execute JUnit from Eclipse Execute JUnit from Maven 107
  108. JPA & JTA for CDI Unit Test Exercise • Execute

    JUnit through M2Eclipse™ for the created Java Test source file  Right click on the project and select “Run As”  “3 Maven build” Confirm that test completes successfully in “Console” 108
  109. JPA in Jakarta EE Container Programming Exercise 109

  110. Presentation Named CDI Business Domain Service Transactional CDI JPA in

    Jakarta EE System Test Exercise • Domain Model 110 Data Access O-R Mapper Entity Entity RDB Entity Entity Name: Vendor: ABC XYZ Update Update Results: Name ABC Vendor XYZ Entity Entity Web System Test Jakarta EE Container
  111. JPA in Jakarta EE System Test Exercise • Check if

    the “EXEC JPA” button on a JSF menu works successfully with “JUnit5” Testing Framework and “Selenium-Jupiter” for the integration between Selenium and JUnit5 • The button executes the “manageEmployees()” method of the “EnterpriseService” CDI called from “ViewBean” CDI migrated from the “jsfproject” project. 111 Exercise: Let’s create a new project using the tested CDI class and proceed the web system test for it.
  112. JPA in Jakarta EE System Test Exercise • Application Architecture

     “PostgreSQL™” instead of “Apache Derby™” as DBMS and “JTA” instead of “LOCAL_RESOURCE” as transaction type are used for the Web System Test (Maven Integration Test).  “LOCAL_RESOURCE” is still used for CDI Unit Test. Therefore different Persistence Units in each JPA Configuration File are required depending on each Maven build phase. 112 Payara Server (Jakarta EE Container) Eclipselink (JPA Framework) Configuration File (persistence.xml) Persistent Context Department Entity Employee Entity Entity Manager Application Enterprise Service CDI PostgreSQL (DBMS) ViewBean CDI AuthBean CDI jsf_jpaPool (Connection Pool) jdbc/jsf_jpa (JDBC Resource) home.xhtml login.xhtml ... Facelets Define Persistence Units for CDI Unit Test and Web System Test Need to check here!!!
  113. JPA in Jakarta EE System Test Exercise • This project

    of “jsf_jpa” is based on the “jsfproject” project and add necessary components from the “jpaproject” project on the Eclipse IDE. 113 jsfproject Copy jsf_jpa jpaproject Add • Employee/Department : Entities • EnterpriseService : Service • JpaCDITest : Unit Test • persistence.xml : JPA Config. • …
  114. JPA in Jakarta EE System Test Exercise • Procedure of

    the Exercise Edit pom.xml Copy and Modify persistence.xml and Setup PostgreSQL Create Packages and Copy/Move & Paste Required Files Modify Required Files Execute integration-test from Maven 114
  115. JPA in Jakarta EE System Test Exercise • Modify the

    created Maven Object Model file (pom.xml) Change the artifactId to “jsf_jpa”.  Add “weld-junit5”, “org.eclipse.persistence.jpa” and “postgresql” with “test” scope as dependency to execute JpaCDITest CDI Unit Test. <dependencies> : <dependency> <groupId>org.jboss.weld</groupId> <artifactId>weld-junit5</artifactId> <version>2.0.1.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>org.eclipse.persistence.jpa</artifactId> <version>2.7.7</version> <scope>test</scope> </dependency> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>jsf_jpa</artifactId> <packaging>war</packaging> <version>0.0.1</version> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.16</version> <scope>test</scope> </dependency> : </dependencies> 115
  116. JPA in Jakarta EE System Test Exercise • Procedure of

    the Exercise Edit pom.xml Copy and Modify persistence.xml and Setup PostgreSQL Create Packages and Copy/Move & Paste Required Files Modify Required Files Execute integration-test from Maven 116
  117. JPA in Jakarta EE System Test Exercise • Modify the

    JPA configuration file (persistence.xml) Create “src/main/resources” as “Source Folders” and copy “META-INF/persistence.xml” from the “jpaproject” project and paste it to the created folder. Modify the Persistence Unit in the copied persistence.xml like the following for Live Web Application System and Web System Test by Selenium product. <persistence-unit name="persistenceUnit" transaction-type=“JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/jsf_jpa</jta-data-source> <!-- shouldn't be valid for java SE per specification, but it works for EclipseLink ... --> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="create-tables" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> <property name="eclipselink.logging.level" value="SEVERE"/> <property name="eclipselink.target-database" value="PostgreSQL" /> </properties> </persistence-unit> 117
  118. JPA in Jakarta EE System Test Exercise • Modify the

    JPA configuration file (persistence.xml) for CDI Unit Test Create “src/test/resources” as “Source Folders” and copy “META-INF/persistence.xml” from the “jpaproject” project and paste it to the created folder. Modify the Persistence Unit in the copied persistence.xml for CDI Unit Test like the following. <persistence-unit name="persistenceUnit4Test" transaction-type="RESOURCE_LOCAL"> <!-- To make it work on JavaSE, we have to specify all used classes like the followings --> <class>org.example.jsf_jpa.domain.Department</class> <class>org.example.jsf_jpa.domain.Employee</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/jsf_jpa" /> <property name="javax.persistence.jdbc.user" value="jsf_jpa" /> <property name="javax.persistence.jdbc.password" value="jsf_jpa" /> <!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="create-tables" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> <property name="eclipselink.logging.level" value="SEVERE"/> <property name="eclipselink.target-database" value="PostgreSQL" /> </properties> </persistence-unit> 118
  119. JPA in Jakarta EE System Test Exercise • Setup PostgreSQL

    making an account of “jsf_jpa” setting its password to “jsf_jpa” with pgAdmin 4.  For the created account, enable the account to login. 119
  120. JPA in Jakarta EE System Test Exercise • Setup PostgreSQL

    making a database of “jsf_jpa” with pgAdmin 4 Set the owner of the database to the “jsf_jpa” account. 120
  121. JPA in Jakarta EE System Test Exercise • Setup Payara

    Server to accommodate a JDBC Connection Pool of “jsf_jpaPool” Set “Resource Type” to “javax.sql.DataSource”, “Database Driver Vendor” to “Postgresql” and “Introspect” to “Enable”. Set required parameters: “DatabaseNamejsf_jpa”, “Userjsf_jpa”, “Passwordjsf_jpa”, “URLjdbc:postgresql://localhost/jsf_jpa” and “Urljdbc:postgresql://localhost/jsf_jpa” 121 (*) Before configuring Payara Server, be sure that the PostgreSQL JDBC driver module is located in $PAYARA_HOME/glassfish/domains/domain1/lib/ext.
  122. JPA in Jakarta EE System Test Exercise • Setup Payara

    Server to accommodate a JDBC Resource of “jdbc/jsf_jpa” Set “Pool Name” to “jsf_jpaPool”. 122
  123. JPA in Jakarta EE System Test Exercise • Procedure of

    the Exercise Edit pom.xml Copy and Modify persistence.xml and Setup PostgreSQL Create Packages and Copy/Move & Paste Required Files Modify Required Files Execute integration-test from Maven 123
  124. JPA in Jakarta EE System Test Exercise • Refactor package

    names and Copy required files from the “jpaproject” Create packages “org.example.jsf_jpa.service” and “org.example.jsf_jpa.view” under the “src/main/java” folder and copy the “EnterpriseService.java” from the “jpaproject” and paste it to the “org.example.jsf_jpa.service” and refactor the “ViewBean.java” and the “AuthBean.java” to move their package to the “org.example.jsf_jpa.view” and delete “org.example.jsfproject”. Create a new “org.example.jsf_jpa.domain” package under the “src/main/java” and copy the “Employee” and “Department” Enitity Classes from the “jpaproject” and paste it to the created new package. Create packages “org.example.jsf_jpa.service” and “org.example.jsf_jpa.view” under the “src/test/java” folder and refactor the “AuthBeanTest.java” and “LoginIT.java” to move their package to the “org.example.jsf_jpa.view” and copy the “JpaCDITest.java” from the “jpaproject” and paste it to the “org.example.jsf_jpa.service” and delete “org.example.jsfproject”. 124
  125. JPA in Jakarta EE System Test Exercise • Procedure of

    the Exercise Edit pom.xml Copy and Modify persistence.xml and Setup PostgreSQL Create Packages and Copy/Move & Paste Required Files Modify Required Files Execute integration-test from Maven 125
  126. JPA in Jakarta EE System Test Exercise • Modify Domain

    Classes (Department.java, Employee.java)  Modify the two Domain Classes to add a Long “version” property with “@Version” annotation to make use of the Optimistic Lock feature. 126 @Entity public class Department { : @Version Long version; : public Long getVersion() { return version;} public void setVersion(Long version) { this.version = version;} : } Add accessors for the “version” property. Declare “version” property (*) We need to do the same thing for Employee Class as well.
  127. JPA in Jakarta EE System Test Exercise • Modify EnterpriseService

    CDI Java source file (EnterpriseService.java)  Define the CDI as a Transactional CDI with @Transactional Obtain EntityManager with @PersistenceContext DI for Jakarta EE Container 127 @Transactional @ApplicationScoped public class EnterpriseService { @PersistenceContext(unitName="persistenceUnit") private EntityManager manager; : public EntityManager getManager() { return manager; } public void setManager(EntityManager manager) { this.manager = manager; } Try to obtain EntityManager with DI for Jakarta EE container. Declare Transactional CDI
  128. JPA in Jakarta EE System Test Exercise • Modify JpaCDITest

    Java source file (JpaCDITest.java)  Change the persistence unit name to “persistenceUnit4Test” for CDI Unit Test 128 @Test void testEmployees() { EntityManager manager = Persistence.createEntityManagerFactory ( "persistenceUnit4Test").createEntityManager(); EntityTransaction tx = manager.getTransaction(); service.setManager(manager); : Specify the new persistence unit name for CDI Unit Test.
  129. JPA in Jakarta EE System Test Exercise • Modify ViewBean

    CDI Java source file (ViewBean.java) (1) Define Employee List of “empList” to show the list of employee and add accessor methods for it. Obtain EnterpriseService CDI of “es” by @Inject Injection. 129 @Named @ViewScoped public class ViewBean implements Serializable { private static final long serialVersionUID = 1L; private float lat = 34.694295f; private float lng = 135.1556805f; private int zoom = 15; private String token; private List<Employee> empList = new ArrayList<Employee>(); @Inject private AuthBean authBean; @Inject private EnterpriseService es; private Logger logger = Logger.getLogger(this.getClass().getName()); Add getter and setter for this new field.
  130. JPA in Jakarta EE System Test Exercise • Modify ViewBean

    CDI Java source file (ViewBean.java) (2)  Add a new method of “executeJPA()” to check its token and execute EnterpriseService#manageEmployees() from a JSF Facelets of “home.xhtml”. 130 public void executeJPA() { if (this.token.equals(authBean.getToken())) { String generatedString = generateRandomString(new Random(), 10); this.token = generatedString; authBean.setToken(generatedString); empList = es.manageEmployees(); return; } else { try {ExternalContext ec = FacesContext.getCurrentInstace().getExternalContext(); ec.redirect(ec.getRequestContextPath() + "/faces/login.xhtml"); } catch (IOException e) { e.printStackTrace(); } return; }}
  131. JPA in Jakarta EE System Test Exercise • Modify the

    “home” JSF Facelet file (home.xhtml) (1) Remove the <p:panelGrid> tag with the <ui:remove> tag. Add a new <p:commandButton> tag to execute ViewBean#executeJPA() instead. 131 <ui:remove> <p:panelGrid columns="2"> <p:outputLabel for="latitude" value="Latitude:" /> : </p:panelGrid> </ui:remove> : <p:commandButton id="executeJPA" value="EXEC JPA" action="#{viewBean.executeJPA}" update=":empList, token" /> :
  132. JPA in Jakarta EE System Test Exercise • Modify the

    “home” JSF Facelet file (home.xhtml) (2) Remove the <p:gmap> tag with the <ui:remove> tag. Add a new <p:dataTable> tag to show ViewBean#empList instead. 132 <ui:remove> <p:gmap id="gmap" … style="width:580px;height:380px" /> </ui:remove> <p:dataTable id="empList" var="emp" value="#{viewBean.empList}"> <p:column> <f:facet name="header"> <h:outputText value="Name" /> </f:facet> <h:outputText value="#{emp.name}" /> </p:column> <p:column> <f:facet name="header"> <h:outputText value="Department" /> </f:facet> <h:outputText value="#{emp.department.name}" /> </p:column> </p:dataTable>
  133. JPA in Jakarta EE System Test Exercise • Modify the

    system JUnit test file (LoginIT.java) Change the button name executing a JPA operation on the “home” page. 133 : element = driver.findElement(By.id("login")); element.click(); boolean isTitle = wait.until(ExpectedConditions.titleContains("Hello World")); assertTrue(isTitle); Thread.sleep(3000); element = driver.findElement(By.id("executeJPA")); element.click(); Thread.sleep(5000); element = driver.findElement(By.id("logout")); element.click(); :
  134. JPA in Jakarta EE System Test Exercise • Procedure of

    the Exercise Edit pom.xml Copy and Modify persistence.xml and Setup PostgreSQL Refactor Package Names and Copy and Modify Required Files Modify ViewBean and home.xhtml Execute integration-test from Maven 134
  135. JPA in Jakarta EE System Test Exercise • Execute JUnit

    through M2Eclipse™ for the created Java Test source file (1)  Right click on the project and select “Run As”  “Maven build …”  Put “jsf_jpa – post-integration-test (Remote)” in “Name” field and “post-integration-test” in “Goals” field and click “Run”. 135
  136. JPA in Jakarta EE System Test Exercise • Execute JUnit

    through M2Eclipse™ for the created Java Test source file (2)  Right click on the project and select “Run As”  “Maven build …”  Put “jsf_jpa – post-integration-test (Local)” in “Name” field and “post-integration-test” in “Goals” field and put “payara5x-local” in “Profile” field and click “Run”. 136
  137. Exercise 137

  138. Exercise for Managing Related Entities • Required features Create, Update

    and Remove a “Department” entity. Once one of the entity is removed, the related “Employee” entities are also deleted.  After one of the “Department” entity is selected, Create, Update and Remove an “Employee” entity related with the selected “Department” entity. 138