EJB development made easy using the UML Visualizer in WebSphere Studio

EJB development doesn't have to be hard. This article will show you how easy it is to create an EJB-based application visually and test it on a server using WebSphere Studio V5.1.2 and its UML Visualizer. By creating a simple library application, you'll learn how to use the UML Visualizer to create, modify, deploy, and test of a set of EJBs.

Daniel Berg (danberg@us.ibm.com), Senior Software Engineer, J2EE Tools Team Lead, IBM Research Triangle Park Lab, North Carolina

Daniel Berg is a software engineer at IBM Research Triangle Park Lab in Durham, North Carolina, and the lead architect for J2EE tools on the WebSphere Studio Application Developer team. You can reach Daniel at danberg@us.ibm.com



06 October 2004

Introduction

I can't tell you the number of times I've heard that developing with EJBs is so hard that people turn to writing their own persistence layer using plain old Java™ beans, and they may only define simple session beans to take advantage of EJB security settings. A year ago I would have agreed with these statements. However, times have changed, development tools have improved, and the EJB specification has matured. The EJB 2.0 specification introduced local client views, which eliminate the need to use remote method invocations when running EJBs within the same JVM. And IBM® WebSphere® Studio V5.1.1 and V5.1.2 now support visual creation and manipulation of EJBs through the UML Visualizer.

This article will show you how to create a simple EJB application using the UML Visualizer in WebSphere Studio V5.1.2. It will walk you through the creation, modification, deployment, and testing of a set of EJBs. The article will also use the new EJB snippet support to add business logic to the generated beans. To learn more about the new snippet support in WebSphere Studio, see EJB Programming with snippets in WebSphere Studio V5.1.2. By the end of this article, I hope to convince you that EJB development does not have to be hard and complex, and can actually be done quickly and easily.


Review of the library model

To demonstrate that EJB development can be easy, this article will show you how to create a simple library application that consists of Books and Authors, as shown in the UML diagram above. The relationship between these two types is that an Author can have many Books but a Book can have only one Author.


Create the library enterprise application

The example starts with the creation of a new enterprise application named Library that contains an EJB module named LibraryEJB.

  1. Select File => New => J2EE => Enterprise Application Project to launch the Enterprise Application Project wizard.
  2. Select Next.
  3. Keep the Create J2EE 1.3 Enterprise Application project option and select Next.
  4. Enter Library for the project name:
    .
  5. Select Next.
  6. Select New Module:
  7. Select only the EJB Project option, leave the default name, and click Finish:
  8. The new LibraryEJB EJB project will now appear and be selected in the dialog from Step 6. Select Finish:

A new enterprise application will now appear in the J2EE Hierarchy view of the J2EE perspective named Library and it will contain one module called LibraryEJB.jar. The LibraryEJB module corresponds to a LibraryEJB project, which appears under the EJB Modules section of the J2EE Hierarchy view.


Creating an EJB visual class diagram

To start creating EJBs visually, you must first create a visual class diagram in the LibraryEJB project:

  1. Select the LibraryEJB module from the J2EE Hierarchy view.
  2. Select New => UML Visualization => Class Diagram to open the New Class Diagram wizard:
  3. Select Finish. This will open an empty Visualizer diagram, as shown below:

The default location to save the new diagram is in the LibraryEJB project under the ejbModule/META-INF folder. This folder contains all of the meta-information for the project. Saving the class diagram under the ejbModule directory (or anything else for that matter) will cause it to be exported to the deployed EJB module JAR when the final EAR file is exported. If you do not want the class diagram exported with the module, save the class diagram within the project itself or in any folder that is not within the ejbModule folder or any other Java source folder within the project. For example, you could create a folder named diagrams under the project to hold all of the class diagrams, and this folder would not be included in the deployed EJB module JAR.

