http://www.developer.com/

Back to article

Who Says EJB 2.1 is Too Hard?


October 11, 2005

EJBs, and in particular the EJB 2.1 spec, have a reputation of being powerful but complex. I have seen more arguments against using Java/J2EE because EJBs are too complex than for any other reason, and from many different sources. Common wisdom seems to be that J2EE and EJBs are synonymous; hence, J2EE is too complex to use.

Obviously, even casual inspection of this reasoning shows the flaws. For one thing, EJBs are just a part of the J2EE specification (or the Java EE specification as it is now known), and need not be used at all. I also take issue that the complexity is somehow the fault of EJBs. Certainly, they could be simplified (and EJB 3.0 goes a long way to doing that), but the real problem is that they deal with a very complex problem domain. Delivering components that have transactional support, security, location transparency, discovery, scalability and concurrency is not easy.

However, I will admit that using EJB 2.1 as detailed in the specification, with deployment descriptors, containers, and EJB lookup is quite a steep learning curve. It is a tough architecture to roll out to developers who need to be up and running fast, unless you have good tools that you can rely on to simplify the whole thing.

And that is what this article is about. It is intended to demonstrate that EJBs, even in their 2.1 form, need not be so scary, that you can jump in and with little time and effort have a working system that uses the full strength EJB architecture. Between using NetBeans to create the EJB, Sun App Server 8.1 to deploy it, and Java Studio Creator to consume it, you will not see a deployment descriptor, lookup code, or anything else complex (unless you really want to).

First Steps

This article can either be used as an introduction to the approach and tools available, or as a click-along tutorial. If you intend to do the latter, you will need to download NetBeans and Java Studio Creator 2 EA 2:

For NetBeans, you will need to download at least NetBeans 4.1. You can choose to download the NetBeans 5.0 Beta, but should know that if you do so you should get a package that includes the Sun App Server PE 8.1 (or download it separately). Unless you have the app server and have configured NetBeans to know about it, you will not be able to create an enterprise project in NetBeans.

Download NetBeans from http://www.netbeans.org.

For Java Studio Creator, you need to get the Early Access 2 release of Creator 2. To do this, go to http://developers.sun.com/prodtech/javatools/jscreator/ea/jsc2/index.html and register; you then will be able to download the EA2 version of Creator 2 that has all of the new EJB support.

This article demonstrates a very narrow part of the whole field of EJB creation and consumption. For one thing, I intend to demonstrate Session Beans only (I prefer using only Session beans for remote APIs) and will also skip the persistence part, prefering to concentrate on the creation of an API and the consumption within Java Studio Creator.

However, there are some excellent guides and tutorials that do a better job of demonstrating Entity EJBs (for persistence) in NetBeans, and also an alternative one that shows how Hibernate could be used for persistence instead (should that be your preference).

Using NetBeans to Create the Session API

First, you are going to use NetBeans to create your Session EJB-based API. To do this, start NetBeans and:

  1. From the Welcome page, select New Project.
  2. In the new project wizard, select Enterprise/EJB Module. Click Next.
  3. Choose a name for your EJB module (I suggest CreatorDemoEJB).
  4. Choose a directory for the project.
  5. For Server, you should have Sun Application Server 8.1 selected. If it is not available, you need to download it and configure it in NetBeans. The easier option is to download the NetBeans distribution that already includes it.
  6. Leave everything else default and click Finish.

Create a DTO Class

Before you do anything else, you need an object to pass data from the server to the client. You could certainly do this using arrays, but a full DTO (Data Transfer Object) lets you send structured data across from the server, and this will demonstrate some of the richer features in Java Studio Creator.

For this demo, you are going to create an object that holds some typical details about a person (like first and last name, telephone numbers, age, salary, and whether the person is on vacation—this last one is in there as a way to demonstrate boolean values).

