GithubHelp home page GithubHelp logo

openliberty / guide-jpa-intro Goto Github PK

View Code? Open in Web Editor NEW
14.0 6.0 17.0 662 KB

A guide on how to use Java Persistence API to access and persist data to a database for your microservices: https://openliberty.io/guides/jpa-intro.html

License: Other

Java 67.14% HTML 23.52% CSS 6.83% Shell 2.51%

guide-jpa-intro's Introduction

Accessing and persisting data in microservices using Java Persistence API (JPA)

Note
This repository contains the guide documentation source. To view the guide in published form, view it on the Open Liberty website.

Learn how to use Java Persistence API (JPA) to access and persist data to a database for your microservices.

What you’ll learn

You will learn how to use the Java Persistence API (JPA) to map Java objects to relational database tables and perform create, read, update and delete (CRUD) operations on the data in your microservices.

JPA is a Jakarta EE specification for representing relational database table data as Plain Old Java Objects (POJO). JPA simplifies object-relational mapping (ORM) by using annotations to map Java objects to tables in a relational database. In addition to providing an efficient API for performing CRUD operations, JPA also reduces the burden of having to write JDBC and SQL code when performing database operations and takes care of database vendor-specific differences. This capability allows you to focus on the business logic of your application instead of wasting time implementing repetitive CRUD logic.

The application that you will be working with is an event manager, which is composed of a UI and an event microservice for creating, retrieving, updating, and deleting events. In this guide, you will be focused on the event microservice. The event microservice consists of a JPA entity class whose fields will be persisted to a database. The database logic is implemented in a Data Access Object (DAO) to isolate the database operations from the rest of the service. This DAO accesses and persists JPA entities to the database and can be injected and consumed by other components in the microservice. An Embedded Derby database is used as a data store for all the events.

You will use JPA annotations to define an entity class whose fields are persisted to the database. The interaction between your service and the database is mediated by the persistence context that is managed by an entity manager. In a Jakarta EE environment, you can use an application-managed entity manager or a container-managed entity manager. In this guide, you will use a container-managed entity manager that is injected into the DAO so Liberty manages the opening and closing of the entity manager for you.

Try what you’ll build

The finish directory in the root of this guide contains the finished application. Give it a try before you proceed.

To try out the application, run the following commands to navigate to the finish/frontendUI directory and deploy the frontendUI service to Open Liberty:

cd finish/frontendUI
mvn liberty:run

Open another command-line session and run the following commands to navigate to the finish/backendServices directory and deploy the service to Open Liberty:

cd finish/backendServices
mvn liberty:run

After you see the following message in both command-line sessions, both your services are ready.

The defaultServer server is ready to run a smarter planet.

Point your browser to the http://localhost:9090/eventmanager.jsf URL to view the Event Manager application. The event application does not display any events because no events are stored in the database. Go ahead and click Create Event, located in the left navigation bar. After entering an event name, location and time, click Submit to persist your event entity to the database. The event is now stored in the database and is visible in the list of current events.

Notice that if you stop the Open Liberty instance and then restart it, the events created are still displayed in the list of current events. Ensure you are in the finish/backendServices directory and run the following Maven goals to stop and then restart the instance:

mvn liberty:stop
mvn liberty:run

The events created are still displayed in the list of current events. The Update action link located beside each event allows you to make modifications to the persisted entity and the Delete action link allows you to remove entities from the database.

After you are finished checking out the application, stop the Open Liberty instances by pressing CTRL+C in the command-line sessions where you ran the backendServices and frontendUI services. Alternatively, you can run the liberty:stop goal from the finish directory in another command-line session for the frontendUI and backendServices services:

mvn -pl frontendUI liberty:stop
mvn -pl backendServices liberty:stop

Defining a JPA entity class

Navigate to the start directory to begin.

When you run Open Liberty in dev mode, dev mode listens for file changes and automatically recompiles and deploys your updates whenever you save a new change.

Run the following commands to navigate to the frontendUI directory and start the frontendUI service in dev mode:

cd frontendUI
mvn liberty:dev

Open another command-line session and run the following commands to navigate to the backendServices directory and start the service in dev mode:

cd backendServices
mvn liberty:dev

After you see the following message, your Liberty instance is ready in dev mode:

**************************************************************
*    Liberty is running in dev mode.

Dev mode holds your command line to listen for file changes. Open another command-line session to continue, or open the project in your editor.

To store Java objects in a database, you must define a JPA entity class. A JPA entity is a Java object whose non-transient and non-static fields will be persisted to the database. Any Plain Old Java Object (POJO) class can be designated as a JPA entity. However, the class must be annotated with the @Entity annotation, must not be declared final and must have a public or protected non-argument constructor. JPA maps an entity type to a database table and persisted instances will be represented as rows in the table.

The Event class is a data model that represents events in the event microservice and is annotated with JPA annotations.

Create the Event class.
backendServices/src/main/java/io/openliberty/guides/event/models/Event.java

Event.java

link:finish/backendServices/src/main/java/io/openliberty/guides/event/models/Event.java[role=include]

The following table breaks down the new annotations:

Annotation Description

@Entity

Declares the class as an entity

@Table

Specifies details of the table such as name

@NamedQuery

Specifies a predefined database query that is run by an EntityManager instance.

@Id

Declares the primary key of the entity

@GeneratedValue