The first item that you should notice with the diagram is that it has a palette to the left. This palette contains simple selection mechanisms and annotation devices that you can select and drop on the diagram. The palette items are push buttons that indicate the action to be applied on the diagram. There are two compartments: Java and EJB 2.0. The Java compartment contains actions to create and modify Java classes and interfaces. The EJB 2.0 compartment is used to create and modify EJBs. For an EJB 1.1 project, the EJB compartment would be slightly different to only support actions that are available for 1.1 EJBs.

Create container-managed entity beans

With the class diagram, the domain objects (Book and Author) can be created using 2.0 container-managed entity beans. To do so, select the CMP 2.0 Entity Bean palette entry, then move your mouse over the diagram to see a plus symbol. Select your left mouse button to activate this action:

Once the action is activated, the Create Enterprise Bean wizard will open with the type already selected to a 2.0 CMP bean. The remaining steps of the wizard need to be completed in order to create our Book CMP bean:

  1. Enter Book for the name of the bean and enter com.wsdd.library.ejbs for the default package name.
  2. Select the Next button. By default only a local client view is selected for entity beans. This is the preferred client view for entity beans but a remote client view may be added at this point in the wizard.
  3. Select the Add button to open the Add CMP Field dialog.
  4. Enter id for the name, select Integer for the type and ensure the Key field check box is selected.
  5. Select the Apply button.
  6. Repeat steps 3 - 5 to add another field named title that is typed to String (this is not a key field).
  7. Select Finish to create the Book bean and have it appear in the diagram as a UML2 Class shape.

Repeat the previous steps to add another 2.0 CMP bean named Authorwith an id key field typed to Integer and a name field typed to String.

The EJB specific UML2 Class shapes in the diagram have two main compartments. The first compartment shows the persistent attributes of the CMP bean (i.e., CMP fields) and the second compartment shows the operations (or methods) that are available on the client home interfaces. Notice that the changes made to the diagram are being reflected in the J2EE Hierarchy view. This is possible because a common object model is shared among the diagram and the J2EE Hierarchy (actually this model is shared among all of the tools as well as WebSphere Application Server).

Add 2.x relationships

It is highly uncommon to have an object model without any relationships. So a relationship between Book and Author will be added via the diagram. In the past the EJB Deployment Descriptor editor was used to add an EJB relationship using the EJB Relationship wizard. This can still be done but I find it hard to use this wizard since it represents the EJB 2.0 relationship which is not described in terms of UML. I don't know about you, but I always like to create relationships using UML terminology. This is where the EJB Visual editor really shines.

To create a relationship from one CMP to another you simply need to select one of the EJB relationship actions form the editor's palette.

These actions indicate the multiplicity of the source and target types as well as the navigability from the source object, either bidirectional or unidirectional. The definition of each action is shown in the table below.

Relationship ActionSource MultiplicityTarget MultiplicityIs Bidirectional
1:1 CMP RelationshipOneOneYes
1:M CMP RelationshipOne ManyYes
M:M CMP RelationshipManyManyYes
1:1 Directed CMP RelationshipOneOneNo
1:M Directed CMP RelationshipOneManyNo
M:1 Directed CMP RelationshipManyOneNo
M:M Directed CMP RelationshipManyManyNo

After selecting the appropriate action, in this case 1:M CMP Relationship, the source CMP bean (Author) is selected and then, while still holding your mouse button, you will drag the selection over to the target CMP bean(Book) and release the mouse button. This will create the new relationship and generate the appropriate Java code as well as update the EJB deployment descriptor. Note that a default relationship name and default Container Managed Relationship (CMR) field name are used.

The following methods are generated within the AuthorBean.java file to support the relationship.

/**
 * This method was generated for supporting the relationship role named books.
 * It will be deleted/edited when the relationship is deleted/edited.
 */
public abstract java.util.Collection getBook();
/**
 * This method was generated for supporting the relationship role named books.
 * It will be deleted/edited when the relationship is deleted/edited.
 */
public abstract void setBook(java.util.Collection aBook);

The following methods are generated within the BookBean.java file to support the relationship.

/**
 * This method was generated for supporting the relationship role named author.
 * It will be deleted/edited when the relationship is deleted/edited.
 */