So, create a new class called PersonDTO:

  1. In the top left pane, select the Projects tab and find the Source Packages node in the project tree, right-click on it, and select New->Java Class....
  2. In the dialog, type the name PersonDTO for the class name, and choose a suitable package. Click Finish.
  3. A new class will be created. Add the following code into it:
    • The DTO needs to be serializable, so add implements Serializable to the class definition.
    • In the Projects pane, expand the node for the new PersonDTO class, and the node inside that. You should see four nodes named Fields, Constructors, Methods, and Bean Patterns.
    • Right-click on Bean Patterns, and select Add->Property. In the dialog, add a property with name lastName and type String. This is the quick way to add new properties without having to write getter and setter methods (they are provided for you).
    • Repeat for the following fields: firstName of type String, homeTel of type String, workTel of type String, income of type double, age of type int, and onVacation of type boolean.
    • You are not doing any persistence code, so you need some test data. Add the following code to set some up:
    public static PersonDTO[] peopleList = null;
    static {
       // set up some demo data for the people list
       peopleList = new PersonDTO[10];
       peopleList[0]=new PersonDTO("Bloggs","Fred","770-555-1212",
                                   "770-555-2121",55000.00,25,true);
       peopleList[1]=new PersonDTO("Schmo","Joe","404-555-3434",
                                   "404-555-4343",125000.00,62,false);
       peopleList[2]=new PersonDTO("McTog","Nog","770-555-5555",
                                   "770-555-6666",25000.00,17, true);
       peopleList[3]=new PersonDTO("Pepper","Petey","770-555-5432",
                                   "770-555-3456",84378.12,33,false);
       peopleList[4]=new PersonDTO("Fairlane","Sandy","770-555-9999",
                                   "770-555-9898",142222.00,55,true);
       peopleList[5]=new PersonDTO("Lane","Lois","123-555-8833",
                                   "123-555-5544",95000.00,22,false);
       peopleList[6]=new PersonDTO("Wesley","Tom","770-555-7654",
                                   "770-555-6756",48000.00,44,false);
       peopleList[7]=new PersonDTO("McDunne","Diane","770-555-5275",
                                   "770-555-6641",76543.21,51,false);
       peopleList[8]=new PersonDTO("Burt","George","770-555-8111",
                                   "770-555-7222",70000.00,41,false);
       peopleList[9]=new PersonDTO("Smith","Anne","770-555-5656",
                                   "770-555-7878",90000.00,24,true);
    }
    
  4. You need to add a constructor to build the data using this information. In the class, add the following code:
  5. /**
     * PersonDTO constructor. Takes all fields to produce a ready
     *  populated Person Data Transfer Object
     * @param last String containing last name
     * @param first String containing first name
     * @param homeTel String containing home telephone
     * @param workTel String containing work telephone
     * @param income double containing person's income
     * @param age int age of person
     * @param onVac boolean flag set to true if person is on vacation
     */
    public PersonDTO(String last,String first,String homeTel,
                     String workTel,double income,int age,
                     boolean onVac) {
       this.lastName = last;
       this.firstName = first;
       this.homeTel = homeTel;
       this.workTel = workTel;
       this.income = income;
       this.age = age;
       this.onVacation = onVac;
    }
    

That's it for your DTO object. Now, on to the EJB.

Creating the EJB

