57
UNIVERSITY OF NOVI SAD FACULTY OF SCIENCES DEPARTMENT OF MATHEMATICS AND COMPUTER SCIENCE Persistence in EJB 3: A Practical Example Term paper from course Software Engineering for Database Systems Professor: Dr. Miloš Racković Student: Robert Pap Date: May 19, 2011 Novi Sad

Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Embed Size (px)

Citation preview

Page 1: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

UNIVERSITY OF NOVI SAD

FACULTY OF SCIENCES

DEPARTMENT OF MATHEMATICS AND COMPUTER SCIENCE

Persistence in EJB 3: A Practical Example

Term paper from course Software Engineering for Database Systems

Professor:Dr. Miloš Racković

Student:Robert Pap

Date:May 19, 2011 Novi Sad

Page 2: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most
Page 3: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Table of ContentsABSTRACT___________________________________________________________5INTRODUCTION_______________________________________________________7INTRODUCING EJB 3___________________________________________________9

A BRIEF HISTORY ABOUT EJB 9OVERVIEW OF EJB 3 9EJB 3 TYPES 11THE HELLOUSER EXAMPLE 12

THE MODEL OF THE PRACTICAL EXAMPLE_______________________________13THE IMPLEMENTATION OF THE PRACTICAL EXAMPLE_______________________17

THE PERSISTENCE AND DATABASE LAYER 17THE BUSINESS LOGIC LAYER 29THE PRESENTATION LAYER 39

THE PRACTICAL EXAMPLE IN ACTION___________________________________45SETTING UP AND CONFIGURING PUBDB 45STARTING PUBDB 47

CONCLUSION________________________________________________________55

3

Page 4: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most
Page 5: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

AbstractEnterprise software is software used in organizations, such as in a business or government

and is usually an integral part of an Information System. One of the major players in this field is Enterprise JavaBeans (or EJB for short) developed by Sun Microsystems (now owned by Oracle). This term paper was written to demonstrate some possibilities of EJB technology, namely the persistence of data in databases. In EJB, this piece of technology is called Java Persistence API (or JPA for short). JPA is a framework managing relational data in applications using the Java platform. In order to achieve this functionality, JPA (and other similar technologies) use the Object-Relational Mapping (or ORM for short) technique for converting data between incompatible type systems in object-oriented programming languages (in this case, between Java and a relational database). With this technique, a developer can manage data stored in a database as pure objects. Lastly, to query the database, an ORM-friendly query language must be used: Java Persistence Query Language (or JPQL for short). JPQL is an object-oriented query language and it is part of the JPA specification.

The technologies mentioned above will be demonstrated on a practical example. The goal of this example was to develop an application called Publication Database (or pubDB for short), which should store publications (articles and books) in a relational database and query the database as needed using the technologies mentioned above.

This term paper is organized as follows: after a brief introduction, four chapters will be presented. The first will briefly introduce the reader to the EJB 3 technology, and the remaining three will focus on the example. The second chapter will introduce the ER-model of pubDB. The third will show the inner details of the implementation itself, focusing on the persistence tier. The fourth chapter will demonstrate the application in action, explaining how it is used, with a number of screen-shots to better visualize the functionality of the application. The paper concludes with a brief conclusion.

To develop the application, a number of other applications were used. For the development environment, the free and open Eclipse IDE was used (version: Helios Service Release 1 v3.6.1) <http://www.eclipse.org/>. As an application server, the free and open JBoss Application Server v5.1.0.GA from Red Hat was used <http://www.jboss.org/jbossas>. For the relational database server, the freely available MySQL Community Edition v5.5.10 from Oracle Corporation was used <http://www.mysql.com/products/community/>. For the management and querying of the MySQL server, the freely available MySQL Workbench v5.2.33b from Oracle Corporation was used <http://www.mysql.com/products/workbench/>. Finally, for the creation of the application's GUI, the free WindowBuilder Pro v0.9.0 from Google was used (as a plug-in of the Eclipse IDE) <http://code.google.com/javadevtools/wbpro/>.

All diagrams in this paper were created using BOUML v4.23 patch 4, the freeware UML 2 modeling tool, and LibreOffice Draw v3.3.2, the free and open drawing tool. The homepages of these projects can be found at <http://bouml.free.fr/> and <http://www.libreoffice.org/>, respectively.

5

Page 6: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most
Page 7: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

IntroductionEnterprise software is software used in organizations, such as in a business or government,

contrary to software chosen by individuals. Enterprise software is usually an integral part of an Information System. Some important characteristics of enterprise software are performance, scalability and robustness [Wikipedia contributors 2011]. There are many competing technologies which can be used to develop an enterprise software, like OMG's CORBA or Microsoft's .NET. One of the major players in this field is also Enterprise JavaBeans (or EJB for short) developed by Sun Microsystems (now owned by Oracle). EJB is a server-side component architecture technology for the Java platform, enabling rapid and simplified development of applications based on Java technology [Oracle 2011].

This term paper was written to demonstrate some possibilities of EJB technology, namely the persistence of data in databases. In EJB, this piece of technology is called Java Persistence API (or JPA for short). JPA is a framework managing relational data in applications using the Java platform. In order to achieve this functionality, JPA (and other similar technologies) use the Object-Relational Mapping (or ORM for short) technique for converting data between incompatible type systems in object-oriented programming languages (in this case, between Java and a relational database). With this technique, a developer can manage data stored in a database as pure objects. Lastly, to query the database, an ORM-friendly query language must be used: Java Persistence Query Language (or JPQL for short). JPQL is an object-oriented query language and it is part of the JPA specification.

All these technologies will be explained in a little more detail in the next chapter, which is devoted to EJB.

7

Page 8: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most
Page 9: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Introducing EJB 3Generally speaking, Enterprise JavaBeans (or EJB for short) is a platform for building

portable, reusable and scalable business applications using Java. It's a component model or framework that can be used to build enterprise Java applications without the need to reinvent some commonly used services such as transactions, security, persistence, etc.

In this chapter, the reader can learn more about EJB 3 before moving on towards other chapters. The chapter starts with a little background story about various releases of EJB, continues with a general overview of the technology including EJB types and it concludes with a short variation of the HelloWorld example. This chapter is based mostly on chapter 1 of [Panda, Rahman& Lane 2007].

A Brief History About EJBIn contrast to popular claims, EJB was originally developed by IBM in 1997 and it was

clearly inspired by other technologies, mainly CORBA. Sun Microsystems adopted the EJB specification a year later. EJB had three main reincarnations so far: EJB 1.0 was released in 1998 and EJB 1.1 in 1999. The second reincarnation started in 2001 with EJB 2.0 and continued with EJB 2.1 in 2003. Finally, the third reincarnation came in 2006 with EJB 3.0. The most recent version is EJB 3.1 released in 2009. [Wikipedia contributors 2011]

The story behind these reincarnations is rather interesting. The initial goal of EJB 1 was to provide a simpler but innovative alternative to CORBA, but its functionality was rather limited. However, by the time EJB 2 was released, it has become more functional but way too heavy and far too complicated to be usable by developers. EJB's popularity was also decimated by Microsoft's .NET and more importantly, by the lightweight and open-source tools like SpringSource's Spring and JBoss' Hibernate. Clearly inspired by these lightweight projects, the goal of the new version of EJB was to become lightweight but also to retain the functionality of the older versions. When EJB 3 was released, it literally shocked the IT world. However, the revolution had its price: its specification was so different comparing to EJB 2 that it is considered that the two versions have very little in common.1 With new characteristics such as POJO-programming, Java 5 annotations (which replaced the verbose XML files), metadata programming, dependency injection, intelligent defaulting, and finally, ORM-like persistence with JPA, the previous statement is surely true.

Overview of EJB 3EJB is executed in a specialized runtime environment called the EJB container, which

provides a number of component services. At the other hand, persistence services are provided by a specialized framework called the persistence provider.

EJBs are components, because they encapsulate their inner behavior, so the “clients” of the components can use them without knowing anything about the inner details. The only thing they must know is what to pass in and what to expect back. EJB components are lightweight compared to heavyweight CORBA or COM+ components, because they are nothing more than a regular Java class called POJO (abbr. Plain Old Java Object). Lastly, they are reusable either as an EJB or as a

1 If we would need to find comparisons to the different reincarnations of EJB, a ladybug, an elephant and a cow would provide a rather good selection. EJB 1 could be referred as a ladybug, because of it's beauty but also because of it's limited power. EJB 2 could be seen as an elephant: it's very powerful, but at the other hand, it's way too heavy and hungry to be useful in all situations. Finally, EJB 3 could be referred as a cow: its functionality is first-rate, and because of its moderate size, it's usable in most situations.

9

Page 10: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

web-service.

EJB components live in a container. Together, these components and the container can be seen as a framework that provides valuable services for enterprise application development, such as managing application state, managing relational databases, managing transactions, implementing security, etc. By default, EJB provides these common services out-of-the-box, so there's no need to implement them from scratch. The container provides these services in a rather elegant way: with metadata annotations. These are used to mark specific parts of a class (such as a field or method) or the whole class with attributes. They were added with Java 5, and start with the @ character.

Because enterprise applications have a lot in common, it's no surprise that their architecture is also similar. Developers can build an enterprise application by following some common architecture principles. One of the most popular architecture is the traditional four-tier layered architecture. As the name suggests, this architecture has four layers. The first is the presentation layer which is responsible for rendering the graphical user interface (GUI for short) and managing user input. This tier passes down each request to the second layer, the business logic layer. This tier is the heart of the application and contains workflow and processing logic, such as actions and processes of the application. It also manages some kind of a database (e.g. saving and retrieving data). To achieve this, this layer utilizes the third tier, the persistence layer. This tier provides a high-level object-oriented abstraction over the database tier. Finally, the database layer typically consists of a relational database management system, such as Oracle, SQL Server, MySQL, etc. Of course, EJB naturally supports this architecture. However, it's obvious that EJB is not a presentation technology, so simple J2SE should be used for the first layer. Instead, EJB is all about robust support for implementing the business logic and persistence layers.

Before moving on to the next section, it would be useful to properly emphasize some strong points of EJB 3:

• Ease of use – EJB 3 is one of the simplest server-side development platform around, and it's learned fairly quickly. Features that emphasize this easiness are POJO-programming, metadata annotations, sensible defaults and JPA. Most used services work out-of-the-box, so the developer can focus on the application logic instead.

• Integrated solution stack – EJB 3 offers a complete stack of server solutions, like persistence, messaging, scheduling, remoting, web services, dependency injection (DI for short), etc. Also, EJB 3 is seamlessly integrated with other Java technologies, such as JDBC, Java Transaction API (JTA for short), Java Messaging Service (JMS for short), Java Naming and Directory Interface (JNDI for short), Java Remote Method Invocation (RMI for short). Also, Java presentation technologies such as Swing, JavaServer Pages (JSP for short) and JavaServer Faces (JSF for short) are also supported. This renders the need for other third-party technologies obsolete.

• Open Java EE standard – EJB is part of the Java EE standard. Because of this, EJB has an open and public specification, which organizations are encouraged to follow. Also, the EJB 3 standard was developed by the Java Community Process (JCP for short), which groups individuals and organizations.

• Broad vendor support – EJB is supported by a large number of organizations, such as IBM, and open-source groups such as JBoss. This creates a competing market, which allows users to choose from a wider selection of solutions.