public abstract com.wsdd.library.ejbs.AuthorLocal getAuthor();
/**
 * This method was generated for supporting the relationship role named author.
 * It will be deleted/edited when the relationship is deleted/edited.
 */
public abstract void setAuthor(com.wsdd.library.ejbs.AuthorLocal anAuthor);

Since Author has many Books, it is more desirable to have the relationship role name from Author to Book set to be books and not book. This requires that the deployment descriptor, bean class, and local interface get updated. This can all be done on the diagram surface as follows.

  1. Select the book relationship role once to select the role.
  2. Select the role a second time to start a modification section.
  3. Change the role name to books.
  4. Click enter.

It should be noted that you can change the multiplicity as well as the role names of the EJB relationship from within the diagram. If you would like to change the relationship name or the navigability of one of the relationship roles you can select one of the EJB class shapes and select Open from the context menu. This will open the EJB Deployment Descriptor editor and take you to the Beans page with the bean selected. From this point you can scroll down and select the relationship you would like to edit from the Relationships section and then select the Edit button.

Create a stateless session bean

One of the EJB 2.0 best practices is to use a stateless Session bean to interact with Entity beans that have any local client views. The same for the Book and Author entities in this example.

  1. Select the Stateless Session Bean palette action.
  2. Click anywhere on the diagram to open the Create Enterprise Bean wizard with the session bean option selected.
  3. Enter Library for the name of the stateless session bean.
  4. Select Next.
  5. Leave the default Remote Client View option selected.
  6. Select Finish.

Add EJB references

Another EJB best practice is to use EJB References when doing a lookup of another EJB Home interface. This is a best practice because the application's Java code will only refer to the EJB Reference name when doing the lookup and not the global JNDI name of the bean. So, if the JNDI name changes, as it often does during deployment, the application code will continue to work since the EJB Reference is bound to the JNDI name. With the WebSphere Application Server a local EJB Home interface can only be looked up using an EJB Local Reference. It is not possible to obtain a local reference using the global JNDI name.

Creating an EJB Reference with the EJB Visual editor is similar to creating a relationship. There are two types of EJB Reference palette actions as shown below.

For this example, two EJB Local References will be created from Library to Author and Book so that the Library session bean can interact with the two entity beans. Follow the steps below to create these references.

  1. Select the EJB Local Reference palette action.
  2. Click on the Library bean and continue to hold the mouse button down.
  3. Drag the selection to the Author bean and release the mouse button. This will create an EJB Local Reference with a default name. The default name is changed by simply selecting it and typing a different name. For this example the default name will be used.

    Here is the new reference shown in the EJB Deployment Descriptor editor. Notice that the newly created EJB RLocal Reference is already correctly bounded to the proper global JNDI name namely ejb/com/wsdd/library/ejbs/AuthorLocalHome.
  4. Repeat steps 1 - 3 using the Book bean as the target.

Add EJB finders

It is common to have additional "finder" methods defined for a given entity bean within an application. EJB finders provide the ability to return a subset of entity beans based on conditions defined using container-managed persistent fields and relations. In this library application, a finder needs to be added to the Book entity to return a collection of Books for a given Author's name. EJB finders can be defined on a container managed entity bean using the EJB Visual editor. Follow the steps below to add the findBooksByName finder to the Book entity bean.

  1. Select the Book entity from the class diagram.
  2. Select the Add EJB => Query context menu action to launch the EJB Finder wizard.
  3. Select New and enter findBooksByName for the name of the new finder.
  4. Click Add to add a new parameter named name with a type of java.lang.String.
  5. Select java.util.Collection as the return type.
  6. Click Next to advance to the second page where the query statement is entered.
  7. Select the Single Where Predicate sample query. This will enter a valid EJBQL query with one cmp-field used in the WHERE predicate.
  8. Change the WHERE predicate to o.author.name = ?1.
  9. Click Finish to add the new finder.

At this point a new EJB Query is defined in the deployment descriptor for the Book bean and there is a new findBooksByName(String) method on the BookLocalHome interface.