Specifies the strategy used for generating the value of the primary key. The strategy = GenerationType.AUTO code indicates that the generation strategy is automatically selected

@Column

Specifies that the field is mapped to a column in the database table. The name attribute is optional and indicates the name of the column in the table

Configuring JPA

The persistence.xml file is a configuration file that defines a persistence unit. The persistence unit specifies configuration information for the entity manager.

Create the configuration file.
backendServices/src/main/resources/META-INF/persistence.xml

persistence.xml

link:finish/backendServices/src/main/resources/META-INF/persistence.xml[role=include]

The persistence unit is defined by the persistence-unit XML element. The name attribute is required and is used to identify the persistent unit when using the @PersistenceContext annotation to inject the entity manager later in this guide. The transaction-type="JTA" attribute specifies to use Java Transaction API (JTA) transaction management. Because of using a container-managed entity manager, JTA transactions must be used.

A JTA transaction type requires a JTA data source to be provided. The jta-data-source element specifies the Java Naming and Directory Interface (JNDI) name of the data source that is used. The data source has already been configured for you in the backendServices/src/main/liberty/config/server.xml file. This data source configuration is where the Java Database Connectivity (JDBC) connection is defined along with some database vendor-specific properties.

server.xml

link:finish/backendServices/src/main/liberty/config/server.xml[role=include]

The jakarta.persistence.schema-generation properties are used here so that you aren’t required to manually create a database table to run this sample application. To learn more about the JPA schema generation and available properties, see Schema Generation, Section 9.4 of the JPA Specification

Performing CRUD operations using JPA

The CRUD operations are defined in the DAO. To perform these operations by using JPA, you need an EventDao class.

Create the EventDao class.
backendServices/src/main/java/io/openliberty/guides/event/dao/EventDao.java

EventDao.java

link:finish/backendServices/src/main/java/io/openliberty/guides/event/dao/EventDao.java[role=include]

To use the entity manager at runtime, inject it into the CDI bean through the @PersistenceContext annotation. The entity manager interacts with the persistence context. Every EntityManager instance is associated with a persistence context. The persistence context manages a set of entities and is aware of the different states that an entity can have. The persistence context synchronizes with the database when a transaction commits.

The EventDao class has a method for each CRUD operation, so let’s break them down:

  • The createEvent() method persists an instance of the Event entity class to the data store by calling the persist() method on an EntityManager instance. The entity instance becomes managed and changes to it will be tracked by the entity manager.

  • The readEvent() method returns an instance of the Event entity class with the specified primary key by calling the find() method on an EntityManager instance. If the event instance is found, it is returned in a managed state, but, if the event instance is not found, null is returned.

  • The readAllEvents() method demonstrates an alternative way to retrieve event objects from the database. This method returns a list of instances of the Event entity class by using the Event.findAll query specified in the @NamedQuery annotation on the Event class. Similarly, the findEvent() method uses the Event.findEvent named query to find an event with the given name, location and time.

Event.java

link:finish/backendServices/src/main/java/io/openliberty/guides/event/models/Event.java[role=include]
  • The updateEvent() method creates a managed instance of a detached entity instance. The entity manager automatically tracks all managed entity objects in its persistence context for changes and synchronizes them with the database. However, if an entity becomes detached, you must merge that entity into the persistence context by calling the merge() method so that changes to loaded fields of the detached entity are tracked.

  • The deleteEvent() method removes an instance of the Event entity class from the database by calling the remove() method on an EntityManager instance. The state of the entity is changed to removed and is removed from the database upon transaction commit.

The DAO is injected into the backendServices/src/main/java/io/openliberty/guides/event/resources/EventResource.java class and used to access and persist data. The @Transactional annotation is used in the EventResource class to declaratively control the transaction boundaries on the @RequestScoped CDI bean. This ensures that the methods run within the boundaries of an active global transaction, which is why it is not necessary to explicitly begin, commit or rollback transactions. At the end of the transactional method invocation, the transaction commits and the persistence context flushes any changes to Event entity instances it is managing to the database.

EventResource.java

link:finish/backendServices/src/main/java/io/openliberty/guides/event/resources/EventResource.java[role=include]

When Liberty is running, go to the http://localhost:9090/eventmanager.jsf URL to view the Event Manager application.

Click Create Event in the left navigation bar to create events that are persisted to the database. After you create an event, it is available to view, update, and delete in the Current Events section.

Testing the application

Create the EventEntityIT class.
backendServices/src/test/java/it/io/openliberty/guides/event/EventEntityIT.java

EventEntityIT.java

link:finish/backendServices/src/test/java/it/io/openliberty/guides/event/EventEntityIT.java[role=include]

The testInvalidRead(), testInvalidDelete() and testInvalidUpdate() methods use a primary key that is not in the database to test reading, updating and deleting an event that does not exist, respectively.

The testReadIndividualEvent() method persists a test event to the database and retrieves the event object from the database using the primary key of the entity.

The testCRUD() method creates a test event and persists it to the database. The event object is then retrieved from the database to verify that the test event was actually persisted. Next, the name, location, and time of the test event are updated. The event object is retrieved from the database to verify that the updated event is stored. Finally, the updated test event is deleted and one final check is done to ensure that the updated test event is no longer stored in the database.

Running the tests

Since you started Open Liberty in dev mode, press the enter/return key in the command-line session where you started the backendServices service to run the tests for the backendServices.

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.event.EventEntityIT
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.703 sec - in it.io.openliberty.guides.event.EventEntityIT