• Stable, high-quality code base – because the majority of the vendors are long-time supporters and partners of Java and EJB, it guarantees that the quality of solutions will be very high, and also ensures their stability.

10

Page 11: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

EJB 3 TypesIn EJB-speak, a component is called a “bean”. In EJB, there are three types of components:

• Session Beans (SBs for short)

• Message-Driven Beans (MDBs for short)

• Entities

Naturally, each type has its purpose and can use only a specific subset of the EJB services. SBs and MDBs live in the EJB container, which manages them and provides services to them. They are used to build the business logic layer. In contrast, entities are used to model the persistence part of the application. However, they aren't managed by the container, but by the persistence provider.2

A session bean is invoked by a client for the purpose of performing specific business operations. The “session” name implies that a bean instance is available for the duration of a “unit of work”. There are two types of SBs: stateful and stateless. A stateful SB automatically saves the bean's state between client invocations. For example, the shopping cart of an E-business web-site which allows users to shop (and the cart will remember all items put in him during the shopping process), is a good example of a stateful SB. Another good example are wizards or questionnaires on web-sites spreading several pages. In contrast, a stateless SB doesn't maintain any state, instead, it models an application service that can be completed in a single client invocation. Checking the balance of the user's credit card is such an invocation. SBs can be invoked either locally or remotely via Java RMI. Also, a stateless SB can be exposed as a web-service. A developer can mark a POJO as a SB with the annotations @Stateless and @Stateful (depending on the type of the SB).

Message-driven beans also process business logic, just like SBs, but with a big difference: clients never invoke MDB methods directly. Instead, MDBs are triggered by messages sent to a massaging server. An E-commerce web-site sending massages to a shipping company's application to send the purchased articles from the warehouse to the buyer's address, would be a good example. A developer can mark a POJO as a MDB with the @MessageDriven annotation.

Entities are de facto Java objects that are persisted into a database. Persistence is the ability to have data contained in objects automatically stored in a relational database. Persistence in EJB 3 is managed by JPA by automatically persisting Java objects using a technique called ORM, which maps data held in objects to database tables. Another way to explain entities is that they are the OO representation of the database. Because entities are nothing more than POJOs, they fully support the OO principles, like defining relationships between entities (tables), inheritance and polymorphism. A POJO can be marked as an entity with the @Entity annotation.

In EJB 3, the persistence provider has three tasks: to manage the ORM configuration for mapping, to provide CRUD (abbr. Create, Read, Update and Delete) and persistence operations to entities (this is done by the EntityManager API), and to search and retrieve persisted data (this is done by the Java Persistence Query Language or JPQL for short). While entities know how they should be persisted, they aren't persisted by themselves. Instead, the EntityManager interface is assigned to actually provide persistence services. It knows how to add, update, delete or retrieve entities from the database. Additionally, JPQL is used to search for entities saved into the database. JPQL was clearly inspired by SQL, because of their similar syntax, but JPQL works with entities, not tables.3 Some JPQL queries will be presented in the third chapter.

2 It must be noted that EJB 2 had entity beans instead of the EJB 3 entities. That's because these entity beans were also managed by the EJB container. However, this added unnecessary complexity to them.

3 It's worth noting that JPA also supports native SQL queries if needed.

11

Page 12: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

The HelloUser ExampleTo demonstrate just how easy is to create a HelloWorld example in EJB 3, we'll include a

modified version of this example called HelloUser from [Panda, Rahman & Lane 2007].

package example;@Localpublic interface HelloUser { public void sayHello(String name);}

package example;import java.ejb.Stateless;

@Statelesspublic class HelloUserBean implements HelloUser { public void sayHello(String name) { System.out.println("Hello " + name + " welcome to EJB 3!"); }}

It seems unbelievable (especially to those experienced in EJB 2) but this code is an example of a perfectly valid EJB. As it can be seen, this is a stateless SB. A SB as a component must have at least one business interface, that's why an interface is also included. This code shows just how simplified EJB 3's programming model is. In fact, these classes are nothing more than regular objects and interfaces called Plain Old Java Objects (POJOs for short) and Plain Old Java Interfaces (POJIs for short). A POJO can be turned into a stateless SB with the @Stateless annotation. In addition, the POJI is marked with the @Local annotation4. These metadata annotations are part of the Java 5 specification and are heavily used in EJB 3. Earlier in EJB 2, developers were forced to write verbose XML configuration files for each component. These files were called as deployment descriptors. In EJB 3, the majority of the configuration can be done using annotations, rendering these descriptors more or less obsolete5.

One last feature of EJB 3 which was not mentioned in more detail is dependency injection. To access an EJB, EJB 2 used standard JNDI lookup, which was long and tedious. EJB 3 replaced it with metadata-based dependency injection (DI for short)6. For example, the @EJB annotation can “inject” EJBs transparently into an annotated variable, e.g. to access the HelloUser SB from another EJB, the following code can be used:

...@EJBprivate HelloUser helloUser;

void hello() { helloUser.sayHello("Robert");}...

This concludes the brief introduction of EJB 3. Starting from the next chapter, the main focus will be on the practical example. First, the database model must be presented.

4 This means that the SB will be used locally by a client collocated in the same container (JVM) instance. If the client is outside of the container instance, e.g. on a remote machine, the SB must be accessed remotely across the network via Java RMI. In that case, the @Remote annotation must be used. Finally, if the client isn't even written in Java, the SB can be exposed as a web-service with the @WebService annotation. A SB can have more than one interface.

5 However, a developer can continue to use deployment descriptors if that suits his/her needs better.6 Of course, the developer can continue to use JNDI lookups, and in some situations, it's unavoidable.

12

Page 13: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

The Model of the Practical ExampleWe will start the presentation of the practical example with the model of the information

system. Both the traditional Entity-Relationship model (ER-model for short) and object model will be shown.

The Publication Database (or pubDB for short) is a simplified information system storing and managing publications. As such, it's logical that the model of this system will have various entities, like publications, authors, categories to which these publications can belong, etc.

The ER-model of pubDB consists of seven entity-types: Author, Category, Publication, Article, Book, Journal and Publisher. An Author is uniquely identified by his or her identification or ID number, but there are also other attributes, like the author's first name, last name and biography. A Publication represents a generic publication. Each of them is uniquely identified by its ID number, but there are other attributes, too: the title of the publication, the year it was published and a description about the publication. An Author can write one or more Publications, but it's not necessary (as such, an Author can exist without a single written Publication). At the other hand, a Publication is written by at least one Author (a Publication cannot exist without a related Author).

A generic Publication must either be an Article or a Book. A Publication which is an Article, cannot be a Book, and a Book cannot be an Article. An Article, besides inheriting the common attributes of a Publication, such as an ID number, title, year of publication and description (for Articles, this should be the abstract), also has a unique attribute not available for Books: the Digital Object Identifier (DOI for short). At the other hand, a Book, besides inheriting the common attributes of a Publication (for Books, the publication description should be a review of the book), has some other unique attributes not available for Articles: the number of pages, the International Standard Book Number (ISBN for short) and a cover image.

An Article appears exclusively in a scientific Journal. An Article is published in exactly one Journal. An Article cannot exist without a related Journal. A Journal can consist of zero, one or more Articles. A Journal is uniquely identified by its ID number, but there are other references, like its title and volume.7 At the other hand, a Book is published by a Publisher company. Similarly as for Articles, a Book has exactly one Publisher. A Book cannot exist without a related Publisher. A Publisher can publish zero, one or more Books. A Publisher is uniquely identified by its ID number, but there are other references, too, like the name of the publisher and its address.

Lastly, all Publications should belong to a Category. A Publication must belong to exactly one Category. At the other hand, a Category can be related to zero, one or more Publications. A Category has only two attributes: its unique ID number and its label. However, the group of categories should be considered as a hierarchy. As such, a particular Category can be a parent category, a child category, none of them (if there is only one Category in the hierarchy), or even both. A particular Category can have one or more subcategories (children), but it's not necessary for the Category to have child categories at all. At the other hand, a Category can have zero or one parent, however, it's not allowed for a Category to have two parents.

7 Note that two different volumes of a journal are considered as two different entities in the Journal entity-type, e.g. the 24th and 25th number (volume) of the “IEEE Software” journal are two physically different journals.

13

Page 14: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

The ER-model of pubDB can be seen on Image 1. This model has some characteristics that should be noted:

• All relationships are bidirectional: an entity of an entity-type can always access it's related entities belonging to other entity-types.

• The majority of relationships are one-to-many, however, there is one many-to-many relationship (between Author and Publication).

• The relationship between Publication, Article and Book is modeled as a complete and disjoint IS_A hierarchy. It's complete because each instance of the Publication superclass belongs to at least one instance of a subclass (Article or Book). This means that the minimal cardinality should be 1. At the other hand, this hierarchy is disjoint, because each instance of the superclass can belong to at most one instance of a subclass. This sets the maximal cardinality to 1. In our case, this means, that a Publication must either be an Article or Book (there are no other possibilities), but a Publication cannot be both an Article and a Book at the same time.

• Most relationships are between two different entity-types, however, there is one particular relationship, which models a relationship between only one entity-type: Category. Also called a recursive relationship, it models a hierarchy of Categories. One particular category can have zero, one or more subcategories, and zero or one parent category.

Based on this ER-model, an object model can be created. The object model of pubDB can be seen on Image 2.

14

Image 1: The ER-model of pubDB

WritesAuthor(0, N)

Publication

Book

Category

Article

PublisherJournal

Belongs toHas

IS_A

Appears in

(1, N) (1, 1) (0, N)

(0, N)

(0, 1)

(1, 1)

(0, N)

(1, 1)

(0, N)

subcategory

(1, 1)

Published by

AUTHOR_ID

LAST_NAME FIRST_NAME

BIO

PUB_YEARPUB_ID PUB_TITLE

PUB_DESC

CAT_LABEL

CAT_ID

DOI

COVER

ISBN

PAGES

JOURNAL_VOL

JOURNAL_TITLE

JOURNAL_ID

PUB_ADDRESS

PUBLISHER_NAME

PUBLISHER_ID

Page 15: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

It would be tempting to see how this object model maps to the relational database. The result of this mapping can be seen on Image 3. This is an EER-model (abbr. Enhanced ER-model) that was automatically generated with MySQL Workbench. This diagram will be more interesting in the next chapter, when we present the persistence layer.

This concludes the chapter describing the model of the practical example. In the next chapter, the implementation of the Java application will be presented.

15

Image 2: The object model of pubDB

Author

idAuthor : string

lastName : string

firstName : string

biography : string

Publication

idPub : int

titlePub : string

yearPub : int

desc : string

Category

idCat : int

labelCat : string

Article

doi : string

Book

pages : int

isbn : string

cover : byte[]

Journal

idJournal : int

titleJournal : string

volume : string

Publisher

idPublisher : int

namePublisher : string

address : string

has

writes belongs to

appears inpublished by

subcategory

*

0..1

{complete,disjoint}

*1..* 1*

1

*

1

*

Page 16: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

16

Image 3: The EER-model of pubDB

Page 17: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

The Implementation of the Practical ExampleThe Publication Database (or pubDB for short) was developed utilizing the four-tier layered

architecture. This chapter will describe each tier by showing a class diagram for each of these layers, following by a short description of all classes. In some cases, parts of the source code will also be shown to demonstrate how these parts work. It must be emphasized that this term paper is about persistence, so it's not a surprise that the persistence tier will have the main focus. Of course, EJBs residing in the business logic layer should be also presented, but their priority will be only secondary. Lastly, as this term paper is not about presentation, we won't spend much time on the presentation tier.

