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

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

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

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 requires the basic skills of Windows 10, Rocky Linux, 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 Rocky Linux.

Koichi NAKAGAWA

November 26, 2020
Tweet

More Decks by Koichi NAKAGAWA

Other Decks in Programming

Transcript

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

    3.1) A part of Jakarta EE specification O-R Mapper and Transaction Framework 1 By Koichi NAKAGAWA Enterprise Web Application Development Course (5)
  2. Update Information • Ver. 3: Use Rocky Linux™ instead of

    CentOS™ as a Linux platform and Payara Server 6™ certified as Jakarta EE 9.1 Platform Compatible Products. • Ver. 2 : Use JDK 11 instead of JDK 8 and Jakarta EE 9 instead of Jakarta EE 8 in all exercises. 2
  3. JPA + JTA with CDI Jakarta Persistence API (JPA) and

    Jakarta Transaction API (JTA) with CDI 3
  4. EWA development course curriculum 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 (Rocky Linux™) Total EWA Development Exercise Jakarta Batch Java SE (Oracle JDK™/OpenJDK™) Required Skills to take courses Test Tool with JUnit5 PostgreSQL™ Administration 4 Object Oriented Development Methodology
  5. 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. 5
  6. Assumption for this course • The trainees who take this

    course are required the following skills in advance • PostgreSQL (Version: 13.5) – Basic Administration Operations • Payara Server (Version: 6.2021.1.Alpha1) – Basic Administration Operations • Oracle JDK/OpenJDK (Version: 11) • Eclipse IDE for Enterprise Java Developers (Version: 2021-12 (4.22.0)) • Build Tool Training Course • Version Control Tool Training Course • Test Tool Training Course • JSF with CDI Training Course 6
  7. 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 7
  8. 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 8
  9. Design Patterns in Business Layer • Analysis Models 10 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 11 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 12 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 13 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 Onion Architecture based

    on Domain Driven Architecture (DDD) to Domain Model 14 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 15 Business Domain Service / Infrastructure Entity/VO Entity/VO RDB Entity/VO Entity/VO Entity Manager
  15. Jakarta Persistence API (JPA) • Entity Instance Life Cycle 16

    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 • 2 Transaction Types 18 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
  17. Database Transaction • ACID Properties in DBMS for Short Transaction

    (1) 19 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
  18. Database Transaction • ACID Properties in DBMS for Short Transaction

    (2) 20 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
  19. Java Transaction • 2 Java Transaction Types 21 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
  20. Java Transaction • JTA Transaction [Managed by Application ] 22

    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!
  21. Java Transaction • JTA Transaction [Managed by Jakarta EE Container]

    23 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
  22. Java Transaction • Typical 2 JTA Transaction Attributes [@Transactional(TxType.REQUIRED or

    TxType.REQUIRED_NEW)] 24 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
  23. Transaction and Database Connection • Connection Pool for Performance Improvement

    • Data Source for Mappings between Transactions and Physical Connections 25 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)
  24. Locking Mechanism and Isolation Control • 2 types of Locking

    Method and 4 types of Isolation Level 27 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
  25. Locking Mechanism • Lock Method [Pessimistic Lock] 28 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
  26. Locking Mechanism • Lock Method [Optimistic Lock] 29 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
  27. Locking Mechanism • Comparison between Lock Methods 30 Lock Type

    Pessimistic Lock Optimistic Lock When to select? Cases where the same “Entity(a row)” is updated by many transactions at the same time. Other cases, 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
  28. How to set Lock Methods • JPA Programming for Pessimistic

    Lock 31 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; : }
  29. Long Transaction with Optimistic Lock • Demo – Long Transaction

    with Optimistic Lock 32 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
  30. Short Transaction with Optimistic Lock • Demo – Short Transaction

    with Optimistic Lock 33 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
  31. Short Transaction with Pessimistic Lock • Demo – Short Transaction

    with Pessimistic Lock 34 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
  32. Isolation Control • 3 Illegal Transaction Interactions [ANSI/ISO SQL Standard

    SQL92] 35 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
  33. Isolation Control • Transaction Interaction [Dirty Read] 36 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
  34. Isolation Control • Transaction Interaction [Non-repeatable Read] 37 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
  35. Isolation Control • Transaction Interaction [Phantom Read] 38 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
  36. Isolation Control • Comparison among Isolation Levels 39 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
  37. How to set Isolation Level • Isolation Level Configuration for

    Jakarta EE (In case of Payara Server) 40
  38. Modeling Domains in Data Access Layer • Logical Object Model

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

    Patterns in Data Access Layer 43 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
  40. Data Mapper Design Pattern • Example of Data Mapper Design

    Pattern 44 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
  41. O-R Mapper Architecture • JPA – Jakarta Persistence API 45

    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
  42. O-R Mapper Configuration • JPA Configuration File 46 Configuration File

    (persistence.xml) <?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" version="3.0"> <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 xmlns="https://jakarta.ee/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd" version="3.0"> <persistence-unit name="defaultUnit" transaction-type=“RESOURCE_LOCAL"> <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. For Jakarta Persistence 3.0
  43. How to obtain EntityManager in CDI? • 2 ways to

    obtain EntityManager 47 @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
  44. State Machine of JPA Entity Instance • JPA State Transitions

    of Entity Instance 48 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)
  45. JPA Annotations • 2 Ways to define JPA Annotations for

    Entity Properties (Columns) 49 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.
  46. JPA Annotations • Auto numbering for Primary Key 50 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
  47. JPA Annotations • Pessimistic Lock and Optimistic Lock (Review) 51

    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.
  48. JPA Annotations • Relationships (Definition) 52 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.
  49. . JPA Annotations • Relationships (Manipulation) 53 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.
  50. JPA Annotations • Relationships (fetch option) 54 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
  51. JPA Annotations • Relationships (cascade option) 55 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”
  52. JPA Annotations • Relationships (orphanRemoval option) 56 @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);
  53. JPA Annotations • Relationships (Inheritance : 3 Strategies) 57 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
  54. JPA Annotations • Relationships (Single Table Inheritance) 58 @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
  55. JPA Annotations • Relationships (Joined Multiple Table Inheritance) 59 @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
  56. JPA Annotations • Relationships (Table Per Class Inheritance) 60 @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
  57. JPA Annotations • Relationships (Embeddable Class and Embedded Properties for

    Value Object) 61 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
  58. JPA Annotations • Relationships (Element Collection with Embeddable Class for

    Collection of Value Objects) 62 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
  59. JPA DB Manipulation Language • 2 Ways to manipulate DB

    with JPA 63 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.
  60. JPA DB Manipulation Language • JPQL(Jakarta Persistence Query Language) 64

    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
  61. JPA DB Manipulation Language • JPQL – Aggregate Function &

    Grouping 65 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
  62. JPA DB Manipulation Language • JPQL – Sorting & Eliminating

    Duplications 66 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();
  63. JPA DB Manipulation Language • JPQL – Paging for query

    results 67 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
  64. 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 68
  65. 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); 69
  66. JPA DB Manipulation Language • JPQL – LAZY (N+1 SELECT

    Problem) 70 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
  67. JPA DB Manipulation Language • JPQL – Batch Delete and

    Update operations 71 • 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();
  68. JPA DB Manipulation Language • JPQL – Native Query 72

    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; : }
  69. DB Exception Handling • Sequence Model for Exception Handling 74

    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)
  70. Exception Handling in Transaction • Error Types in Transaction and

    how Jakarta EE Container handles them 75 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, …
  71. DB Exception Handling • EJB Exceptions 76 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.
  72. First JPA DB Application Development Exercise • Domain Class Model

    “Department” Entity has a relationship with “Employee” Entity (One-to-Many). 78 Employee - name Department - name * 1 Exercise: Let’s make the First JPA DB Application on Java SE for this Domain Model.
  73. First JPA DB Application Development 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. 79 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
  74. 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). Set “org.example” as <groupId> and “0.0.1- SNAPSHOT” as <version>. 3. Modify “pom.xml” to add properties of “project.build.sourceEncoding”, “maven.compiler.source” and “maven.compiler.target” setting “UTF-8”, “11” and “11” respectively. 4. Additionally, modify the following points to upgrade the project to use “Jakarta EE 9.1”. • In the “pom.xml”, for the dependency artifact of “eclipselink”, change <version> to “3.0.2”, and for the dependency artifact of “javax.persistence”, change <groupId> to “jakarta.persistence” and <artifactId> to “jakarta.persistence-api” and <version> to “3.0.0”. • For all the source files, “Department.java”, “Employee.java” and “JpaTest.Java”, change all the imported classes starting from “javax.persistence” package to ones starting form “jakarta.persistence” package. • For the JPA configuration file of “persistence.xml”, change all the attributes of <persistence> to use Jakarta Persistence 3.0 and all the <properties> under <persistence-unit> starting from “javax.persistence” package to ones starting form “jakarta.persistence” package. 80
  75. First JPA DB Application Development Exercise • Development Procedure on

    Eclipse™ (Continued) 5. Right click on the project and select “Properties” “Project Facets” and change “Java Version” to “11” and unset “JPA”. Moreover, we need to disable “JPA Configurator” of Maven feature by selecting “Window”  “Preferences”  “Maven”  “Java EE Integration” and unset “JPA Configurator”. This is because current Eclipse IDE has not supported Jakarta Persistence 3.0 yet. 6. Create the target jar file of “jpaproject-0.0.1-SNAPSHOT.jar” by building 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. 81 <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” from left menu. 2. Press “New launch configuration” icon button and set the name to “derby tool” and confirm “jpaproject” is selected as “Project” 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.
  76. First JPA DB Application Development Exercise • Project Explorer New

    Derby Database Folder created automatically by executing Java Application Modify Department Entity Class Modify Employee Entity Class Modify 82 Modify Main Class Modify JPA Configuration File
  77. JPA Relationship Programming Exercise • Relationships (cascade option) 84 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
  78. JPA Relationship Programming Exercise • Relationships (cascade option) 85 @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.
  79. 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. 86 <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
  80. JPA Relationship Programming Exercise • Project Explorer Delete Derby Database

    Folder before executing Java Application 87 Modify Main Class
  81. Presentation Named CDI Business Domain Service Transactional CDI JPA &

    JTA for CDI Unit Test Exercise • Domain Model 89 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
  82. 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 90 Exercise: Let’s modify the previous JPA DB Application to make the above new CDI class and test it.
  83. 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 91
  84. 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.8.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.8.2</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> 92
  85. 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>3.0.0.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jboss.weld.se</groupId> <artifactId>weld-se-core</artifactId> <version>4.0.2.Final</version> </dependency> : </dependencies> 93
  86. 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 94
  87. 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 jakarta.enterprise.context.ApplicationScoped; import jakarta.persistence.EntityManager; import org.example.jpaproject.domain.Department; import org.example.jpaproject.domain.Employee; 95 @ApplicationScoped public class EnterpriseService { private EntityManager manager; public EnterpriseService() { super(); } public EntityManager getManager() { return manager; } public void setManager(EntityManager manager) { this.manager = manager; }
  88. 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; } 96 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);} }
  89. 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”. 97 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
  90. JPA & JTA for CDI Unit Test Exercise • Procedure

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

    a Test Class folder named “src/test/java” by executing the followings  Right click on the project of “jpaproject” 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. 99
  92. JPA & JTA for CDI Unit Test Exercise • Create

    a Test Resource folder named “src/test/resources” by executing the followings  Right click on the project of “jpaproject” and select “New”  “Source Folder”.  Enter “src/test/resources” and click “Finish” button. 100
  93. 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. 101
  94. 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 static org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.util.List; import jakarta.inject.Inject; import jakarta.enterprise.context.ApplicationScoped; import jakarta.persistence.EntityManager; import jakarta.persistence.EntityTransaction; import jakarta.persistence.Persistence; 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; @EnableWeld class JpaCDITest { @WeldSetup public WeldInitiator weld = WeldInitiator.from(EnterpriseService.class).activate( ApplicationScoped.class).build(); @Inject EnterpriseService service; : 102
  95. 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(); } : } 103
  96. 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(); } : 104 : 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(); } :
  97. 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” defining target 2 JPA Entity classes with <class> tag. 105 src/test/resources/META-INF/persistence.xml
  98. JPA & JTA for CDI Unit Test Exercise • Procedure

    of the Exercise 106 Edit pom.xml Create the EnterpriseService Java Class Make a JUnit Test Class for the EnterpriseService Execute JUnit from Eclipse Execute JUnit from Maven
  99. 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. 107
  100. 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 108
  101. 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” 109
  102. Presentation Named CDI Business Domain Service Transactional CDI JPA in

    Jakarta EE System Test Exercise • Domain Model 111 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
  103. 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. 112 Exercise: Let’s create a new project using the tested CDI class and proceed the web system test for it.
  104. 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. 113 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!!!
  105. 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 following the procedure described in the slides form the next page. • Right click on the project and select “Properties” “Project Facets” and unset “JPA”. 114 jsfproject Copy jsf_jpa jpaproject Add • Employee/Department : Entities • EnterpriseService : Service • JpaCDITest : Unit Test • persistence.xml : JPA Config. • …
  106. 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 115
  107. JPA in Jakarta EE System Test Exercise • Modify the

    created Maven Object Model file (pom.xml) Change the artifactId to “jsf_jpa”.  Add “eclipselink”, “jakarta.persistence-api”, “weld-junit5” and “postgresql” with “test” scope as dependency to execute JpaCDITest CDI Unit Test. <dependencies> : <dependency> <groupId>org.eclipse.persistence</groupId> <artifactId>eclipselink</artifactId> <version>3.0.2</version> <scope>test</scope> </dependency> <dependency> <groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>3.0.0</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.jboss.weld</groupId> <artifactId>weld-junit5</artifactId> <version>3.0.0.Final</version> <scope>test</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.3.1</version> <scope>test</scope> </dependency> : </dependencies> 116
  108. 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 117
  109. 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/jpaPool</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> <property name="jakarta.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" /> <property name="jakarta.persistence.jdbc.url" value="jdbc:derby:simpleDb;create=true" /> <property name="jakarta.persistence.jdbc.user" value="jpaproject" /> <property name="jakarta.persistence.jdbc.password" value="jpaproject" /> <!-- 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 Delete
  110. 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”, if it does not exist 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="jakarta.persistence.jdbc.driver" value="org.postgresql.Driver" /> <property name="jakarta.persistence.jdbc.url" value="jdbc:postgresql://[hostname]/jpa_db" /> <property name="jakarta.persistence.jdbc.user" value="jpa_exercise" /> <property name="jakarta.persistence.jdbc.password" value="jpa_exercise" /> <!-- 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> 119 Hostname or IP address of PostgreSQL Server
  111. JPA in Jakarta EE System Test Exercise • Setup PostgreSQL

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

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

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

    Server to accommodate a JDBC Resource of “jdbc/jpaPool” Set “Pool Name” to “jpaPool”. 123
  115. 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 124
  116. JPA in Jakarta EE System Test Exercise • Refactor package

    names and Copy required files from the “jpaproject” 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 a new package of “org.example.jsf_jpa.service” 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 change it to import the above Entity Classes. Refactor the package of “org.example.jsfproject” under “src/main/java” to rename it to “org.example.jsf_jpa.view”. Create a new package of “org.example.jsf_jpa.service” under the “src/test/java” folder and copy the “JpaCDITest.java” from the “jpaproject” and paste it to the created package and change it to import an appropriate Entity Class. Refactor the package of “org.example.jsfproject” under “src/test/java” to rename it to “org.example.jsf_jpa.view”. 125
  117. 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 126
  118. 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. 127 @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.
  119. 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 from Jakarta EE Container 128 @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 from Jakarta EE container. Declare Transactional CDI
  120. 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 129 @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. private static void clearupDB() { EntityManager manager = Persistence.createEntityManagerFactory ("persistenceUnit4Test").createEntityManager(); EntityTransaction tx = manager.getTransaction(); tx.begin(); : Specify the new persistence unit name for CDI Unit Test.
  121. 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. 130 @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.
  122. 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”. 131 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. getCurrentInstance().getExternalContext(); ec.redirect(ec.getRequestContextPath() + "/faces/login.xhtml"); } catch (IOException e) { e.printStackTrace(); } return; }}
  123. JPA in Jakarta EE System Test Exercise • Modify the

    “home” JSF Facelet file (home.xhtml) (1) Remove the <p:panelGrid> tag by inserting the <ui:remove> tag. Add a new <p:commandButton> tag to execute ViewBean#executeJPA() instead. 132 <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" /> :
  124. 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. 133 <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>
  125. 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. 134 : element = driver.findElement(By.id("login")); element.click(); boolean isTitle = wait.until(ExpectedConditions.titleContains("Hello World")); assertTrue(isTitle); Thread.sleep(5000); element = driver.findElement(By.id("executeJPA")); element.click(); Thread.sleep(5000); element = driver.findElement(By.id("logout")); element.click(); isTitle = wait.until(ExpectedConditions.titleContains("Login Menu")); assertTrue(isTitle); Thread.sleep(5000); }
  126. 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 135
  127. 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”. 136
  128. 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 “payara6x-local” in “Profile” field and click “Run”. 137
  129. Exercise for Managing Related Entities • Required features Create, Update

    and Remove a “Department” entity. Once one of the entities 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. 139