Add business logic

At this point in the example the entity beans are setup correctly and what is needed is the addition of business logic on the Library session bean to interact with these entity beans. One remote method that is needed is the findBookTitlesByAuthor(String) which will return a String array of Book titles given an Author's name. The second remote method that is needed is the populateTestData method, which will be used only for testing purposes. Some of this work can be done from within the EBJ Visual editor.

Show related diagram elements

In order to add logic to the Library's bean class it is necessary to visualize the EJB bean class for the Library bean which is done by selecting the Library bean in the visual editor and selecting the Show Related Elements context menu action. This opens the Show Related Elements in Diagram dialog which is used to filter or display related elements for the selected item(s) in the diagram. For this example , deselect the Java and EJB checkboxes and select the Abstraction checkbox under the EJB header. The From Selection to Supplier radio button needs to be selected so abstractions from the bean will be displayed. Abstractions will include the bean class and client interfaces.

After clicking OK you will see the abstractions added to the class diagram. For this example the Library and LibraryHome elements can be deleted from the diagram. Deleting from the diagram does not delete the underlying resource.

From the class diagram a method can be added to the LibraryBean class by selecting the LibraryBean element and selecting the Add Java > Method context menu action. This launches a wizard that allows you to set the method information. I'm not a big fan of this approach. Creating methods are much easier done from the Eclipse Java editor plus you need to use the Java editor to add to the body of the method. So I prefer to just double click on the LibraryBean element to open the Java editor. Then from here the new methods can be added.

Add Java methods

Whenever a stateless session bean is introduced into an application, some custom code writing is almost always necessary. Following J2EE best practices business logic APIs will be added to the stateless session beans within the application. In order to make this example a bit more realistic, some business methods will be added to the LibraryBean using the Java editor that was just opened.

Add the populateTestData() method

The populateTestData method will be the first one added to the bean. Before we add this method, two private methods that will create a BookLocal and an AuthorLocal will need to be added to support the poplulateTestData method.. The new EJB snippet support will be utilized to complete these methods. for details on how to use this new function, see EJB programming with snippets in WebSphere Studio V5.1.2. To begin add the following empty method.

private BookLocal createBook(int id) {

}

Use these steps to complete the body of this method.

  1. With your cursor within the body of this method, launch the Call an EJB "create" method EJB snippet from the snippets view.
  2. The wizard will display the EJB references to Book and Author that were created in the EJB Visual editor. Double click the ejb/BookLocal reference.
  3. Double-click on the create(Integer) method.
  4. Change the Integer value in the table to be new Integer(id) and click Finish.

Upon finish the method body will be completed based on the selections in the steps above. It's necessary to organize imports by selecting Ctrl + Shift + O to add missing imports. A return statement of return aBookLocal needs to be added to the end of the method body. Here is the completed method:

private BookLocal createBook(int id) {
BookLocalHome aBookLocalHome =
	(BookLocalHome) ServiceLocatorManager.getLocalHome(
		STATIC_BookLocalHome_REF_NAME,
		STATIC_BookLocalHome_CLASS);
BookLocal aBookLocal = null;
try {
	if (aBookLocalHome != null)
		aBookLocal = aBookLocalHome.create(new Integer(id));
} catch (CreateException ce) {
	// TODO Auto-generated catch block
	ce.printStackTrace();
}
return aBookLocal;
}

Next a similar method for the Author bean needs to be added. Follow the same steps above to add a "create" method for an Author. The completed method should appear as the following.

private AuthorLocal createAuthor(int id) {
AuthorLocalHome anAuthorLocalHome =
	(AuthorLocalHome) ServiceLocatorManager.getLocalHome(
		STATIC_AuthorLocalHome_REF_NAME,
		STATIC_AuthorLocalHome_CLASS);
AuthorLocal anAuthorLocal = null;
try {
	if (anAuthorLocalHome != null)
		anAuthorLocal = anAuthorLocalHome.create(new Integer(id));
} catch (CreateException ce) {
	// TODO Auto-generated catch block
	ce.printStackTrace();
}
return anAuthorLocal;
}