The Persistence and Database LayerAs it was mentioned earlier, one task of the business logic layer is to manage some type of a

database. To achieve this, it must utilize the persistence layer, which provides a high-level object-oriented abstraction over the database tier. The database layer typically consists of a relational database management system.

PubDB uses MySQL as the database layer. Of course, this layer required no programming in Java, however, it needed some configuration, e.g. creation of a user (with user-name and password), creating a schema, and then assigning privileges to the newly created user to freely manage the new

17

Image 4: Showing the SQL Editor in MySQL Workbench

Page 18: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

schema. Every task involving the database was done in MySQL Workbench. However, this application was useful during the whole development process, because it accepts SQL queries, so it was also useful for testing (Image 4).

However, all other layers were created in Java with the Eclipse IDE. First, an Enterprise Application (EAR for short) project was made with projectEAR as its name, and JBoss v5.0 as its target runtime. An EAR is used to tie together one or more J2EE modules, including EJB modules.

When the EAR was created, it was time to create the persistence tier by creating a new JPA project with the name projectJPA. For this JPA project, it was important to add it to the newly created EAR.

The persistence tier has a single package called persistence. This package holds the EJB entities and each entity is a POJO with the @Entity annotation. Image 5 shows the class diagram for the persistence package. As it can be seen, the package has seven classes, which correspond to the seven entities mentioned in the previous chapter: Author, Category, Publication, Article, Book, Journal and Publisher. An observant reader will notice that the class diagram shown in Image5 is practically the same as the object model shown in Image 2. This is not a coincidence, because the object model shows a model in an OO way, and at the same time, EJB 3 entities model the object model in the same way, although they are Java classes.

In the remainder of this section, some implementation details with source code fragments will be given.

For example, let's see how the Author entity looks like. As the reader will notice, it's a completely regular Java class (i.e. a POJO) named Author.java, with some annotations to attach some additional functionality to the class.

18

Image 5: Class diagram of the persistence package

Author CategoryPublication

Article Book

Journal Publisher

persistence

Page 19: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

package persistence;import java.io.Serializable;import java.lang.String;import java.util.HashSet;import java.util.Set;import javax.persistence.*;import static javax.persistence.FetchType.LAZY;

@Entity // 1)@Table(name="AUTHOR") // 2)

@NamedQueries({ // 3) @NamedQuery(name = "findAllAuthors", query = "SELECT a FROM Author a"), @NamedQuery(name = "findAuthorByName", query = "SELECT DISTINCT a FROM Author a WHERE a.lastName LIKE :authorName OR a.firstName LIKE :authorName OR CONCAT(a.firstName, a.lastName) LIKE :authorName OR CONCAT(a.lastName, a.firstName) LIKE :authorName")})public class Author implements Serializable {

@Id @GeneratedValue @Column(name = "AUTHOR_ID") private int idAuthor; // 4) @Column(name = "LAST_NAME") private String lastName; @Column(name = "FIRST_NAME") private String firstName; @Lob @Basic(fetch = LAZY) @Column(name = "BIO") private String biography; // 5) @ManyToMany @JoinTable(name = "AUTHOR_PUBLICATION", joinColumns = @JoinColumn(name = "AP_AUTHOR_ID", referencedColumnName = "AUTHOR_ID"), inverseJoinColumns = @JoinColumn(name = "AP_PUB_ID", referencedColumnName = "PUB_ID")) private Set<Publication> publications; // 6) private static final long serialVersionUID = 1L;

public Author() { super(); }

public int getIdAuthor() { return this.idAuthor; } public void setIdAuthor(int idAuthor) { this.idAuthor = idAuthor; }

public String getLastName() { return this.lastName; } public void setLastName(String lastName) { this.lastName = lastName; }

19

Page 20: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

public String getFirstName() { return this.firstName; } public void setFirstName(String firstName) { this.firstName = firstName; }

public String getBiography() { return this.biography; } public void setBiography(String biography) { this.biography = biography; }

public Set<Publication> getPublications() { return publications; } public void setPublications(Set<Publication> publications) { this.publications = publications; }

public void addPublication(Publication publication) { // 7) if(publications == null) { publications = new HashSet<Publication>(); } publications.add(publication); }}

Some lines in the source code were marked with a number inside a commentary. Let's explain them:

1) As it was explained earlier, the @Entity annotation marks this POJO as an EJB entity. This is all that the developer needs to do to transform a POJO into an entity.

2) The @Table annotation specifies the table containing the columns to which the entity is mapped. The name parameter sets the name of the table in the relational database (in this case, it will be set to AUTHOR).8

3) The @NamedQuery annotation specifies a JPQL query. There are two types of a query: dynamic and named queries. Dynamic queries are created on the fly during runtime, so they are defined in class methods. Named queries, on the other hand, are defined in entities using the @NamedQuery annotation (and grouped with the @NamedQueries annotation if there are more of them). Named queries are used when a particular query is used many times in an application and it's always fixed. These queries are created before runtime, so they are faster than dynamic queries. The @NamedQuery annotation has two parameters. The name parameter sets the name of the query. Later, when the query will be needed, it's enough to call the query by its name. The query parameter contains the query itself. As it can be seen, JPQL is almost the same as native SQL, but it works with entities, not tables (additionally, the results of a JPQL query will be also entities). One more interesting part of a query is the expression beginning with the colon sign, e.g. :authorName. This is a parameter, which will be passed to the query by the method calling the query. We'll continue the discussion about queries later when we show the session beans.

4) After defining this POJO as an entity, it's time to define the fields of the class, which will

8 Note that the @Table annotation is entirely optional. If left out, the table will be named as the entity itself: Author.

20

Page 21: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

correspond as table columns in the database. Let's show the basic principles with the idAuthor field. This field has three annotations. The @Column annotation maps a persisted field or property to a table column. It has many parameters9, but the only one which is actually used here is the name parameter, which sets the name of the table column in the database (in this case, to AUTHOR_ID).10 This field also has an @Id annotation. This tells the database that this field will serve as a primary key to this table. Lastly, the @GeneratedValue annotation sets this primary key as synthetic11.

5) The biography field has some advanced annotations. The @Lob annotation (abbr. Large OBject) tells the database that this field will hold “heavy” objects, such as long textual strings, or even non-character type files like pictures.12 Because these items can be very big, it's recommended to optimize their retrieval by setting the fetch strategy in the @Basic annotation to FetchType.LAZY13.

6) Until now, we haven't discussed about relationships between entities (and tables). It's well known that there are three types of relationships: one-to-one, one-to-many and many-to-many. Here, the many-to-many relationship will be discussed. This is achieved with the @ManyToMany annotation. As it was defined earlier, there is a many-to-many relationship between an Author and Publication. This means that an Author can be connected to many Publications and vice versa. This is represented by the publications field, which type is Set<Publication> (i.e. a set of publications). Because many-to-many relationships don't exist in a relational database, the tables representing these entities must be joined with the help of a third table which will hold the IDs of both tables (e.g. an author with the ID 5 is connected to publications 21 and 44, etc.). In EJB 3, this is achieved with the @JoinTable annotation, which has three parameters. The name parameter defines the name of the third table. The joinColumns parameter defines, which field from this entity will be copied to the third table (in this case, the Author's identification field). The inverseJoinColumns parameter defines the same thing, but from the other table (in this case, the Publication entity, and its ID field). The last two parameters practically define the foreign keys of the third table (which will reference to the other two tables) and are defined with the @JoinColumn annotation with two parameters: the name parameter sets the name of the column in the third table, and the referencedColumnName parameter tells which column from the original table corresponds to this column in the third table. Note that there's no need to define the same thing on the other side of the relationship (i.e. in the Publication entity), but more about that later.

7) Finally, the addPublication(…) method is used to add publications to an author. This is a standard method for adding objects to collections, and it's widely used in one-to-many and many-to-many relationship type entities.

9 For example, whether the field is unique, nullable, insertable, updatable, etc.10 Similar to the @Table annotation, the @Column annotation can be omitted, too. In that case, the name of the table

column will be set as the name of the field itself: idAuthor.11 There are two primary key types: natural and synthetic. Natural keys model real-world identification properties. For

example, a person can be uniquely identified by an identity card number, a book can be identified by its ISBN, etc. However, these identifications are not safe, because they can be changed for some reason. Because of this, synthetic keys are better. They are automatically generated by the database itself with a number generator.

12 Long textual strings are called CLOBs (abbr. Character Large OBjects), and non-character files are called BLOBs (Binary Large OBjects). The @Lob annotation unites both LOB types, depending on the field type. CLOBs are represented as a String, and BLOBs as byte[]. As it can be seen, the biography field is a CLOB.

13 A lazy fetch will postpone the retrieval of this field for as long as possible. For example, when a user needs only the author's name, the persistence provider won't really retrieve the author's biography, only the author's name.

21

Page 22: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

To summarize, the Author entity is a simple POJO: it has a standard default constructor, some private fields, their getters/setters and some annotations. This is how an entity is created in EJB 3. It's not necessary to write annotations to the fields. EJB 3 has a feature called automatic table generation, however, it's not recommended to use it. It's always better to manually set the fields, but as it can be seen, it's fairly easy. One last thing to mention is that it's not necessary to add these annotations to fields, because they can be added to the getters/setters instead. Adding them to the fields is called field access, and adding them to getters/setters is called property access. It's up to the developer to choose, which style will be used, but it must be noted, that inside an entity, only one access type can be used.

Let's see how the Publication.java class is implemented next.

package persistence;

import javax.persistence.*;import static javax.persistence.DiscriminatorType.STRING;import static javax.persistence.FetchType.LAZY;import static javax.persistence.CascadeType.MERGE;

import … // some other standard imports

@Entity@Table(name="PUBLICATION")@Inheritance(strategy=InheritanceType.JOINED) // 1)@DiscriminatorColumn(name = "PUB_TYPE", discriminatorType = STRING, length = 1)@NamedQueries({ // 2) @NamedQuery(name = "findPublicationByTitle", query = "SELECT p FROM Publication p WHERE p.titlePub LIKE :pubTitle"), @NamedQuery(name = "findPublicationByYear", query = "SELECT p FROM Publication p WHERE p.yearPub BETWEEN :yearStart AND :yearEnd"), @NamedQuery(name = "findPublicationByAuthor", query = "SELECT DISTINCT p FROM Publication p INNER JOIN p.authors a WHERE a.lastName LIKE :authorName OR a.firstName LIKE :authorName OR CONCAT(a.firstName, a.lastName) LIKE :authorName OR CONCAT(a.lastName, a.firstName) LIKE :authorName"), @NamedQuery(name = "findPublicationByCategory", query = "SELECT p FROM Publication p INNER JOIN p.category c WHERE c.labelCat LIKE :categoryLabel")})public abstract class Publication implements Serializable { // 3) @Id @GeneratedValue @Column(name = "PUB_ID") private int idPub; @Column(name = "PUB_TITLE") private String titlePub; @Column(name = "PUB_YEAR") private int yearPub; @Column(name = "PUB_DESC") @Lob @Basic(fetch = LAZY) private String desc; @ManyToMany(mappedBy = "publications", cascade = MERGE) private Set<Author> authors; // 4) @ManyToOne(cascade = MERGE) @JoinColumn(name = "PUBLICATION_CAT_ID", referencedColumnName = "CAT_ID") private Category category; // 5)