For the sake of this demo, call your EJB "PeopleEJB". The API you write will be pretty simple (deliberately) but will provide some methods to list back the data as collections of the PersonDTO objects you just created.

  1. In the Projects pane, right-click on the Enterprise Beans node and select New->Session Bean.
  2. For the name, enter PeopleEJB, and select a suitable package, leave the Session Type as Stateless, and check both Remote and Local for the Create Interface options.
  3. Click Finish. A PeopleEJBSB (SB for Session Bean) will appear in the Projects pane. You can think of this as "the" EJB even though there are actually several files behind it. Get used to interacting with this session bean representation in the Projects pane for adding and altering methods. That way, the IDE will do all of the necessary work in all the files behind the scenes.
  4. Right-click on the new PeopleEJBSB and select Add->Business Method.
  5. In the dialog, for the name enter listAll, and for the return type enter PersonDTO[] (for example, an Array of PersonDTO objects).
  6. Make sure both Remote and Local are checked for the Use in interface options, and click OK.
  7. Repeat this for another method called listOnVacation (with the same PersonDTO[] return type).
  8. Create another one called listIncomeAbove with the same return type, but this time add a parameter called amount of type double (you will use this to pass in an amount to filter income by before returning the results).
  9. You need to add method definitions for the EJB methods you just created, so expand the PeopleEJBSB node and one of the Remote or Local nodes inside of it (doesn't matter which).
  10. Double-click on listAll first. The editor window will go to that method definition.
  11. Replace the body of the method with the following code:
  12. return PersonDTO.peopleList;
  13. At this point, you might notice that the editor is complaining about PersonDTO because you haven't imported it yet (unless you happen to have PersonDTO in the same package as PeopleEJB). If it is complaining, right-click in the editor window and select Fix Imports.
  14. Next, you need to flesh out the listOnVacation method. In the Projects pane, find the listOnVacation method and double-click on it.
  15. Replace the method definition with:
  16. ArrayList vacationers = new ArrayList();
    for(int i=0; i<PersonDTO.peopleList.length; i++) {
       if(PersonDTO.peopleList[i].isOnVacation()) {
          vacationers.add(PersonDTO.peopleList[i]);
       }
    }
    // convert to array
    PersonDTO[] retArray =
       (PersonDTO[])vacationers.toArray(new PersonDTO
          [vacationers.size()]);
    return retArray;
    
    Note: If you are using JDK 1.5 and are comfortable with it, you can always use the forEach notation instead of the above.
  17. Finally, replace the body of the listIncomeAbove method with:
  18. ArrayList higherIncome = new ArrayList();
    for(int i=0; i<PersonDTO.peopleList.length; i++) {
      if(PersonDTO.peopleList[i].getIncome() > amount) {
        higherIncome.add(PersonDTO.peopleList[i]);
      }
    }
    // convert to array
    PersonDTO[] retArray =
       (PersonDTO[])higherIncome.toArray(new PersonDTO
          [higherIncome.size()]);
    return retArray;
    
  19. Right-click in the editor again and select Fix Imports a second time, to include any classes you have used and that have not yet been imported.
  20. Finally, do a build all (from the menu, Build->Clean and Build Main Project). If you get errors in other files that need imports, right-click in the offending file and fix the imports; then rebuild until you get a clean build.

Believe it or not, that's your EJB written.

Gotcha: Although life is definitely not that hard when using the SB representation in the Projects pane, you must remember to use it for any changes to the method name, return type, or parameters. This is because if you just change it in the class you have been editing the method bodies in, it will not update the other files that make up the EJB. It is very important to remember to go through the SB representation for all method additions, changes, or removals! To make changes to a method, just right-click on the method in the SB representation object, select Refactor->, and choose the type of change you want to make; then follow through the dialog. Sometimes, you may find that it will be necessary to remove an old method and replace it with a completely new one to change the details; this is ugly but not particularly hard.

Hint: You can always copy the body of the method before removing it, and then paste it into the new method afterwards and make any necessary changes.

Create the EJB Jar file

The final step in NetBeans is to create the EJB Jar file. To do this, simply go to the menu and select Build->Build Main Project. Look in the output window to see where the jar file is created.

Deploy to the Java Studio Creator App Server

The next step is to take the EJB Jar file you just created and deploy it to the App Server instance inside Java Studio Creator.

Deploy Direct to Sun App Server 8.1 Instance in Creator

  1. Start Java Studio Creator 2 EA 2.
  2. In the top left pane, select the Servers tab.
  3. Find the Deployment Server node, and right-click on it. Select Start/Stop Server.
  4. In the dialog, hit the Start Server button (if it is greyed out, the server may already be running).
  5. In a Web browser, browse to http://localhost:24848.
  6. Log in using username: admin and password: adminadmin.
  7. Find EJB Modules under Applications and click on it.
  8. Click the Deploy button in the main frame.
  9. Browse to the EJB jar file you created in NetBeans (probably in the dist folder under your project folder), and open that jar file.
  10. Click Next, use Application Name: CreatorDemoEJB.
  11. Important: Also check the Generate: RMIStubs checkbox (this will create a client you can use in Java Studio Creator).
  12. Click OK. If all goes well, you should be returned to the EJB list and see the newly deployed EJB module.
  13. The client stubs you created can be found in a jar file in your Java Studio Creator installation directory under SunAppServer8/domains/creator/applications/j2ee-modules/CreatorDemoEJB. Remember this location because you will need it in the next section.
  14. Note: Keep this location noted somewhere, or remember to use the find tool on your OS to locate it. It can be tricky to remember.

Consume the EJB in Creator

Now, you are ready to use the new EJB you just made:

  1. In Java Studio Creator, in the Servers Tab, right-click on the Enterprise Java Beans node and select Add Set of Session EJBs.
  2. In the dialog, enter the name CreatorDemoEJB.
  3. Set the RMI-IIOP port to 23700 (the port number that the Creator app server instance runs on by default).
  4. Click the Add button next to the Client Jar section, and find and open the client jar you created in the last section. Click Next.
  5. This next screen shows you what beans and methods you are importing. You can simply accept them, but read on first:
  6. Because the client creation uses reflection, some information, like the names of the method parameters, is lost by default. This screen lets you edit the parameter names; this will make the API easier to use in Creator.
  7. Because you only have one method with a parameter, select the listIncomeAbove method and in the parameters section, edit arg0 to read the amount (double-click on amount to change it and enter when you have finished changing it).
  8. Click finish when done.

This imports the EJB. You can see it in the Enterprise Java Beans section in the Servers tab of the top right pane. Expand it and you should see the methods you created as well.

Create a Demo Client in Java Studio Creator

Almost there now. Throw a quick project together and a couple of pages to demonstrate the new easy binding features for EJBs in Creator. You will demonstrate it using Data Tables, but the same EJB methods can be bound to other controls using the same tricks. For more information on general binding in Java Studio Creator, see the tutorials at http://developers.sun.com/prodtech/javatools/jscreator/ea/jsc2/learning/tutorials/index.html.

First, get a simple project and page to list all the people:

  1. At the Creator welcome page, click Create New Project.
  2. Select Web and JSF Web Application from the Choose Project dialog. Click Next.
  3. Choose a name (like PeopleDemo) and a location for the project. Click Finish.
  4. In the resulting Page1 file that comes up, drag a Table control from the Palette on the left onto the page.
  5. Rename the "Table" label to read People.
  6. Now, for the cool part. Go to the Servers tab in the top left pane and find the listAll method from the CreatorDemoEJB (if you have not expanded it already, expand the CreatorDemoEJB and the ejb/PeopleEJBBean under that until you see the methods).
  7. Drag the listAll method onto the data table you just created. This binds the results of that method call to the table; you will see the fields change in response to the PersonDTO class fields.
  8. Note: If you get a dialog asking you to select a target, make sure you select the whole table, probably called table 1).
  9. Pretty impressive, but the columns are probably in the wrong order, plus the peopleList static property shows up (which you don't want), and you also can give it some clues about the representation of the data you want:
    1. Right-click on the table and select Table Layout.
    2. Select peopleList and click the < button to remove it.
    3. Select firstName and click the Up button until it is at the top.
    4. Do the same for lastName.
    5. You might want to arrange the homeTel and workTel numbers together as well.
    6. Feel free to select each column definition in turn and give it a better Header Text entry (which will be displayed in the column header).
    7. Also, change the onVacation field to be represented as a checkbox: select onVacation in the columns and then change the Component Type to Checkbox.
    8. Click OK. You should see the changes reflected in the data table.

Now, run the project (Run->Run Main Project from the menu). You should see a page like this:



Click here for a larger image.

If you have not yet played with the new Java Studio Creator 2 controls, go ahead and click on the column headings; this allows you to sort the data displayed in the table by the different columns (and, by using the + symbols that appear after you first select a sort order, you can create a sort hierarchy as well).

A More Involved Example

So, you just bound the results from a simple EJB list method directly into a data table. Very neat, but what if you want to be a little more selective about what you show?

If you remember, you created a method called listIncomeAbove that took a value to filter the details returned by. Create a page that uses that.

  1. In the Projects tab in the bottom right pane, right-click on the Web Pages node and select New->Page....
  2. For the File Name, type ListIncomeAbove. Click Finish.
  3. In the Projects tab again, find the new page, right-click on it and select Set As Start Page (this will make testing it easier).
  4. This time, drag a Static Text control, Text Field control, and Data Table onto the page so it looks like this:
  5. You should rename the ID of at least the text field to be something like amountInput. Renaming your controls to a meaningful name at least for all of the input ones is a good idea because it makes your page code easier to read. Select the control, click properties, and change the top field in the properties pane called ID to read amountInput.
  6. Find the listIncomeAbove EJB method and drag it over the data table.
  7. Follow Step 8 from the List All example above to change the layout of the table and make it look like the List All page.
  8. Now, right-click on the amountInput text field and select Auto Submit on Change, so that when you enter a value here, it will fire a change event in the page bean.
  9. Double-click on the inputAmount text field and Creator will drop you into editing the event for that text field.
  10. Where it says //TODO: Replace with your code, replace the line with the following:
  11. double amount =
       Double.parseDouble((String)this.amountInput.getValue());
    this.peopleEJBRemoteListIncomeAbove1.setAmount(amount);
    this.peopleEJBRemoteListIncomeAbove1.refresh();
    
  12. When you dragged the listIncomeAbove method onto the data table, Java Studio Creator made this peopleEJBRemoteListIncomeAbove1 reference for you, which you can now use to tell it the amount you want to filter by, and then refresh the object (that will update the data in the table). It's that easy.
  13. Run it to see the results. At first, you will see a list of all of the people in the system (the income amount filter is 0 by default), but if you type in 100000 to the income above field and click return, it will filter down to two names with income above 100000.

Conclusion

Well, once again you barely scratched the surface of what is possible, but if you think about the ground covered in this article, it is quite impressive. You have put together an EJB API, deployed it to the App Server Instance in Java Studio Creator, consumed it in Creator, and then bound it to a control in a JSF page.

More to the point, you have done this without seeing a deployment descriptor, Home and Remote interface classes, JNDI lookup code, or anything else that might be considered tricky or confusing. The new EJB features in Java Studio Creator 2 truly do extend the component model and ease of use data bindings into the world of full EJB 2.1 architecture.

Many people are eagerly awaiting the release of EJB 3.0 to help simplify EJB development, but with suitable use of the right IDE tools, simple development using EJBs is available right now, I also look forward to EJB 3.0, but it's hard to imagine how much easier it will make things for the demo we have seen.

Download the source code for this article here and here.

About the Author

Dick Wall is a Lead Systems Engineer for NewEnergy Associates, A Siemens Company based in Atlanta, GA that provides energy IT and consulting solutions for decision support and energy operations. He can be reached for comment on this and other matters at dick.wall@newenergyassoc.com. He also co-hosts the Java Posse with Tor Norbye and Carl Quinn, a podcast devoted to Java News and Interviews, which can be found at http://javaposse.com.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date