These two new methods will be used to simplify the coding of our populateTestData method. Copy the method below and paste it into the LibraryBean.java file using the Java editor.

public void populateTestData() {
System.out.println("Creating Authors");
AuthorLocal a1, a2;
a1 = createAuthor(1);
a1.setName("Jones");
a2 = createAuthor(2);
a2.setName("Smith");

System.out.println("Creating Books");
BookLocal book;
book = createBook(1);
book.setTitle("Book1");
book.setAuthor(a1);

book = createBook(2);
book.setTitle("Book2");
book.setAuthor(a1);

book = createBook(3);
book.setTitle("Book3");
book.setAuthor(a1);

book = createBook(4);
book.setTitle("Book4");
book.setAuthor(a2);

book = createBook(5);
book.setTitle("Book5");
book.setAuthor(a2);
System.out.println("Done creating library.");
}

Add the findBookTitlesByAuthor(String) method

The second method that will be added takes advantage of the EJBQL query that was added to the Book earlier in this article. This method will return a String array of the Book titles given an Author's name. To start add the following method signature to the LibraryBean.

public String[] findBookTitlesByAuthor(String name) {

}

Similar to the createBook(int) and createAuthor(int) method, the EJB snippet support will be utilized to help populate this method body.

  1. Select the Call an EJB "find" method EJB snippet action from the Snippets view.
  2. Double click on the ejb/Book.
  3. Select the findBooksByName(name) method.
  4. Click Finish.

The method body now has the necessary code to find the collection of BookLocal objects for the passed Author's name. All that is necessary is to add to the method body to iterate over this collection to extract the title from each BookLocal and add it to a String array. The completed method is shown below with the additions surrounded with //Begin Add and //End Add..

public String[] findBookTitlesByAuthor(String name) {
BookLocalHome aBookLocalHome =
	(BookLocalHome) ServiceLocatorManager.getLocalHome(
		STATIC_BookLocalHome_REF_NAME,
		STATIC_BookLocalHome_CLASS);
Collection aCollection = null;
try {
	if (aBookLocalHome != null)
		aCollection = aBookLocalHome.findBooksByName(name);
	//Begin Add
	Iterator it = aCollection.iterator();
	String[] titles = new String[aCollection.size()];
	for (int i = 0; it.hasNext(); i++) {
		BookLocal book = (BookLocal) it.next();
		titles[i] = book.getTitle();
	}
	return titles;
	//End Add
} catch (FinderException fe) {
	// TODO Auto-generated catch block
	fe.printStackTrace();
}
//Begin Add
return new String[0];
//End Add
}

In order to make the populateTestData() and findBookTitlesByAuthor(String) methods available to remote clients it is necessary to promote these methods to the remote interface of the Library session bean. Follow the steps below to promote these methods to the remote interface.

  1. Select the populateTestData()and findBookTitlesByAuthor(String) from the Java editor outline.
  2. Select the Enterprise Bean => Promote to remote interface context menu action.

Testing the new enterprise beans

As with any application that is newly created it is always necessary to test the code paths that have been implemented. A J2EE application with EJBs is no different but it can be quite a bit harder to setup the an environment for testing. For example an application server must be created, started, and configured, a database may need to be created, and the EAR project must be deployed and published to this server. Even after all of this is done there must be some mechanism that can exercise the EJB code paths. Needless to say it would be easy to spend hours just setting up this environment before any testing can be done. This is unacceptable for rapid J2EE development. The next sections will describe how easy it is to test the Library application within WebSphere Studio.

Testing with the universal test environment (UTC)