22

Page 23: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

private static final long serialVersionUID = 1L;

public Publication() { super(); }

// getters/setters for the fields: idPub, titlePub, yearPub and desc

public Set<Author> getAuthors() { return authors; } public void setAuthors(Set<Author> authors) { this.authors = authors; }

public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; }

public void addAuthor(Author author) { // analogue to the addPublication(…) if(authors == null) { // method in Author.java authors = new HashSet<Author>(); } authors.add(author); }}

Similar to the previous class, some parts of the source code are marked with a number inside a commentary. Let's explain them:

1) Some readers will remember from the chapter where the model of pubDB was explained that the Publication entity forms an IS_A hierarchy relationship with the Article and Book entities. This is, in fact, an inheritance relationship. In EJB 3, to mark an entity as a superclass in the inheritance relationship, the @Inheritance annotation is used. Its strategy parameter defines which inheritance strategy will be used. There are three strategies: single-table (the default), joined-tables and table-per-class strategy.14 To set the strategy, set the parameter to InheritanceType.SINGLE_TABLE,

14 In the single-table strategy, all classes in the inheritance hierarchy are mapped to a single table, which must contain all data from all entities. This means that this table will contain columns that are common to all entities (the fields of the superclass), and columns that are specific to a particular entity (the fields of the subclasses). An additional column tells to which entity a particular table row belongs. This column is called a discriminator column. This strategy is fast and simple, but bloated, because the table will have many null values in the specific columns (e.g. the Book entity has a specific ISBN field, but since an Article cannot have an ISBN, the ISBN field will be empty for all articles).In the joined-tables strategy, one-to-one relationships are used to model OO inheritance. It creates separate tables for each entity in the OO hierarchy and relates direct descendants in the hierarchy with one-to-one relationships. In this case, the parent table contains only the common columns and a discriminator column. The child tables contain the columns that are specific to that particular child. This solves the column duplication problem of the previous strategy. Also, the joined-tables strategy is probably the best from a design perspective, however it's somewhat slower than the single-table strategy.Lastly, the table-per-class strategy creates tables for each entity in the hierarchy, but without any connection between them. Because of this, the tables must also contain some columns even if they are common, which results in column duplication (the specific columns, however, are not duplicated). This is the only strategy which doesn't use a discriminator column. This strategy is easy to understand, but it doesn't use any relational or OO features. Because of this, manipulating and querying data from the database is hard. Developers are advised to avoid this strategy when possible.

23

Page 24: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

InheritanceType.JOINED or InheritanceType.TABLE_PER_CLASS. As it can be seen, in this case, the joined-tables strategy was used. The discriminator column can be defined with the @DiscriminatorColumn annotation. This annotation has three parameters: the name parameter defines the name of the discriminator column in the parent table, the discriminatorType parameter defines which value type will be used for the discriminator column (in this case, it will be a string), and the length parameter tells the length of the string (in this case, one-letter strings will be used). The discussion about inheritance will continue later when we present the subclasses.

2) As it can be seen, this entity has four named queries. Most of them are fairly common, but the last two are a little more advanced. Namely, they join two tables with the INNER JOIN command. Similar to SQL, this joins two entities. For example, the query with the name findPublicationByCategory searches for all publications which belong to a particular category.

3) Observant readers surely noticed that this class is set to abstract. The reason should be obvious. Because this IS_A hierarchy is complete, each publication is either an article or a book. This means, that a publication cannot exist on its own. With the Publication class set to abstract, it prohibits any creation of a Publication object instance.

4) As we remember, the Author and Publication entities are connected with a many-to-many relationship. Both sides of the relationship should be marked, that's why the authors field is marked with the @ManyToMany annotation. However, as it was mentioned, there's no need to specify the details of the relationship on both sides. As the details were specified in Author.java, there's no need to specify them again. However, it must tell the persistence provider where is the other end of the relationship. This is achieved with the mappedBy parameter. It practically defines the “owning“ side of the relationship. In this case, it tells that the owner of this relationship is the publications field in the Author entity.15 The cascade parameter is also interesting. In databases, cascade operations are often used.16 EJB 3 also allows this feature. A developer can enable the cascade property for a specific EJB 3 persistence operation, or for all of them. As such, the cascade parameter can be set to CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.REMOVE or CascadeType.ALL. We will see some of these operations such as persist, merge or remove in the next section.

5) According to the model of pubDB, a Publication is not only related to an Author but also to a Category. While the relationship between Author and Publication is many-to-many, the relationship between Category and Publication is one-to-many. In EJB 3, this is represented with the @OneToMany and @ManyToOne annotations, depending on the side of the relationship. The category field is marked with the @ManyToOne annotation, because a publication can only belong to a single category. The specifics of the relationship are defined in the @JoinColumn annotation, similar to the many-to-many relationship. It tells that a column specified by the name parameter will be a foreign key which will refer to the primary key of the other entity specified by the referencedColumnName parameter. The other side of this relationship will be shown a little later.

15 Note that this relationship “owner” concept doesn't originate from domain modeling, but it's a convenient way to ease the specification of the relationship by defining the details only on the owning side. For many-to-many relationships, it's not important which side will be the owner.

16 Cascading means that an operation on an entity is also propagated to related entities. The most illustrative way to explain this is with the delete operation. Suppose that we want to delete an author and all related publications. By simply deleting the author entity, the related publications won't be deleted. However, by cascade deleting the author, all related publications will be also deleted. The same principle applies during cascade persisting or cascade updating.

24

Page 25: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

There are two subclasses of the Publication entity: Article and Book. It's enough to present only one of them, because they are rather similar. As Book.java is a little more interesting than Article.java, we will skip the presentation of the latter and will focus on the former instead.

package persistence;

import javax.persistence.*;import persistence.Publication;import static javax.persistence.FetchType.LAZY;import static javax.persistence.CascadeType.MERGE;

import … // some other standard imports

@Entity@Table(name="BOOK")

@DiscriminatorValue("B") // 1)@PrimaryKeyJoinColumn(name = "PUB_ID", referencedColumnName = "PUB_ID")@NamedQueries({ @NamedQuery(name = "findBookByISBN", query = "SELECT b FROM Book b WHERE b.isbn LIKE :isbn"), @NamedQuery(name = "findBookByPublisher", query = "SELECT DISTINCT b FROM Book b INNER JOIN b.publisher p WHERE p.namePublisher LIKE :publisherData OR p.address LIKE :publisherData OR CONCAT(p.namePublisher, p.address) LIKE :publisherData OR CONCAT(p.address, p.namePublisher) LIKE :publisherData")})public class Book extends Publication implements Serializable { // 2) @Column(name = "PAGES") private int pages; @Column(name = "ISBN") private String isbn; @Column(name = "COVER") @Lob @Basic(fetch = LAZY) private byte[] cover; // 3) @ManyToOne(cascade = MERGE) @JoinColumn(name = "BOOK_PUBLISHER_ID", referencedColumnName = "PUBLISHER_ID") private Publisher publisher; // 4) private static final long serialVersionUID = 1L;

public Book() { super(); }

// getters/setters for the fields: pages, isbn, cover and publisher

}

As usual, some parts of this source code are marked with a number inside a commentary. These will be explain next:

1) As it is known, the Book entity forms an IS_A hierarchy with Publication and Article, with Publication as the superclass. This is implemented with a simple inheritance. In a relational database, this type of relationship can be modeled with three different strategies, and as it is known, in this case, the joined-tables strategy was chosen. Some details were defined in

25

Page 26: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Publication.java, however, there is some work that needs to be done in the subclasses as well. First, a discriminator column value must be chosen for the subclasses. In Publication.java, this was defined as a one-letter string. As such, choosing the letter “B” for Books and “A” for Articles would be a logical choice. This is exactly what the @DiscriminatorValue annotation does. However, there is one more thing to be done: a foreign key should also be defined. In the joined-tables strategy, this is done with the @PrimarayKeyJoinColumn annotation. It's very similar to the @JoinColumn annotation. While @JoinColumn between two entities defines a foreign key where both entities will have a primary key and one entity will hold an additional foreign key (which references to the other entity's primary key), @PrimaryKeyJoinColumn defines a foreign key where only one entity will have a primary key, and the other will have only a foreign key referencing the first entity's primary key (and hence, this foreign key becomes this entity's primary key). The usage of this annotation is practically the same as the other annotation's. In this case, the Book entity will have a PUB_ID foreign key which references the primary key of the Publication entity (also called PUB_ID).

2) Because the Book entity is a subclass of Publication, it must extend the Publication object. However, this class is not abstract as the superclass. This means, that it's allowed to create instances of the Book object. The same applies to the Article entity.

3) The Book class also has a LOB field: cover. However, observant readers will notice that this field is not like the previous ones, which were CLOBs. The cover field is actually a BLOB (because of its type, which is byte[]), and it should hold a picture of the book's cover. From a developer's perspective, there's no difference between this BLOB and the previous CLOBs.

4) The Book entity is exclusively related to the Publisher entity (besides the Author and Category entity inherited from Publication). In this case, under exclusively we mean that the Article entity cannot be related to Publisher, however, the Article entity is exclusively related to the Journal entity instead. There is a one-to-many relationship between Publisher and Book. The annotations belonging to the publisher field clearly show this. Also note, that the relationship between the Journal and Article entities is also one-to-many.

It would be tempting to present the Publisher and Journal entities, however, both entities are fairly standard and all their features were seen already in previous entities. The Category entity, on the other hand, should be very interesting. We will present it next.

package persistence;

import javax.persistence.*;

import … // some other standard imports

@Entity@Table(name="CATEGORY")

@NamedQueries({ @NamedQuery( name = "findCategoryByLabel", query = "SELECT DISTINCT c FROM Category c WHERE c.labelCat LIKE :categoryLabel"), @NamedQuery( name = "findAllRootCategories", query = "SELECT c FROM Category c WHERE c.parent IS NULL")})

26

Page 27: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