Results :

Tests run: 5, Failures: 0, Errors: 0, Skipped: 0

When you are done checking out the services, exit dev mode by pressing CTRL+C in the command-line sessions where you ran the frontendUI and backendServices services.

Great work! You’re done!

You learned how to map Java objects to database tables by defining a JPA entity class whose instances are represented as rows in the table. You have injected a container-managed entity manager into a DAO and learned how to perform CRUD operations in your microservice in Open Liberty.

guide-jpa-intro's People

Contributors

ahmad-ayyoub avatar andrewdes avatar austinseto avatar dazey3 avatar dependabot[bot] avatar evelinec avatar gkwan-ibm avatar guidesbot avatar jakub-pomykala avatar jj-zhang avatar justineechen avatar maihameed avatar nimg98 avatar priyyanshi avatar proubatsis avatar ruilin-ma avatar ryan-storey avatar saumyapandyaa avatar t27gupta avatar tt-le avatar yeekangc avatar yuval105 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

guide-jpa-intro's Issues

Update the guide to use new LMP copyDependencies feature

Need to update the backendServices/pom.xml

...
         <!-- Derby library -->
        <version.derby>10.14.2.0</version.derby>
-        <derby.path>${user.home}/.m2/repository/org/apache/derby/derby</derby.path>
         <!-- Liberty configuration -->
         <backend.service.http.port>5050</backend.service.http.port>
         <backend.service.https.port>5051</backend.service.https.port>
-        <liberty.var.derby.lib>${derby.path}/${version.derby}/derby-${version.derby}.jar</liberty.var.derby.lib>
     </properties>
...
             <groupId>org.apache.derby</groupId>
             <artifactId>derby</artifactId>
             <version>${version.derby}</version>
-            <scope>test</scope>
+            <scope>provided</scope>
...
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-dependency-plugin</artifactId>
-                <version>3.1.2</version>
-                ...
-            </plugin>
             ...
             <plugin>
                 <groupId>io.openliberty.tools</groupId>
                 <artifactId>liberty-maven-plugin</artifactId>
+                <configuration>
+                    <copyDependencies>
+                        <location>${project.build.directory}/liberty/wlp/usr/shared/resources</location>
+                        <dependency>
+                             <groupId>org.apache.derby</groupId>
+                             <artifactId>derby</artifactId>
+                         </dependency>
+                    </copyDependencies>
+                </configuration>
...

and backendServices/src/main/liberty/config/server.xml

...
   <variable name="default.http.port" defaultValue="5050"/>
   <variable name="default.https.port" defaultValue="5051"/>
-  <variable name="derby.lib" defaultValue="${shared.resource.dir}/derby-10.14.2.0.jar"/>
... 
   <!-- Derby Library Configuration -->    
   <library id="derbyJDBCLib">
-      <file name="${derby.lib}" />
+      <file name="${shared.resource.dir}/derby-10.14.2.0.jar" />
   </library>
...

and update the daily build automation to fix #146

Event overrides equals but not hashCode

The Event class overrides equals() but does not override hashCode()

Although in this guide we're probably not hashing the Event, overriding equals() like this without also overriding hashCode() violates the contract of hashCode and is very bad practise.

Daily build test failed

It is because copying derby jar is ahead of installing liberty if using openliberty-all-xxx.zip as following in the pom.xml

<configuration>
  <install>
    <runtimeUrl>https://public.dhe.ibm.com/ibmdl/export/pub/software/openliberty/runtime/nightly/2020-09-08_1900/openliberty-all-20.0.0.10-cl201020200908-1900.zip</runtimeUrl>
  </install>
</configuration>

No issue if not using above.

Probably need the LMP copy dependencies feature: OpenLiberty/ci.maven#705

Peer Review

Overall

What you'll learn

  • These two sentences about what the guide will teach aren't really consistent, maybe you can find a way to tie the two together.

"You will learn how to use the Java Persistence API to map Java objects to database tables."
"Learn how to perform CRUD operations using JPA"

  • Many acronyms are introduced here (JPA, ORM, POJO, JTA) and mentioned throughout the guide, I felt that I had to go back a lot to remember them and it was difficult to follow along when I didn't understand the acronym.
  • I think ORM can be removed since it is only mentioned one time, or you can remove the acronym since we never use the term again.
    ex.

"JPA eliminates the burden of writing SQL code when performing database operations."

  • I'm not sure if it's necessary to include the Embedded Derby link, I feel like it disturbs the flow of the paragraph.

  • The following sentence could be simplified

You will use JPA annotations to define a Plain Old Java Object (POJO) class as an entity class whose persistent fields are persisted to the datastore.

You will use JPA annotations to define an entity class whose fields are persisted to the data store.

  • What are transaction boundaries? Is the user supposed to know what this term means already?

  • The following sentence could be simplified.

A container-managed EntityManager requires the use of the Java Transaction API (JTA). By using JTA transactions, the Event Manager application does not have to pass references to EntityManager instances from one component to another.

Getting Started

  • This sentence may be more clear in the following way

"Before being able to use JPA to store Java objects in a database, an entity class must be defined."
"An entity class must be defined before you are able to use JPA to store Java objects in a database."

  • I think it would be useful to show the persistence of the events by telling the user that the events will still be there after the server is stopped and ran again.