I am quite pleased to say that testing within WebSphere Studio does not have to be as painful as described above. At this point in the development of the Library application, the EJBs have been modeled and additional business logic has been added to the Library session bean. Deployment code and server creation/configuration has not been done. It would be nice to be able to test the two new public methods that were added to the Library session bean without the complications of database creation point in time. In order to do this the UTC will be used to exercise the session bean. This is easily done by following the steps below.

  1. Select the Library session bean from the J2EE Hierarchy view.
  2. Select the Run on Server context menu action. The server can also be launched in debug mode by selecting the Debug on Server action. Choosing the Debug on Server action will allow the use of breakpoints to correct problems in the code.

Selecting a server

After selecting the Run on Server action, a wizard will be launched to walk through the steps required to test the selected EJB on a particular server.

  1. The first step is to select the type of server that to test with. For this example the default selection of WebSphere Application Server V5.1 Test Environment will be used.

    Click the Next button.
  2. The next page indicates the port to use. For this example leave the default port number and click Next.
  3. The third page of the wizard is for the deployment of the Enterprise Java Beans within the EJB module(s) (in this case just one). Both the Create tables and data sources and DeployEJB Beans options need to be selected since this is the first time the module has been launched. The first option will ensure that the actual database tables are created and that the necessary data sources will be defined on the server to access these tables. The second option will perform a top-down mapping of the Container Managed entities within the EJB project to a default database type e.g., Cloudscape) and it then generates the necessary deployment code for running on the server against this database type.

    Click Finish from this page.
  4. The following confirmation dialog will be presented when the table creation and data source creations are complete.

    Click OK from this dialog.
  5. At this point the EJBs are mapped and deployed and the server is created and configured. So the application can be published to the new server. A publishing dialog will be presented at this point.
  6. The console will indicate that the server is starting. Once the server has started the Universal Test Client will open with the Library bean already selected.

Test the Library bean

With the UTC open we can begin testing the new Library session bean.. First a Library session bean instance needs to be created.

  1. Expand the Library bean from the EJB References tree and select the LibraryHome link. This will show you the available methods on the LibaryHome interface.
  2. Select the create() method link.
  3. This adds the method context to the Parameters section of the UTC. Now the create() method can be executed by selecting the Invoke button.
  4. After selecting the Invoke button, the results of the method call (i.e., a new Library session instance) are displayed in the Results section.
  5. Click on the Work with Object button to add it to the References tree and to allow for it be tested.

Now the methods that were added to the remote interface of the Library bean can be tested.

  1. Select the Library 1 reference from the References tree and select the populateTestData() method.
  2. Like the create() method before, the method context is added to the Parameters section and the Invoke button needs to be selected to run the method. Now the database tables will be populated with some test data that can be used for the other method.
  3. From the References tree select the findBookTitlesByAuthor(String) method.
  4. Since this method requires a parameter, one must be entered before invoking the method. In the Parameters section set the String parameter to be Smith.
  5. Click on the Invoke button to invoke this method. The results are again shown in the Results section and it should show a String[] of size two. In order to see the results select the Work with Object button.
  6. From the References tree, select the new String[] reference to expand operations that can be invoked on it and select the Inspect Fields link.
  7. The results of inspecting the fields will appear in the Parameters section and a Book4 and Book5 entry will be displayed.

Follow these same seven steps except enter Jones for the parameter and a String[] with three elements Book1, Book2, and Book3 will be returned.


Conclusion

This article has shown you how to use WebSphere Studio V5.1.2 and its UML Visualizer to create an EJB-based application and test it on a server. The visual development techniques outlined here make the formerly daunting task of EJB development much simpler and faster. Of course, developing an application is an iterative process that requires requires repeated cycles of design, implementation, and test, and while the article did not show these repeated cycles, WebSphere Studio fully supports repeated incremental changes to the diagram, EJB mapping, and database tables, followed by retesting on the server. For the most part, you can just follow the steps in the article. However, to make incremental changes to the mapping of the CMP entities to the database tables, you need to launch the EJB-to-RDB Mapping wizard on the existing back end with the Create and map unmapped elements option. For details, see the EJB documentation.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Java technology
ArticleID=23607
ArticleTitle=EJB development made easy using the UML Visualizer in WebSphere Studio
publish-date=10062004