public class Category implements Serializable { @Id @GeneratedValue @Column(name = "CAT_ID") private int idCat; @Column(name = "CAT_LABEL") private String labelCat; @OneToMany(mappedBy = "category") private Set<Publication> publications; // 1) @ManyToOne @JoinColumn(name = "PARENT_CAT_ID", referencedColumnName = "CAT_ID") private Category parent; // 2) @OneToMany(mappedBy = "parent") private Set<Category> subCategories; private static final long serialVersionUID = 1L;

public Category() { super(); }

// getters/setters for the fields: idCat and labelCat

public Set<Publication> getPublications() { return publications; } public void setPublications(Set<Publication> publications) { this.publications = publications; }

public Category getParent() { return parent; } public void setParent(Category parent) { this.parent = parent; }

public Set<Category> getSubCategories() { return subCategories; } public void setSubCategories(Set<Category> subCategories) { this.subCategories = subCategories; }

public void addSubCategory(Category category) { // analogue to the addPublication(…) method in Author.java }

public void addPublication(Publication publication) { // analogue to the addPublication(…) method in Author.java }}

As usual, here are the explanations of the numbered parts in the source code shown inside a commentary:

1) First, we remember that there is a one-to-many relationship between the Category and Publication entities. Earlier in the Publication entity, the category field was marked with the @ManyToOne annotation. This, however, means, that this end of the relationship will be marked with the @OneToMany annotation, because one category can be related to more publications. The only parameter that can be seen here is the mappedBy parameter. Similar to

27

Page 28: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

many-to-many relationships, it tells that the “owning” side of the relationship is the category field in the Publication entity.17

2) The Category entity also sports an interesting feature: this entity is in a relationship with itself, more precisely, it has a recursive relationship. This means, that a particular category can have a parent category, and it can also have child categories (or subcategories). However, in reality, this relationship is nothing more than a one-to-many relationship, with both ends residing in the same entity. This is clearly shown in the implementation. The parent field is of type Category, and it's marked with the @ManyToOne annotation, meaning that a particular category can have at most one parent. As usual, the @JoinColumn annotation defines the foreign key named as PARENT_CAT_ID which will reference CAT_ID. At the other hand, the subcategories field (which represents the other end of the relationship) is marked with the @OneToMany annotation with the usual mappedBy parameter. It must be also noted, that both fields (parent and subcategories) should have getters/setters.

Based on these mapping properties, EJB and JBoss AS will create the appropriate tables in the MySQL relational database. The result of this mapping was shown in the previous chapter, on Image 3. This diagram shows that the object and relational representation of the model is not the same (one obvious difference would be the relational representation of the many-to-many relationship), but EJB 3 manages all these differences on the fly, behind the scenes.

This concludes the presentation of the persistence layer. In the next section, the business logic layer will be described. This is the layer where session beans and message-driven beans live.

17 Unlike in many-to-many relationships, where it's not important which side of the relationship will be the “owner”, in one-to-many relationships, the relationship owner is always the field which is marked with the @ManyToOne annotation. This means, that the mappedBy parameter will always reside inside the @OneToMany annotation. In fact, specifying mappedBy inside the @ManyToOne annotation will result in a fatal error.

28

Page 29: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

The Business Logic LayerThe business logic layer is located between the presentation and persistence tier. It's

practically the heart of the application and contains workflow and processing logic, such as actions and processes of the application. At one hand, the presentation layer passes down user requests and data to it. Here, these requests are processed. These processes usually involve database management (such as CRUD (abbr. Create, Read, Update and Delete) and search operations). To achieve this, the business logic layer must communicate with the third tier, the persistence layer. The persistence tier persists or retrieves persisted data, passes it back to the business logic layer, which (after manipulating this data as necessary) passes it back to the presentation tier. It must be noted, however, that this is only a general idea about the usage of this layer.

The business logic layer is where session and message-driven beans live. In Eclipse, to create the business logic layer, a new EJB project must be created. In the case of pubDB, its name was set as projectEJB, the EJB module version was set to version 3.0, and it was added to the previously created EAR (named projectEAR), just like in the persistence tier earlier. The client JAR (abbr. Java ARchive) creation was disabled.

The business logic tier has only one package called buslogic. The classes of this package are simple POJOs and POJIs. Because the main focus of pubDB was to demonstrate the persistence tier, only the most basic EJBs were used in the business logic layer, that is, only stateless session beans. Unlike EJB entities, SBs consist of two parts: at least one business interface, and the

29

Image 6: The class diagram of the buslogic package

Page 30: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

implementation of this interface (or interfaces). The class diagram of the buslogic package can be seen on Image 6. This package has several SBs, one for each entity. Each SB groups together all operations involving a particular entity (e.g. the AuthorManager SB groups together all operations involving authors)18. As it can be seen, each SB has two business interfaces: a local and a remote. However, as it will be shown, the local interface is actually never used, and it was included only for the sake of completeness.19

In the remainder of this section, some implementation details with source code fragments will be given.

For example, let's see some implementation details of the AuthorManager SB. First, the remote business interface will be shown, which is called AuthorManagerRemote.java.

package buslogic;

import java.util.List;import javax.ejb.Remote;

@Remote // 1)public interface AuthorManagerRemote {

void addAuthor(String lastName, String firstName, String biography); // 2) void updateAuthor(int idAuthor, String lastName, String firstName, String biography); // 3) void deleteAuthor(int idAuthor); // 4) List<Object[]> populateAuthorList(); // 5) List<String> retrieveAuthor(int idAuthor); // 6) List<Object[]> findAuthor(String authorName); // 7)}

As it can be seen, the business interface is pretty straightforward. It lists the methods (or services) of this SB, according to the principles of components. The numbered parts inside a commentary will be explained next:

1) To mark this POJI as a remote interface of a SB, the @Remote annotation is used.20

2) The addAuthor(…) method, as its name suggests, adds an author to the database.

3) The updateAuthor(…) method updates an already persisted author in the database. The author is identified by his or her ID number.

4) The deleteAuthor(…) method deletes an author from the database.

5) The populateAuthorList() method is used strictly by a GUI component (more precisely, a JList component). It finds all authors in the database, returns the results back to the GUI, which populates the JList with data from the results.

6) The retrieveAuthor(…) method finds a particular author by his or her ID number.

7) Finally, the findAuthor(…) method searches the database for authors by his or her name.

18 With the exception of PublicationManager which groups together the operations involving the subclasses of Publication: Article and Book.

19 It can be asked, why was only the remote interface used. Although all layers of pubDB were developed on a single developer machine, which should imply that the usage of the local interface should be enough, the remote interface was used instead to demonstrate the use of JNDI.

20 The AuthorManagerLocal POJI is exactly the same as AuthorManagerRemote, the only difference is that it's marked with the @Local annotation instead. To transform a POJI into a web-service, the @WebService annotation should be used.

30

Page 31: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Let's show now the implementation of this business interface. It's called AuthorManager.java and implements both the AuthorManagerRemote and AuthorManagerLocal interfaces.

package buslogic;

import java.util.ArrayList;import java.util.Iterator;import java.util.List;import javax.ejb.Stateless;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;import javax.persistence.Query;

import persistence.Article;import persistence.Author;import persistence.Book;import persistence.Publication;

@Stateless(mappedName = "authorManager") // 1)public class AuthorManager implements AuthorManagerRemote, AuthorManagerLocal {

@PersistenceContext protected EntityManager em; // 2)