Accessing data using JPA

  • I feel like the paragraphs explaining the persistence-unit and data source configuration is a little redundant because the names of the attributes are self-explanatory.

Performing CRUD operatoins using JPA

  • Typo "The persistence" context manages a set of..."
  • Are all of the methods that you are describing essential to what the user needs to learn for the guide? If not, maybe you should remove the descriptions because there is a lot of information in these couple of paragraphs.

Peer Review

Peer Review

  • Working instruction and sample code
  • Quality of code (best coding practices)
  • Quality and presentation of guide according to Structure and Style Guideline
  • Consistency of guide with template and other guides
  • Examples with the right outcomes are provided
  • Example with the wrong outcomes, if any, are provided
  • Check that all licensing statements are properly stated in all files
  • Check that the pom.xml, server.xml, etc files are clean up
  • Check that the directories are properly structured

Fix the java code

Format all java code formatted properly
e.g.

  • in Event.equals() method missing space
        if(name == null) {
            if(other.name != null)
                return false;
        }else if(!name.equals(other.name))
            return false;
  • EventEntityTest
    • better have a new empty line in between
import io.openliberty.guides.models.Event;
public class EventEntityTest {
  • missing space
    private JsonObject findTestEvent(JsonArray events){
        for(int i = 0; i < events.size(); i++){

Convert to Dev Mode

  • Convert to Dev Mode
  • ideal pom
  • latest mp
  • jakartaee
  • latest version of dependencies and plugins

### Defining a JPA entity class

Defining a JPA entity class

  • Add file hotspot (or class hotspot) for Event class

    The Event class is a data model that represents events in the event microservice and is annotated with JPA annotations.

Configuring JPA

  • Add file hotspot for persistence.xml

    The persistence.xml file is a configuration file that defines a persistence unit.

  • server.xml need blank line before the end of the </server> tag

Performing CRUD operations using JPA

  • Add file hotspot (or class hotspot) for EventDao

    To perform these operations by using JPA, we need an EventDao class.

  • annotations in EventResource.java should have space above them, not below them:
    image

Originally posted by @NimG98 in #121 (comment)

Review on 9/7's draft

Title and Intro:

  • the title doesn’t seem broad enough to cover what’s in the abstract, ie, mapping java objects to the db and CRUD.
  • it feels that the intro is not enough. ie, can explain ORM more?
  • state the benefit of using JPA separately to increase its value? ie, eliminates the burden of having to write SQL code when performing database operations.
  • also are there more benefits of using JPA? perhaps answer the question of how data processing work without using JPA and then why JPA makes things easier/better?
  • not sure what “container-managed entity manager” means on its own. perhaps there are different type of entity managers, and this is one of them? Then I’d say should briefly mention the different types, then say this guide will use the container-manage type.
  • “The application that you will be working with is the event manager, which provides services for creating, retrieving, updating, and deleting event entities.” I think this sentence can be broken down into two. ie, “The application that you will be working with is an event manager.” Then I think user will be instructed to build the CRUD operations with the database. So perhaps, describe how JPA work and then mention the CRUD services that user will be building.

Defining a JPA entity class

  • the @NamedQuery annotation probably needs a more explanation, why is it used here?
  • the @id annotation description doesn’t start with a verb

Tommy's Feedback

I don't have many complaints for this guide. I loved how descriptive it was compared to the other guides. This made it very easy to understand and work through quickly. The 20 minute estimated completion time was also accurate. One fault with the guide is perhaps the tests. When I create an event and do not delete it a test will fail. I figured this may not be intended as many users may not delete all of the events they have created before running mvn verify

Compilation fails in the start directory

Should I be able to run 'mvn compile' from the start directory?

When I clone the guide and navigate to the start directory I cannot successfully execute mvn install or mvn compile because there are compilation errors (see screenshot below). Perhaps it would be more user friendly and intuitive if the user could compile from the start directory. Compilation errors should only occur if they are caused by the user.

image

Review on 8/7's draft

  • The application that you will be working with is the Event Manager, which provides services for creating, retrieving, updating and deleting Event objects. => it feels that the "Event Manager" doesn't need to be backticked and cap'ed, simply leave it as "a event manager". Similarly for the "Event objects", it can be "events" or "event objects". Kind of prefer the first.

  • The application uses an Embedded Derby database as a datastore for all the Event objects. => same here for "Event objects".

  • If you want to learn more about Embedded Derby, see the official website. => official website should be change to the title for the website, ie, Derby Tutorial website. Or simply don't need the word "website".

  • You will use JPA annotations to define an entity class whose fields are persisted to the database. Every entity object is managed by an EntityManager that will be injected into our Enterprise Java Bean (EJB). In this guide, you will learn how to use a container-managed EntityManager so you will not need to explicity begin, commit or rollback database transactions, the EJB container will manage the transaction boundaries for you. => Notice in this paragraph you talked about entity. If you had introduced the event object as event entity in the previous paragraph, that'll make this paragraph easier to follow. You did seem to use event entity later in the guide too.

  • Avoid using the directional word, ie, "Add the following JPA annotations to the Event class in the src/main/java/io/openliberty/guides/jpaguide/models/Event.java file:". => also, specify the annotations to be added. Looks like there're quite some annotations, perhaps you provide the event class, then refer and talk about each annotation. What you have currently is not very clear.

  • Remove the "related guide" tag if there's no related guide.

Multipane Issues

Configuring JPA

  • "The name attribute is required and is used to identify the persistent unit.." -> name should be hotspotted and highlight the name attribute
  • "The data source has already been configured for you in the backendServices/src/main/liberty/config/server.xml file." -> In the server.xml hotspot, could we highlight the data source configuration when jumping to the file? I think that would be more beneficial to the user than just switching to the file itself, this way they know exactly where the configuration is taking place.
  • "JPA Extensions Reference for EclipseLink." hyperlink doesn't open in new tab

Performing CRUD

  • "The CRUD operations are defined in the DAO. To perform these operations by using JPA," -> This sentence is then followed by a code command arrow. Is this valid? I have not seen something like this in previous guides. Perhaps we should make this a full sentence instead.
  • "The DAO is injected into the finish/backendServices/src/main/java/io/openliberty/guides/event/resources/EventResource.java class and used to access and persist data." -> finish directory can be taken off the path

Building and running the application

  • "Your Maven pom.xml is already configured to start the application in this server instance." -> Should pom.xml be hotspotted and displayed in the right hand pane?

Nice work you did it!

  • "You learned how to map Java objects to database tables by defining a JPA entity class whose instances are represented as rows in the table in Open Liberty" -> Makes it sounds like the table is in Open Liberty. I think this sentence should be reworded or perhaps the "in Open Liberty" should be added elsewhere.

Remove the warnings

Got following warning during mvn install:

[WARNING]
[WARNING] Some problems were encountered while building the effective model for io.openliberty.guides:io.openliberty.guides.jpaguide:war:1.0-SNAPSHOT
[WARNING] 'dependencyManagement.dependencies.dependency.version' for io.openliberty.features:features-bom:pom is either LATEST or RELEASE (both of them are being deprecated) @ line 30, column 26
[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING]

Review feedback

  • The objective of this guide should show to the readers what files are they need to create (or concern), so that they can create a JPA microservice without GUI. The content (Readme) should mention and explain all those files. I guess they should be
    • Event
    • EventDao
    • EventService (the rest service, right?)
    • EventApplication ???
    • persistence.xml
    • server.xml (JDBC and DataSources) ???
  • Following paragraph should be under the source first in the section
    • The EventDao.java class has a method for each CRUD operation, so let’s break them down:
  • Because the application in this guide contain UI and JPA microservice, the source should be organized clearly
    • Page* classes should be under ui package
      • e.g. io.openliberty.guides.ui.facelets
    • URLMapper? UI or JPA microservice code?
  • Add comment to each class to explain its purpose (especially the UI classes because they are not described in Readme)
  • Is it important to explain EntityManager in EventDao? It is mentioned in Readme several places but it only appears in EventDao as an private variable.

Feedback for "Performing CRUD operations using JPA"

The paragraph below under this section is difficult to understand:

Every entity object has a lifecycle that consists of four states: new, managed, detached and removed. Whenever a new Event object is created its state will be new, meaning that it is not mapped to a row in the database table and is not associated with an EntityManger. Managed entities are entities that have been persisted, or fetched by find() or a query, and are managed by the EntityManager. This means that they are actively tracked by the persistence context. Detached entities are no longer managed by a persistence context. When using a container-managed EntityManager, entities automatically become detached at the end of transaction boundaries. Lastly, removed entities will be marked for removal and will be deleted from the database upon transaction commit.

Its relationship to the rest of the section is difficult to work out too.

Should consider revision to make it easier to understand and make clear its relationship to doing CRUD operations.

Review comments

Development question before the rest of my comments (as the answer might nullify some of my comments below). Is there a reason why the app uses an EJB container instead of JPA in CDI? I don't know how well these two examples map to the app in this guide but they seem similar (at a very quick glance): http://www.mastertheboss.com/jboss-frameworks/cdi/cdi-and-jpa-tutorial and https://www.sitepoint.com/cdi-weld-inject-jpa-hibernate-entity-managers/

The rest of my comments (which I'd already written):

What you'll learn

  • "container-managed" - I think the context here needs to be clearer. My first thought was Docker containers but it's actually talking about EJB containers. I think using the term "EJB container" first would make the context clearer.

  • It's not clear (from the introduction) what the EJB here is for and why EJB is being used in this app. Can this be made clearer?

Defining a JPA entity class

  • "Add JPA annotations to the Event class and all of its fields in the src/main/java/io/openliberty/guides/jpaguide/models/Event.java file:" should be "Create file xxxx" (using the standard wording we use in other guides. Then the user copies the entire class and creates the class (however we do it as standard for the guides) in the location in the start folder. There's no reason to provide the old version because the text below the snippet explains what's been added to make it a JPA entity class and why. I like the rest of the intro before that sentence - nice and clear.

    For most guides, the purpose of the guide app isn't for the reader to adapt an existing app. The aim is that they will build the app. But, in most guide apps, there are parts that are not relevant to learning about the key concepts addressed in the guide. That's why we have the start directory - it contains files that don't contribute to the learning. In this case, there's no reason for the Event.java file to be part of the start directory because the reader creates the file as part of learning about what it does.

  • "Lets break down the new annotations:" -> "Let's break down the annotations that are used in this JPA entity class:" (or similar). Note, also, the apostrophe. I like the table.

Configuring the EntityManager

  • I'm not sure I follow what an "EntityManager instance" is. Instance of what? And why does it need to be configured? I think this introductory paragraph (before creating the persistence.xml file) needs to be clearer. Okay, so I just noticed it's introduced a little more in the "What you'll learn" section but I'm still not clear why the word is highlighted (as opposed to just "entity manager" because I don't see the term used in any of the code. According to the Oracle docs it's an interface.

  • "Configuring the EntityManager" heading. It looks weird having highlighting in a heading. I'd suggest without the highlighting but I think the title needs to be clearer what the section is about.

  • "displayed in the WAS server log" - I don't think it should refer to the WAS server log? That's not it's name and we shouldn't be referring to WAS/WebSphere unless that's the exact name of the file. I think it'd be worth giving the name of the log file in the target/..../servers... directory structure (assuming that's what's being referred to) so that they can take a look at it.

  • "A JTA transaction type requires a data source" - is this still part of configuring the EntityManager? Or should it be a separate "Configuring the data source" section? (I don't know - it just is a bit unclear that this is the start of a next bit - not critical though).

  • "This means that a Java Database Connectivity (JDBC) connection does not have to be specified in the persistence.xml file and instead the data source can be preconfigured in the server.xml." - It needs to be clearer why this is a good thing (I assume it is?). Also "preconfigured" should be "configured".

  • "Configure the data source in the src/main/liberty/config/server.xml file:" - this should be 'Create the xxx/server.xml file:" etc. The previous paragraph explains that the data source is configured in there and the paragraphs after the snippet explain the relevant bits.

  • Would it make sense to introduce the entity manager and CRUD etc before doing the entity manager configuration? ie swap the order of the Configuring the EntityManager and Performing CRUD operations using JPA sections. Does that cause problems or make no sense to a developer? I'm just thinking it might make it easier to see why you need to configure it if you've already used it in the app.

Style comments:

  • Think "Java Objects" should be "Java objects". "Object Relational Mapping" -> "object relational mapping (ORM)". There's no need to capitalise programming concepts.

  • "injected into our Enterprise Java Bean (EJB)." - make "our" into "the" - it reads oddly as it is ("our" is not used anywhere else - and is annoying if used everywhere - so just stick with "the").

  • "Every entity object is managed by an EntityManager" - It doesn't make sense to run the highlighted interface name into a sentence like this. Re-word eg "Every entity object is managed by an entity manager".

  • Use the Oxford comma in lists. So put a comma in "creating, retrieving, updating, and deleting event entities" (commas before 'and' and 'or' in lists of more than two items). See also the next example...

  • "In this guide, you will learn how to use a container-managed EntityManager so you will not need to explicity begin, commit or rollback database transactions, the EJB container will manage the transaction boundaries for you." -> "In this guide, you will learn how to use a container-managed EntityManager which means you do not need to explicitly begin, commit, or rollback database transactions because the EJB container manages the transaction boundaries for you." Don't talk about how the technology works in the future tense - it's not going to happen in the future - that's just how it works. Also, "roll back" as two words when used as a verb.

  • In the annotations table, "Specifies the generation strategy for the value of the primary key, strategy = GenerationType.AUTO indicates that the persistence provider will pick a strategy depending on the database used" doesn't make sense. Either the comma should be a full-stop/period, or there should say "which indicates" (depending on the meaning intended).

  • "oeration" - typo

Gilbert's comment

  • in the pom.xml, organize the <dependency/> better, e.g.
    • put all test scope dependencies together
    • a comment to indicate each scope
    • is org.apache.derby only required in test scope?
  • I found the following are deprecated, would confirm that they are right to use?
    • javax.faces.bean.ManagedBean
    • javax.faces.bean.ViewScoped
    • javax.faces.bean.ApplicationScoped
  • a minor: in server.xml, does not align with and others
  • EventEntityTest.findTestEvent(), a line longer than 88 chars and not align
  • add a comment for the dependency of jaxb-* in the pom.xml that they are for Java 9 and 10

multipane

Defining a JPA entity class

  • right side of annotations chart cut off, could use some formatting (maybe make middle guide panel larger?)

Configuring JPA

  • transaction-type="JTA" should be set up as a hotspot

Checklist for Review

Through the browser:

  • Read over guide and run through all commands (copy and paste using browser etc..)
  • Test the actual application (use it, hit endpoints, etc.)
  • No files in the middle panel (guide section)
  • Appropriate files are being displayed on the right hand side at the right time
  • Any mention of code in the right panel should be hot spotted
  • Make sure hotspots actually point to the correct lines
  • Any actions to the code (Create, replace) should be put in an arrow (code_command)
  • All code commands are highlighting the right code
  • Any actions to look at the code should be a hotspot
  • Guide attribution is present
  • Any links are hyperlinks with the webpage title not the URL
  • Feature versions should not be included in the guide
    In the README.adoc:
  • Tags in the front matter are correct (MicroProfile, Maven, Docker, Kubernetes, Gradle, Java EE)
    • If :page-guide-category: none remove :page-essential: and :page-essential-order:

In other files:

  • Failsafe plugin and Surefire plugin updates if applicable
  • Parent POM update
    • start directory
    • finish directory
  • Files are formatted correctly
  • .travis.yaml file is updated accordingly

In the readme.adoc's page tags make sure to add another ' to the [Java EE']

Joe's Review

My thoughts, comments, and suggestions:

What You'll Learn

  1. What level of expertise are we expecting of the user? I don't see CRUD defined anywhere near the top, so are we expecting a base level of database knowledge?

  2. Might sound better? " eliminates the burden of having to write JDBC and SQL code when performing database operations."

  3. "The application that you will be working with is the event manager, which provides services for creating, retrieving, updating, and deleting event entities." -- In this statement, are you referring to JPA entity types? I ask because the word "entity" gets to be a really overloaded term, so if another word, to diminish confusion, can be used that might be better

  4. "You will use JPA annotations to define an entity class whose fields are persisted to the database. Every entity object is managed by an entity manager that will be injected into the Enterprise Java Bean (EJB)."

Maybe something more like: "You will use JPA annotations to define an entity class whose fields are persisted to the database. The interaction between your application and the database is mediated the persistence context managed by an EntityManager, which itself is injected into the Enterprise Java Bean (EJB) Session Bean."

  1. "In this guide, you will learn how to use a container-managed entity manager which means the EJB container is responsible for opening and closing the entity manager, as well as managing the transaction boundaries so that you do not need to explicitly begin, commit, or rollback database transactions."

Maybe something more like: "In this guide, you will learn how to use a (Transaction-Scoped) Container-Managed Persistence Context EntityManager (which places the burden of managing the EntityManager's lifecycle on the application server) with a (Stateless) EJB Session Bean; the Session Bean has been configured so that the EJB Container manages the global transaction boundaries, so that you do not need to explicitly begin, commit, or rollback database transactions."

Getting Started

Defining a JPA entity class

  1. "JPA uses a database table for every entity" -- technically it's more complicated than that, when you consider the various types of inheritance schemes, secondary table mappings, etc.

  2. Looking at the Event entity class, I gotta ask: A String for time Data?

@Column(name = "eventTime")
    private String time;

Why not use java.util.Date (with @ Temporal) or java.sql.Timestamp?

Configuring the entity manager

  1. I see lots of use of "entity manager" throughout the document, let's actually use its proper class name, "EntityManager".

  2. "An entity manager provides the functionality for performing operations on the database such as persisting, loading, updating, and deleting entities."

Maybe change that to "An EntityManager provides the functionality to perform operations on the database such as persisting new entities (table rows), fetching entities through find() and queries, updating changes, and removing entities (table rows.)"

  1. In an EE environment, you do not need the <class>io.openliberty.guides.jpaguide.models.Event</class> entry. That is for only for the JSE environment (or applications which use the JSE bootstrapping method, something I try to discourage.)

Performing CRUD operations using JPA

  1. Ok, so you define CRUD here. I think it should be defined much earlier, so the reader isn't distracted what CRUD stands for, since the term is introduced right at the beginning.

  2. Though the default is Container Managed Transactions, it might be helpful to annotate the session bean with the @TransactionManagement(CONTAINER) annotation, and session bean's business methods with the @TransactionAttribute(REQUIRED) annotation (the defaults). We shouldn't assume the reader knows those are the defaults.

  3. "Since the entity manager is container-managed, the EJB container will ensure that the methods are executed within an active transaction which is why it is not necessary to explicitly begin, commit, or rollback transactions. "

No. "Since the Stateless Session Bean is configured to manage the global transaction, the EJB Container will ensure that its business methods are executed within the boundaries of an active global transaction, which is why it is not necessary to explicitly begin, commit, or rollback transactions."

A Container Managed Persistence Context's EntityManager will enlist with the current global transaction (caveat: since 2.1 that can be made optional given the new transaction synchronization configurability.) The EntityManager itself doesn't start or commit/rollback transactions (though it can mark the global transaction for rollback given certain error events.)

  1. "At the end of an EJB operation, the persistence context will be notified that the transaction is committing and the persistence provider, EclipseLink, will flush the changes to the database."

I think this might sound better "At the end of a session bean business method invocation, the persistence context will be notified that the transaction is committing, and will flush any changes made to entity instances it is managing to the database."

It is important to clarify this, because if you em.detach() entities before the commit, changes made to those entities would be lost. You would have to invoke a manual flush with em.flush() before detaching those entities if they have changes you want to save on the database.

  1. Somewhere here might be a good idea to point out that at the end of transaction boundaries, entities managed by a Container Managed Persistence Context become detached automatically.

It might be a good idea to dedicate a paragraph explaining the notion of new entities (constructed, never persisted by an EntityManager), managed entities (new entities that have been persist()ed, fetched by find() and queries, and merge()d, that are being actively tracked by the persistence context), and detached entities (entities that have been explicitly kicked out of the persistence context by em.clear() or em.detach(), or in a CMTS persistence context, a commit/rollback transaction boundary.)

Of course, things get more complicated when you consider persistence context propagation, which gets even more hairier when you consider transaction suspension when encountering business methods annotated with REQUIRES_NEW, etc.

  1. "The updateEvent() method updates an instance of the Event entity class in the database. The EntityManager automatically tracks entity objects in the persistence context for changes and synchronizes them with the database. The merge() method will copy the entity supplied as an argument into a new Event instance that will be added to the persistence context so that its changes can be tracked."

Yeah, that wording bugs me. It comes back to the necessity of explaining new/managed/detached entities. The thing is, changes to managed entities are automatically tracked by the persistence context, you don't have to do anything. But if your entity becomes detached, then yes, you have to merge that entity into the current persistence context (it gets hairier when you consider that the merge will only track changes for fields which have been loaded before the entity was detached, so there's ramifications for LAZY loaded fields here.)

  1. "The deleteEvent() method removes an instance of the Event entity class from the database by calling the remove() method on an EntityManager instance. An instance of an entity class must be passed as an argument to the remove() method, otherwise an IllegalArgumentException will be thrown."

Eh, maybe say it marks the entity for deletion, because it doesn't actually issue the DELETE FROM SQL statement until either a flush() (implicit or explicit, implicit flushes can happen any time you execute a query) or at transaction commit. Considering that remove() requires an active transaction in this scenario, that detail might not matter

(NOTE: I haven't executed the test yet, will update this issue when I have)

YK's feedback

Make it clear what in the service or the application uses JPA and for what. IOW, explain not only in terms of JPA and what it can do but also from the perspective of the application what it is used for and why it matters.

The focus is here is on accessing and persisting data for microservices and JPA is what we used to accomplish this in the service -- JPA helps us to map from the objects that we need to work with to the data in the DB and make it easier for us to query for the data and make changes.

Peer Review - 11/14/2018

  • Working instruction and sample code
  • Quality of code (best coding practices)
  • Quality and presentation of guide according to Structure and Style Guideline
  • Consistency of guide with template and other guides
  • Examples with the right outcomes are provided
  • Example with the wrong outcomes, if any, are provided
  • Check that all licensing statements are properly stated in all files
  • Check that the pom.xml, server.xml, etc files are clean up
  • Check that the directories are properly structured
  • Test the guide on 3 platforms: Mac, Win, Liniux
  • If any URL visits, try them on different browsers: Firefox, Chrome, Safari
  • If any URL visits, try curl command where applicable

Ports being used by another program

There is an issue for the ports be used by any other program. Not only the server cannot be started, but also the test will fail (The test in the JPA guide hard-coded the port and it should be same as other guides). Therefore, the test should provide an easy way to update the ports instead of search and update the test files.

Joe's Review #2

Reviewing https://qa-guides.mybluemix.net/guides/jpa-intro.html in its current state.

Section What you’ll learn:

"The JPA specification is implemented by several different persistence providers."

This reads a little awkward to me.

"In this guide you will use EclipseLink as the persistence provider because it is the implementation that is shipped with Liberty."

We actually ship 2 JPA provider implementations, Apache OpenJPA for the jpa-2.0 feature, and Eclipselink for the jpa-2.1 and jpa-2.2 (and expectingly all future) features.

"JPA simplifies object-relational mapping (ORM) by using annotations and/or XML to map Java objects to tables in a relational database."

As a newcomer, I'd wonder what they mean about "XML". I'd say "Object Relational Mapping XML Documents" or something to that effect.

"JPA also reduces the burden of having to write JDBC and SQL code when performing database operations."

True, but I think it is also worthwhile to figure a way to mention that JPA also takes care of database vendor specific differences in (most) cases. It doesn't get everything, but it does a fairly decent job. Anyone who has written a JDBC application that supports multiple database vendors is already familiar with having to write complicated if-blocks addressing database vendor differences with trying to accomplish the same thing.

Section Defining a JPA entity class

"A JPA entity is a Java object whose non-transient fields will be persisted to the database."

I'd say non-transient and non-static fields. Static fields are not considered persistent fields.

"JPA uses a database table for every entity and persisted instances will be represented as one row in the table."

Maybe say JPA maps an entity type to a database table (although you can also map an entity to secondary tables.) But I think "map" is a better word than "uses" here.

This block here:

<logging  traceSpecification="eclipselink.sql=all"
  traceFileName="trace.log"
  maxFileSize="20"
  maxFiles="10"
  traceFormat="BASIC" />

I don't think "eclipselink.sql=all" is a valid trace spec. I think you want "JPA=all". That will trace both the JPA Runtime Integration as well as integrate Eclipselink's own logging into Liberty's trace system.

Section Performing CRUD operations using JPA:

Please say "EntityManager" and not "entity manager".

"Lastly, removed entities are ones that have been removed from the database."

Removed entities are marked for removal, the DELETE FROM TABLE won't be issued to the database until flush or transaction commit.

Peer Review

What you'll learn

  • What are RDBMS tables? Should this be explained?
  • object-relational mapping
  • "and/or" Should this be just an "or" because if they use both annotations and XML wouldn't that be redundant?

JPA simplifies object relational mapping (ORM) by using annotations and/or XML to map Java objects to tables in a relational database.

Configuring the Entity Manager

  • < persistence unit>
  • < data source>

Testing the application

  • testCrud() method

Need to fix the abstracts and intro sentence

These should better reflect what the guide covers:

:page-description: Learn how to perform CRUD operations using JPA
Learn how to map Java objects to database tables and perform CRUD operations using JPA.

The first one is the abstract that shows in the card for the guide under all guides page and the second one is the abstract under the title.

Consider something along the line of "Learn how to use Java Persistence API to access and persist data to a database for your microservices".


For the below:

You will learn how to use the Java Persistence API (JPA) to map Java objects to database tables and
perform create, read, update and delete (CRUD) operations in your microservices.

We should call out the target too i.e. it is against a (relational) database.

The jpa guide does not show up in search results

When I search for the "jpa" on the open liberty website this guide does not appear.

Screen Shot 2019-04-08 at 11 54 42 AM

However, it does appear when I search "java persistence". A developer may not know what jpa stands for and may simply search "jpa".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.