public AuthorManager() { // default constructor }

public void addAuthor(String lastName, String firstName, // 3) String biography) { Author author = new Author(); author.setLastName(lastName); author.setFirstName(firstName); author.setBiography(biography); em.persist(author); }

public void updateAuthor(int idAuthor, String lastName, String firstName, String biography) { // 4) Author author = em.find(Author.class, idAuthor); author.setLastName(lastName); author.setFirstName(firstName); author.setBiography(biography); em.merge(author); }

public void deleteAuthor(int idAuthor) { // 5) Author author = em.find(Author.class, idAuthor); em.remove(author); }

public List<Object[]> populateAuthorList() { // this method isn't a general CRUD operation, but a specific one needed // by a JList GUI component, and as such, its details will be omitted }

31

Page 32: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

public List<String> retrieveAuthor(int idAuthor) { Author author = em.find(Author.class, idAuthor); List<String> authorData = new ArrayList<String>(); // now fill the List with data from the retrieved author and return it }

public List<Object[]> findAuthor(String authorName) { // 6) Query query = em.createNamedQuery("findAuthorByName"); query.setParameter("authorName", authorName); List list = query.getResultList(); List<Object[]> authorList = new ArrayList<Object[]>();

Iterator<Author> it = list.iterator(); Author author; while(it.hasNext()) { author = it.next(); // populate authorList with the author's data

// finally, get the publications that are related to this author for(Publication publication : author.getPublications()) { if(publication instanceof Article) { // this Publication is an Article } else if(publication instanceof Book) { // this Publication is a Book } } // final preparation of authorList } return authorList; }}

Let's explain the numbered parts inside a commentary to better understand how CRUD operations were in EJB 3:

1) To mark a POJO as a stateless SB, the @Stateless annotation is used. The mappedName parameter is used by vendors to assign the given string as a global JNDI name for the EJB. The client will find this EJB by looking up the authorManager name.

2) In an EJB, the first step to performing any persistence operations is obtaining an instance of an EntityManager. This can be done by injecting the instance using the @PersistenceContext annotation.21

3) A standard create CRUD operation can be seen in the addAuthor(…) method. It creates a new instance of the Author entity and fills it with data (using the public setter methods defined in Author.java). At the end, it persists (adds) this Author instance to the database by calling the persist(…) method of the EntityManager's em instance.

4) The updateAuthor(…) method shows a standard update CRUD operation. Of course, first it needs to find the author by his or her ID number. In EJB 3, there's no need to write a standard query for this basic purpose. Instead, the find(…) method of the EntityManager should be used. This method has two parameters: the first specifies the type of the

21 Typically this is all a developer needs to do to get an instance of EntityManager. All EntityManager instances injected with the @PersistenceContext annotation are managed by the EJB container. This means that the container takes care of the cumbersome task of looking up, opening and closing the EntityManager behind the scenes. Of course, a developer can choose to manage it manually. In that case, the EntityManager is not container-managed, but application-managed.

32

Page 33: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

retrievable entity (in this case, Author.class), and the second specifies the entity's primary key. The EntityManager searches for the author by the given primary key (his or her ID), and returns it as an entity instance of type Author. After this, the data of the retrieved author is changed. However, at the end, instead of calling the persist(…) operation, the merge(…) operation is called. This only updates the already existing entity.

5) The deleteAuthor(…) method shows a pretty straightforward delete CRUD operation. First it must find the deletable author, and then it removes the entity from the database with the remove(…) operation of EntityManager.

6) The findAuthor(…) method which searches the database for authors by their name, is a little more complicated. This is the first method that uses queries. As it can be seen, it uses the findAuthorByName named query. Using a named query is pretty simple: call the createNamedQuery(…) operation from EntityManager and pass the name of the named query as its parameter. The EntityManager will prepare the query and store it as a Query object.22 The next step is to set the query parameters. As we recall, this query is defined in Author.java and looks like this: SELECT DISTINCT a FROM Author a WHERE a.lastName LIKE :authorName OR a.firstName LIKE :authorName OR (…). In this query, :authorName is a query parameter.23 This parameter must be replaced by a real value before executing the query. This is achieved with the setParameter(…) operation of Query, which has two parameters: the first identifies the query parameter, and the second sets it with a real value. Note that if a particular query has two or more different query parameters, the developer needs to call the setParameter(…) method as many times as there are different parameters. The final step should be to execute the query by calling the getResultList() method of Query. The result will be stored in a List (if no results were found, the list will be empty). The rest of the findAuthor(…) method is not really important for this demonstration. Basically, the method needs to return a list populated with data from the result list. To walk through the list which was returned by getResultList(), an Iterator should be used, or a “for each” loop. One more interesting detail of this method is the effective use of OO polymorphism. As it is known, the Author entity is in a relationship with the Publication entity, however, a publication should either be an Article or Book. Publications that are related to a particular author can be retrieved through Author's publications field (more precisely, through its getter method author.getPublications()). The returned entities are of type Publication, but because EJB 3 fully supports polymorphism, we can detect the real type of the entity with the instanceof operator (e.g. if(publication instanceof Article)).

We will discuss the PublicationManager SB next. As it was mentioned, this SB groups together all operations involving articles and books (which are subclasses to Publication). First, we will briefly skim through the remote interface, PublicationManagerRemote.java.

22 To use a dynamic query instead of a named query, the createQuery(…) method should be used, with a string parameter containing the JPQL query string.

23 There are two types of query parameters in JPQL. Query parameters starting with a colon (e.g. :authorName) are called named parameters, because they are identified by their name. However, query parameters starting with a question mark followed by a number are called positional parameters (e.g. SELECT a FROM Author a WHERE a.lastName LIKE ?1 AND a.firstName LIKE ?2). These parameters are replaced in the setParameter(…) method by putting the position number as the first parameter of the method (e.g. query.setParameter(1, “Smith”)). However, positional parameters are error-prone, so the developer should use named parameters when possible.

33

Page 34: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

package buslogic;

import java.util.List;import javax.ejb.Remote;

@Remotepublic interface PublicationManagerRemote { void addArticle(String title, int year, String desc, List<Integer> authors, String categoryLabel, String doi, int idJournal); void addBook(String title, int year, String desc, List<Integer> authors, String categoryLabel, int pages, String isbn, byte[] cover, int idPublisher); void updateArticle(int idArticle, String title, int year, String desc, String doi, String category, Integer idJournal, List<Integer> authors); void updateBook(int idBook, String title, int year, String desc, int pages, String isbn, byte[] cover, String category, Integer idPublisher, List<Integer> authors); void deleteArticle(int idArticle); void deleteBook(int idBook); List<String> retrieveArticle(int idArticle); List retrieveBook(int idBook); List<Object[]> findPublicationByTitle(String pubTitle); List<Object[]> findPublicationByYear(Integer yearStart, Integer yearEnd); List<Object[]> findArticleByDOI(String doi); List<Object[]> findBookByISBN(String isbn); List<Object[]> findPublicationByAuthor(String authorName); List<Object[]> findPublicationByCategory(String categoryLabel); List<Object[]> findArticleByJournal(String journalTitle); List<Object[]> findBookByPublisher(String publisherData);}

As it can be seen, this interface defines methods for adding, updating, deleting and retrieving articles and books. The rest of the interface lists methods used for searching articles and/or books by providing various kinds of information, like the publication's title, the article's DOI or book's ISBN. Some of them even join two entities (e.g. find all publications written by an author, etc.).

One specific detail about publications, articles and books is that when they are created, they must be simultaneously connected to their related entities: to author(s), to a category and to a journal (it it's an article) or publisher (if it's a book). This fact complicates the SB methods considerably. Let's see some of the methods of PublicationManager.java.

public void addArticle(String title, int year, String desc, List<Integer> authors, String categoryLabel, String doi, int idJournal) {

Article article = new Article(); article.setTitlePub(title); article.setYearPub(year); article.setDesc(desc); article.setDoi(doi);

// create the relationships with Authors Iterator<Integer> it = authors.iterator(); Author author; int idAuthor; while(it.hasNext()) { idAuthor = it.next().intValue(); author = em.find(Author.class, idAuthor); article.addAuthor(author); author.addPublication(article);

34

Page 35: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

}

// create the relationship with the Category Category category = (Category)em.createNamedQuery("findCategoryByLabel") .setParameter("categoryLabel", categoryLabel).getSingleResult(); article.setCategory(category); category.addPublication(article);

// create the relationship with the Journal Journal journal = em.find(Journal.class, idJournal); article.setJournal(journal); journal.addArticle(article);

em.persist(article); // add the Article to the database }

This method creates an Article and adds it to the database. The first part of the method is pretty straightforward: it sets the basic fields of the entity from data passed down as parameters (like setting the article's title, year of publication, DOI, etc.). The interesting part starts when it must also set the relationships with other entity types. However, it can be seen that setting the relationships are fairly easy, because it only involves the calling of the corresponding setter (starting with the set word, e.g. setCategory(…)) or helper methods (starting with the add word, e.g. addAuthor(…)). It must be noted, however, that the relationship must be set on both sides of the relationship, for example, to connect an Article with an Author, the author must be added to the article with article.addAuthor(author), and then the article must be added to the author with author.addPublication(author). When all relationships are defined, the article can be persisted to the database.

Deleting an article from the database is also more complicated, because it's connected to other entities. This is how the deleteArticle(…) method looks like.

public void deleteArticle(int idArticle) { Article article = em.find(Article.class, idArticle);

// first remove the relationship with the Category Category category = em.getReference(Category.class, article.getCategory().getIdCat()); category.getPublications().remove(article); article.setCategory(null);

// then remove the relationship with the Journal Journal journal = em.getReference(Journal.class, article.getJournal().getIdJournal()); journal.getArticles().remove(article); article.setJournal(null);

// lastly, remove the relationship with the Authors for(Author author : article.getAuthors()) { author.getPublications().remove(article); } article.getAuthors().clear();

// finally, delete the Article // must use the merge() method first to update all references em.remove(em.merge(article)); }

35

Page 36: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

While adding an article required to also set up the relationships before persisting it to the database, deleting an article requires to remove the relationships prior to deleting it from the database. In fact, trying to delete an article with the relationships intact will result in errors and exceptions during runtime. Thankfully, removing the relationships is easy. The method can be divided into three steps: first find the article to be deleted (using the find(…) method), then remove the relationships (with the category, journal and the authors), and finally, delete the article using the remove(…) operation. Before calling the remove(…) method, the references should be updated first, that's why the article is first updated with the merge(…) operation, and then removed.24

The updateArticle(…) method is a little more complicated, because it supports not only the update of the article's data, but also its relationships. In a way, its management of relationships is a combination of the last two described methods: it needs to remove the old relationships first and then it must add the new ones. The other methods of PublicationManager.java also work similarly to the methods already shown in AuthorManager.java.

The remaining SBs (JournalManager, PublisherManager and CategoryManager) are very similar to the already presented SBs. JournalManager and PublisherManager are similar to AuthorManager. CategoryManager, on the other hand, is more similar to PublicationManager, because it also has a twist: recursive relationship. If the reader has already a good grip on managing relationships during CRUD operations, it shouldn't pose a problem. There is, however, a peculiar feature in Category management. Namely, when the user deletes a category from the database, what will happen with its subcategories? To answer this question, the deleteCategory(…) method from CategoryManager.java must be shown.

public void deleteCategory(String label) { Category categoryToDelete = (Category)em.createNamedQuery("findCategoryByLabel") .setParameter("categoryLabel", label).getSingleResult(); Category categoryParent = categoryToDelete.getParent();

// must remove the relationships (with parent and children) first categoryToDelete.setParent(null); if(categoryParent != null) { categoryParent.getSubCategories().remove(categoryToDelete); } for(Category categoryChild : categoryToDelete.getSubCategories()) { categoryChild.setParent(categoryParent); if(categoryParent != null) { categoryParent.addSubCategory(categoryChild); } } categoryToDelete.getSubCategories().clear(); // HashSet.clear()

// now delete the Category em.remove(em.merge(categoryToDelete)); }

Observant readers will surely find out the answer to the previous question just by checking out this code. One answer to the question should be to also delete the subcategories, when their parent is deleted. However, in this case, the children will be preserved by relinking them to their

24 One more interesting operation should be the getReference(…) method of EntityManager. This method is practically the same as the find(…) method, with one important difference: while the find(…) method returns the whole entity with all its data at once, the getReference(…) method returns only the entity's reference first. As such, it's much lighter and faster. It's used when we don't really need to manipulate with the entity. It's practically a lazy retrieval, as the data of the entity will be retrieved only when really needed.

36

Page 37: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

“grandparent” instead. Of course, if the parent to be deleted is a root category (meaning that the category has no parent), then it's obvious that the children have no “grandparent”, and as such, they should become root categories. This is clearly shown in the source code, too.25

This concludes the discussion about the business logic layer. In the last section of this chapter, the presentation tier will be presented.

25 The deleteCategory(…) method also has two more interesting details. The first is the grouping of operations in one line (createNamedQuery(…).setParameter(…).getSingleResult()). This grouping is perfectly legal, and it could be used in previously shown methods, too, but it's somewhat harder to understand, so it was omitted previously. The second peculiarity is the getSingleResult() method of Query. This operation is similar to getResultList(), but it returns only a single result (as such, the type of the returned result will be the type of the entity itself, not a List). The reader should be warned, however, that it's also more restrictive. The getResultList() method returns a List with zero, one or more elements (results). The getSingleResult() method, on the other hand, returns only a single entity. Because of this, finding more than one entity matching the search, or finding no entities, will result in a NonUniqueResultException or NoResultException, respectively.

37

Page 38: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most
Page 39: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

The Presentation LayerThe presentation layer is the top layer of the four-tier layered architecture. It's practically the

client tier, because usually only clients use it. It's responsible for rendering some kind of a graphical user interface (GUI for short), i.e. the front end of the application. Its task is to interact with the user, acknowledge the user's requests, collect required data, and pass it all down to the business logic layer for processing. It's also responsible for displaying information which was returned from the business logic layer.

This layer is typically written in a language with presentation technology support. In the world of Java, there are many such technologies, such as Swing, SWT, JSP, JSF, etc. In the case of pubDB, the Java J2SE Swing technology was used. To create this layer in Eclipse, creating a new Java project with projectClient as its name will suffice.

The presentation layer has two packages. The gui package contains the Swing graphical components, like windows and dialogs. This package is responsible for interacting with the user, collecting user requests and data, and also displaying information that was returned from the business logic layer. However, the classes of this package don't directly interact with the business logic layer. Instead, they communicate with the classes of the second package, agency. This package serves as an agent, mediator or middleman between the presentation layer's GUI and the business logic layer's EJBs. So, in reality, the GUI never actually communicates with EJBs, and vice versa. This design choice was made to somewhat simplify the GUI, and to further separate it from the business logic layer. The class diagram of these packages can be seen on Image 7.26

As this term paper is not about presentation, we won't present implementation details from the gui package. It's sufficient to say that the main class of the gui package, and the whole client layer is MainWindow.java. This class has a main method, so the whole client starts with this class. The other classes are practically various dialogs that are called from MainWindow.java, or from other dialogs. These classes have a Dialog suffix in their names.27 Additionally, one class serves as a helper class: ComponentFactory.java. This class is practically a factory class, i.e. it creates some specific Swing components that are frequently used across the GUI. For example, if the GUI frequently uses a button with fixed dimensions, color and text, it would be a good choice from a design perspective to move the creation of this button to a factory class and pre-customize it, so when a dialog needs a button like that, it calls the factory to create the button instead. Also, this avoids code duplication, because dialogs don't need to customize the button every time when it's needed.

One more thing to mention about these dialog classes is that they are parametrized (except SearchDialog.java). Their constructor, that creates and sets up the dialog has one parameter. These dialogs can function in two “modes”: add mode and view/update mode. The dialog works in add mode when the parameter is null. In this case, the user can add a new entity (such as an author, category, journal, publisher, article or book) into the database. On the other hand, the dialog will work in view/update mode when a valid parameter containing the entity's ID is provided. In this mode, the user can view an existing entity retrieved from the database, and even update its data. In 26 It should be mentioned that there are two more additional packages in the presentation layer: img and test. The

img package is practically a folder to images and pictures needed for the GUI, and as such, it doesn't contain Java classes. The test package is a package which was in use in the development phase. It contains only one Java class, which was used for testing in the command prompt. However, because neither of these packages are important, it was decided to omit them completely.

27 Honestly, not just MainWindow.java has a main method, but all dialogs, too (classes with the Dialog suffix, e.g. AuthorDialog.java). However, a user should never start the application from a dialog. The reason that these dialogs have a main method is a choice made by WindowBuilder Pro, the tool which was used to create pubDB's GUI.

39

Page 40: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

this case, the dialog transforms a little: all data fields will be filled with the entity's data, the Add button will change to Update, etc. We will see this more closely when we'll show the application in action.

From the aspect of EJB 3, it's more interesting to show the inner details of the agency package. As it was told, the GUI uses this package to communicate with the SBs in the business logic layer. As such, it functions more like an agent, mediator or middleman between them. This package consists of the mediator itself called Agent.java and several helper classes to aid this class. Let's see portions of Agent.java to see how it works.

package agency;

import javax.naming.NamingException;

import … // some other imports

public class Agent {

public static void addAuthor(String lastName, String firstName, String biography) { try { AuthorSession.getAuthorManager().addAuthor( lastName, firstName, biography); } catch (NamingException e) { e.printStackTrace(); } }

40

Image 7: Class diagram of the gui and agency packages

Page 41: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

public static void updateAuthor(int idAuthor, String lastName, String firstName, String biography) { try { AuthorSession.getAuthorManager().updateAuthor( idAuthor, lastName, firstName, biography); } catch (NamingException e) { e.printStackTrace(); } }

public static void deleteAuthor(int idAuthor) { try { AuthorSession.getAuthorManager().deleteAuthor(idAuthor); } catch (NamingException e) { e.printStackTrace(); } }

public static List<String> retrieveAuthor(int idAuthor) { try { return AuthorSession.getAuthorManager().retrieveAuthor(idAuthor); } catch (NamingException e) { e.printStackTrace(); return null; } }

public static List<Object[]> populateAuthorList() { try { return AuthorSession.getAuthorManager().populateAuthorList(); } catch (NamingException e) { e.printStackTrace(); return null; } }

public static List<Object[]> findAuthor(String authorName) { String revisedAuthorName = reviseSearchString(authorName, true); try { return AuthorSession.getAuthorManager().findAuthor(revisedAuthorName); } catch (NamingException e) { e.printStackTrace(); return null; } }

private static String reviseSearchString(String searchString, boolean areTwoFields) { String revisedSearchString = "%"; revisedSearchString = revisedSearchString.concat(searchString); revisedSearchString = revisedSearchString.concat("%"); if(areTwoFields) { revisedSearchString = revisedSearchString.replace(' ', '%'); } return revisedSearchString; }

// all other methods involving categories, journals, publishers, articles and // books}

41

Page 42: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

In this class, all calls to SBs in the business logic layer are grouped together. However, for demonstration purposes, it's sufficient to show only the calls towards the AuthorManager SB, and calls toward the other SBs (like CategoryManager, PublicationManager, etc.) are omitted. Also, as it can be seen, all methods of this class are static.

Let's explain, how SBs can be used from a non-J2EE (that is, J2SE) environment. Observant readers will notice that practically all methods of Agent.java use the same methodology, so it's sufficient to demonstrate this on only one method, for example on the addAuthor(…) method. Simply speaking, this method gets a reference to the AuthorManager SB, and calls its addAuthor(…) service (that is, method). To get a reference to AuthorManager, the method uses a helper class from the agency package called AuthorSession.java. Let's see how this class looks like.

package agency;

import javax.naming.Context;import javax.naming.InitialContext;import javax.naming.NamingException;

import buslogic.AuthorManagerRemote;

public class AuthorSession {

private static AuthorManagerRemote sessionAM = null;

public static AuthorManagerRemote getAuthorManager() throws NamingException { if(sessionAM == null) { Context context = new InitialContext(); sessionAM = (AuthorManagerRemote) context.lookup("authorManager"); } return sessionAM; }}

As it can be seen, this class is very simple. To get a reference to the AuthorManager SB, the SB's remote interface will be used. This implies that JNDI must be used to get the actual reference. First, an instance of the JNDI initial context object must be obtained, which is of type InitialContext. An InitialContext object can be used to connect not just to a local JNDI server, but also to a remote one. After the JNDI initial context was obtained, its lookup(…) method should be called to actually get the reference of the SB. Its parameter should be the JNDI name of the SB. As we recall from AuthorManager.java, the name of this SB was set in the @Stateless annotation: @Stateless(mappedName = "authorManager"). So, by setting the parameter of the lookup(…) method to "authorManager", a reference of this SB will be obtained. Of course, the object that was obtained via JNDI must be cast to the appropriate type (in this case, to AuthorManagerRemote). It should be also noted that the lookup(…) method throws a NamingException.

We can return now to the Agent.addAuthor(…) method. In this method, after obtaining a reference to AuthorManager from AuthorSession, its services are ready to be called. In this case, the SB's addAuthor(…) method will be called. As it can be seen, this is all a developer needs to do to use a service of a SB. However, because the lookup(…) method throws a NamingException, the Agent.addAuthor(…) method must catch it. That's why all methods in Agent.java are surrounded with a try/catch block.

One more interesting detail about the Agent.java class is that is has a private method

42

Page 43: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

called reviseSearchString(…). This method is called from other Agent methods, more precisely, from search methods (starting with a find prefix, e.g. findAuthor(…)). The purpose of this method is to revise the text entered in GUI search text fields by a user. It adds some additional characters to the search string, namely the percentage “%” sign. In JPQL, the LIKE operator supports “joker marks”. Adding an underscore “_” sign to the string replaces one character on that place, e.g. specifying “_ike” will find “mike” “bike” or “like”. However, the percentage “%” sign can substitute a random number of characters, e.g. specifying “my%friend” will find “my friend”, but also “my good friend”, “my best friend” and “my only friend”. This method revises the search string by adding the “%” character at the beginning and the end of the string, and also by replacing any space characters with “%”. This improves the quality of the search considerably. For example, the “engineering” string will be revised to “%engineering%”, so besides finding “Engineering”, the search will also find “Software Engineering”, “Field Engineering” and “Engineering of Critical Systems”.

One can ask, is there a way to see the contents of JNDI, i.e. to see which objects are registered in JNDI and what is their name. Thankfully, JBoss allows this by accessing the JBoss Management Console called JMX Console, which provides a raw view into the microkernel of the

43

Image 8: The JMX Console

Page 44: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

JBoss AS. The console can be accessed by entering http://localhost:8080/jmx-console into a browser (of course, the JBoss Application Server must be started first). In the console, find the jboss category, and click on service=JNDIView. A new page similar to Image 8 should be displayed. There, find the list operation in the operations table and click on its Invoke button (in the Parameters column). The JMX MBean Operation View page will be displayed. In the list, browse down until you find Global JNDI Namespace. This is how a portion of it should look like:

… +- authorManager (class: Proxy for: buslogic.AuthorManagerRemote) +- categoryManager (class: Proxy for: buslogic.CategoryManagerRemote) +- publicationManager (class: Proxy for: buslogic.PublicationManagerRemote) +- publisherManager (class: Proxy for: buslogic.PublisherManagerRemote) +- journalManager (class: Proxy for: buslogic.JournalManagerRemote)…

As it can be seen, it also contains the SBs of pubDB (among many other names that are not important for us). For example, the authorManager name can be used to get a reference to AuthorManagerRemote. Note that specifying a nonexistent name will throw a NameNotBoundException during runtime.

This concludes the presentation of the implementation of this practical example. In the final chapter of this paper, it will be shown, how the example looks like when it is executed.

44

Page 45: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

The Practical Example in ActionIn this chapter, we will present the practical example, pubDB in action. However, the

application should be configured properly before executing. Because of this, this chapter has two sections: the first briefly explains how pubDB should be configured in a localhost environment, and the second shows the application itself.

Setting up and Configuring pubDBTo configure pubDB in a localhost environment, first the JBoss Application Server should be

configured with MySQL.28 In order to achieve this, JBoss AS needs a MySQL driver. This driver is called MySQL Connector/J, and it can be obtained from MySQL's website29. For pubDB, version v5.1.6 was used (named mysql-connector-java-5.1.6-bin.jar), however, at the time of writing this paper, the newest version should be v5.1.16. Nevertheless which version is used, the driver should be copied into the JBOSS_HOME/server/default/lib folder. The second task would be to configure the datasource. A datasource is used to configure the parameters for communicating with a specific database (in the case of pubDB, JBoss AS should communicate with MySQL). A datasource usually has some pretty basic parameters like name, host name, database name, user-name and password. The datasource file should be copied into the JBOSS_HOME/server/default/deploy folder. The datasource of pubDB is an XML file named mysql-ds.xml and should look like this:

<?xml version="1.0" encoding="UTF-8"?>

<datasources> <local-tx-datasource> <jndi-name>MySqlDS</jndi-name> <connection-url>jdbc:mysql://localhost:3306/seds</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>robi</user-name> <password>robi</password> <exception-sorter-class-name> org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter </exception-sorter-class-name> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource></datasources>

The user-name and password tags should be the user-name and password of the user which was created in MySQL (as mentioned earlier at the beginning of the previous chapter). The connection-url tag should be the address of the server, starting with jdbc:mysql://, following with the address itself (it's localhost here, but it can be a remote server on the network) and the port (usually 3306) separated with a colon, and finally the name of the schema itself (the creation of a schema was also mention at the beginning of the previous chapter) preceded with the “/” sign.

28 It should be mentioned that there is a bug in JBoss AS 5.1.0 GA that prevented the starting of the server for some versions of JDK as described at https://issues.jboss.org/browse/JBAS-6981. To solve this, edit the JBOSS_HOME\server\default\conf\bootstrap\profile.xml file. Find there the definition of AttachmentStore, and replace <constructor><parameter> with <constructor><parameter class="java.io.File">. The bug was fixed in JBoss AS v6.0.0.M1.

29 The driver can be downloaded from MySQL's website: http://dev.mysql.com/downloads/connector/j/

45

Page 46: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Now it's time to set up the JBoss server itself in Eclipse. First, a new server should be created in Eclipse, which can be done in the Server tab in the Java EE perspective. JBoss v5.0 should be selected as the server's type, localhost as the host name, 8080 as its port, and for the server's runtime environment the developer should find the folder where JBoss was unpacked.

Now that the server is set up, it's time to configure the EJB 3 deployment descriptor. It was mentioned in the introductory chapter about EJB 3, that deployment descriptors are practically never used (contrary to EJB 2). However, some basic configuration must be done. Of course, Eclipse modifies it as new entities are added to the persistence layer. The deployment descriptor is practically an XML file named persistence.xml and it can be found in Eclipse inside JPA Content of the JPA project (in the case of pubDB, projectJPA → JPA Content → persistence.xml). Besides manually editing the XML file, Eclipse provides a graphical interface for this purpose. In the Connection tab, the JTA data source field should be set to java:/MySqlDS (it's the name of the datasource configured earlier), and in the Properties tab, add the following two properties in the table: hibernate.hbm2ddl.auto (with update as its value) and hibernate.show.sql (with true as its value). These two properties set Hibernate as EJB's persistence framework and show the SQL queries in the debug console (the second property is not really necessary). In the Source tab, the developer can edit the file manually. Here's how it should look like (after adding all entities):

<?xml version="1.0" encoding="UTF-8"?><persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="projectJPA"> <jta-data-source>java:/MySqlDS</jta-data-source> <class>persistence.Author</class> <class>persistence.Publication</class> <class>persistence.Article</class> <class>persistence.Book</class> <class>persistence.Journal</class> <class>persistence.Publisher</class> <class>persistence.Category</class> <properties> <property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.show.sql" value="true"/> </properties> </persistence-unit></persistence>

Contrary to EJB 2's verbose deployment descriptor, EJB 3's descriptor looks very simple. Note, that Eclipse adds managed classes (in the class tag) automatically as new entities are created.

The last step in the configuration should be the configuration of the client. Select the main class which is used to start the application (in this case, MainWindow.java), right-click on it, and select Run As → Run Configurations. Select the Arguments tab and enter this in the VM arguments box:

-Djava.naming.factory.initial=org.jnp.interfaces.NamingContextFactory-Djava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces-Djava.naming.provider.url=localhost

With this, the configuration of pubDB is complete.

46

Page 47: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Starting pubDBPubDB can be started by first starting the created server in Eclipse, and then by running

MainWindow.java. The remainder of this section will show, how the application looks like, and how it is used. Several screen-shots will be inserted at various places to help the reader visualize the application.

Upon starting pubDB, the main window will be shown (Image 9) with several buttons to add a new entity to the database (new author, category, journal, publisher, article or book) and an additional button to search the database for already added entities. The lower part of the window show help messages to aid the user. When the user places the mouse cursor over a button, the help message automatically changes to show a text explaining the purpose of that particular button.

When the user clicks on the Add Author button, the Add New Author dialog appears (Image10). Here, the user can enter the author's first and last name, and optionally even his or her biography. To add an author to the database, the user must click on the Add button. It must be noted, that the author's first and last name must be provided prior to adding the author. If the user leaves one of these text fields empty, the application will display an error message (Image 11). Otherwise, the application will add the author to the database and close the dialog, returning the user back to the main window.

The Add Category button adds a new category into the database. In the Add New Category dialog (Image 12), the user must enter a label for the category (otherwise, an error message will be displayed) and select its parent from the tree. The root of the tree is called Root, and it's automatically selected. If the user doesn't specify a parent category from the tree, the application will assume that the user wants to add the category as a root parent category. Note, that the Root node of the tree is actually not a real category, however, its label is reserved. Because of this, if the user tries to add a category with Root as its label, an error message will appear explaining that the

47

Image 9: The main window of pubDB

Page 48: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Root label is reserved. There is one more restriction that must be mentioned: the label of the category should be unique, so, if a category with the same label already exists in the database, the new category won't be persisted and an error message will be displayed.

With the Add Journal button from the main window, the user can add a new journals to the database. In the Add New Journal dialog (Image 13), the user can enter the journal's title and volume. Filling out the journal's title is mandatory, an error message will be displayed otherwise. The Add New Publisher dialog is almost the same (opened by clicking on the Add Publisher button in the main window). Here, the user can enter the publisher's name (which is mandatory) and address (which is optional).

48

Image 10: The Add New Author dialog

Image 11: An Error message showing that the author cannot be added to the database

Page 49: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Clicking on the Add Article button in the main window will show the Add New Article dialog (Image 14). This dialog is more complex compared to the previous dialogs, because it offers more fields to be filled and because this is actually the dialog where an article should be linked with other entities, like author(s), a category and a journal. Because of this, before the Add New Article dialog is actually displayed, pubDB must retrieve all existing authors, journals and categories from the database. Once the dialog is displayed, the user can enter the article's name (mandatory), year of

49

Image 12: The Add New Category dialog

Image 13: Both the Add New Journal and Add New Publisher dialogs are very similar

Page 50: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

publication (mandatory), DOI (optional) and abstract (optional). Also, the user should select one or more authors from the Author(s) list30, one journal from the Journal combo box, and one category by clicking on the Select button. By clicking on this button, a small dialog will be displayed, where the user can select the adequate category for the new article (Image 15). Of course, prior to adding an article, the user can decide to add a new author, journal or category to the database directly from the Add New Article dialog by clicking on the corresponding Add buttons. Similarly, the already existing authors, journals and categories can also be viewed (and even updated if necessary) by clicking on the corresponding View buttons (the View button for categories is placed on the category chooser dialog (Image 15). If the user adds a new author, journal or category to the database, or updates an existing one, the corresponding list (for authors), combo box (for journals) and tree (for categories) will be automatically refreshed with new data. The dialogs responsible for viewing and updating these entities will be presented a bit later. The user can get error messages when the article's title and year of publication is not provided, when the user has forgotten to connect the article with an author (or authors), a category and a journal, or when the year of publication field is not a positive number.

Clicking on the Add Book button in the main window will show the Add New Book dialog. This dialog is very similar to the Add New Article dialog. Namely, the book's title, year of publication, author(s) and category is the same as for an article (its description is also the same, but it's now referred to as a review, not an abstract). However, there are some differences, too. For example, a book is connected to a publisher, not a journal (but the combo box looks the same

30 More authors can be selected by holding down the Control key on the keyboard while selecting them.

50

Image 14: The Add New Article dialog

Page 51: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

nevertheless). Additionally, a book cannot have a DOI, but it can have an ISBN, the number of pages, and a cover image. The cover can be selected by clicking on the Browse button. This opens a file selector dialog, where the user can browse the file system and select a JPG image. When the user clicks on the Open button, the picture is scaled down (or up) to a specific dimension and displayed on the screen. Of course, the user can click on the Browse button again to browse for another picture, or on the Remove button to remove the opened image from the cache. The restrictions explained in the Add New Article dialog also apply here, so if the user doesn't comply, error messages will be displayed.31

Finally, by clicking on the Search button in the main window, the Search dialog will be displayed. The dialog itself is divided roughly into two panels, the upper panel which is a tabbed pane, and the lower, where the search results are displayed. The tabbed pane has two tabs: in the first, the user can search for authors (by their name), categories (by their label), journals (by their title) and publishers (by their name and/or address). By selecting the second tab, the user can search for articles and books (by their title, year of publication, author or category), for specific articles (by their DOI or journal) and for specific books (by their ISBN or publisher). The user should select the type of the search by first selecting the appropriate radio button and then entering the search string into the appropriate text field.

By clicking on the Search button, the search process will commence querying the database, and the results (if any) will be displayed in a table in the lower panel (Image 16). The table has three columns: the first displays the entity's ID (primary key from the database), the second shows the entity's type (author, category, journal, publisher, article or book), and the third shows some basic information about the entity. The user can click on a row in the table to select an entity. When an entity is selected from the table, the user can decide to view it or to delete it. By clicking on the View button, the appropriate dialog will open, showing all information from the database. For example, if the user has selected an entity of type author, the author dialog will appear (Image 17). Observant readers will surely notice, that this dialog (which is named View and Update an Existing Author) is very similar to the Add New Author dialog. This is absolutely true, because only one dialog (and one Java class) is used for both adding and viewing. We mentioned earlier, that most dialog classes in pubDB are parametrized. Depending on the parameter, the dialog can function in two modes: add mode and view/update mode. By comparing Image 10 with Image 17, the following visual changes can be observed:

31 The only addition is that the Add New Book dialog will also check whether the entered number of pages is valid, that is, a positive number.

51

Image 15: The Category Chooser dialog

Page 52: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

• the fields are automatically filled with data retrieved from the database (in view/update mode);

• the dialog titles are different (Add New Author versus View and Update an Existing Author);

• the action buttons are different (Add versus Update); and

• a new panel is added showing the author's publications in a list (this panel is hidden in add mode).

Of course, the user can modify the viewed entity by clicking on the Update button. If no errors were displayed, the entity is updated and the user is returned to the Search dialog. Note, that the results table is also updated, if necessary.

52

Image 16: The Search dialog

Page 53: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

53

Image 17: The dialogs for adding and viewing an entity are similar

Image 18: The View and Update an Existing Book dialog

Page 54: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

Let's see one more entity dialog in view/update mode. Suppose that the user has searched the database for books, selected a book from the results and clicked on the View button (Image 18). This dialog (named View and Update an Existing Book) is also very similar to the Add New Book dialog. Similarly to authors, the title of the dialog and the title of the action buttons are different. However, instead of showing or hiding a whole panel, this dialog does something else. Namely, it must display the author(s), category and publisher this book is related to. Also note, that the cover image is actually retrieved from the database, not from the file system.

To delete an entity from the database, the user should find it by searching, select it from the results table, and click on the Delete button. It must be noted, however, that deleting an author, category, journal or publisher which is related to an article or book, will also delete the related article(s) and/or book(s). This is the way the model of the application works: e.g. an author can survive without an article, but an article cannot survive without an author, so if the article's author is deleted, the article itself must be also deleted. If pubDB notices, that the entity to be deleted is related to an article or book, it will display a confirmation message informing the user that the entity is related to an article or book, and asking whether the user really wants to delete both entities. When the user clicks on the Yes button, pubDB first deletes the related article(s) and/or book(s), and then it deletes the original entity.

This concludes the presentation of the Publication Database.

54

Page 55: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

ConclusionBuilding enterprise applications, a part of an information system, is not easy. Several

characteristics should be met, like performance, scalability and robustness. However, nowadays, there is one more feature that is considered to be more and more important: the application should be easy to use. There are many players on the field, and one of them is Oracle's technology called Enterprise JavaBeans (EJB for short). EJB's history can be considered as quite eventful. EJB 1 was very innovative, but not very functional. This was corrected in EJB 2, however, the technology itself became so complicated that only the bravest dared to exploit its potential. At the same time, some lightweight alternatives emerged, becoming more and more popular. As EJB's popularity plummeted, it was clear that the next reincarnation of EJB must be something revolutionary. And that's exactly what happened. EJB 3 was lightweight, easy to use and functional.

The goal of this term paper was to introduce EJB 3 to the reader, both theoretically and practically. For the practical part, an example called Publication Database (or pubDB) was developed. To demonstrate the possibilities of EJB 3, the example was taken apart. First, the model of the system was analyzed. After that, implementation details were presented, demonstrating the easiness of EJB 3. Lastly, the example was also shown in action.

However, there is always room for improvement for pubDB. First of all, the data (fields) for entities are fairly simple, and may need to be widened. But probably the most important task would be to optimize the communication of pubDB with the database. This means that the amount of data transmitted and received could be lower. There are also some very demanding queries. Queries returning entire tables should be avoided when possible. PubDB contains some queries such as these. They are primarily used in the dialogs involving articles and books (e.g. before showing the Add New Article dialog, the application retrieves all articles and journals to populate the corresponding list and combo box). A redesign of these dialogs would solve the problem. For example, the list of authors could be modified to also include a text box where the user can enter a search string, and clicking on a button, the list of authors would be populated only with authors matching the query, not with all authors. However, as long as the database is not too big, the actual solution is also very functional.

To summarize, it should be clear by now, that developing enterprise applications in EJB 3 is very user-friendly, and because of that, results come fast. Only one question remains: which path will be chosen for the next iteration of EJB? However, because the actual incarnation of EJB is so widely accepted, it should be natural to follow the path which is considered to be popular and well-tried.

55

Page 56: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most
Page 57: Persistence in EJB 3: A Practical Example - Robert Papp€¦ · Persistence in EJB 3: A Practical Example ... Finally, the third reincarnation came in 2006 with EJB 3.0. The most

ReferencesEnterprise JavaBean 2011, Wikipedia, The Free Encyclopedia, viewed 18 May 2011, <http://en.wikipedia.org/wiki/Enterprise_JavaBean>

Enterprise JavaBeans Technology 2011, Oracle, viewed 18 May 2011, <http://www.oracle.com/technetwork/java/javaee/ejb/index.html>

Panda, D, Rahman, R & Lane, D 2007, EJB 3 in Action, , Manning, Greenwich

57