Chapter 17: Using Advanced EJB Techniques address =

July 3rd, 2009

Chapter 17: Using Advanced EJB Techniques address = info.address; emailAddress = info.email; country = info.country; phoneNumber = info.phoneNumber; } And that leaves us with the getCustomerInfo() method. This method is required to return an instance of CustomerValues so you need an instance to return! Either create it locally in the method, or use a global instance for the class. The global instance is the preferred option. Why? Won’t different callers end up overwriting the data that a previous caller requested? No. Remember that remote EJBs always pass data by value. That means that each time a method returns data, the caller ends up with a copy of the data you returned. Thus you can change information as much as you want, and each client will have his or her own individual copy. The final method implementation of your bean is: private CustomerValues customerInfo = new CustomerValues(); public CustomerValues getCustomerInfo() throws EJBException { customerInfo.customerId = customerId; customerInfo.name = userName; customerInfo.address = address; customerInfo.email = emailAddress; customerInfo.country = country; customerInfo.phoneNumber = phoneNumber; return customerInfo; } As you can see, there is not that much work required to convert a standard bean design to a high-performance version using value objects. So, if you know that you are going to have beans that are heavily used by your application and performance is a major consideration, value objects are a worthwhile change. Designing for local beans Looking at the opposite situation wherein the client and bean are held in the same VM the other approach applies. This time, instead of trying to corral all the data into a single reply, each piece of data is requested through a separate method. The disadvantages for the remote beans are the advantages in this situation: You need only to access data that you need rather than having to access all of it. In addition, you have the greatest chance of accessing the most up to date information (the bean may have changed its data between method calls if another client is also working with the same bean). For local beans, you want the methods that you provide to return primitive data whenever possible. This ensures the fastest possible communications and removes the overhead of copying data or allocating new class instances to return data. Earlier in the chapter, we mentioned that one of the restrictions on local beans is that they must pass a reference to the data to the client. Traditional code works the same way. For example, passing an array enables the receiver to change the contents of the array directly. In the context of remote beans, that array would be made as a copy of the original and passed to the client code. Any changes made in that array would be kept on the client and not reflected back at the server. With local beans, the opposite applies unless the local bean implementation takes explicit steps to make a copy of the data before returning it. 386

For reliable and cheap web hosting services please check tomcat web hosting website.

Chapter 17: Using Advanced EJB Techniques Now you

July 3rd, 2009

Chapter 17: Using Advanced EJB Techniques Now you need to provide variables that represent each of the fields. The simplest implementation is to just use a public variable per method that you had in your previous bean instance (this will horrify the OO-purist who would insist on having setter and getter methods!). This is how the class would now look with the addition of the public variables: public class CustomerValues implements Serializable { public int customerID; public String name; public String address; public String email; public String country; public String phoneNumber; public CustomerValues() { } } For your next step, you need to modify the bean’s remote interface to take advantage of this new class. Two options exist replace all the methods with a set/get method pair that just takes the CustomerValues class, or add it as an additional methods. Which choice you make is personal preference. For the purposes of this exercise, all the methods will be replaced by a single pair of set/get methods using the value object. Having made this decision, you can rewrite the remote interface to look like this: public interface Customer extends EJBObject { public CustomerValues getCustomerInfo() throws RemoteException; public void setCustomerInfo(CustomerValues) throws RemoteException; } Next you need to update the bean implementation class (you don’t need top do anything with the home interface) to reflect the changes in the remote interface. Due to the way you constructed the example in the previous chapter, the change in the implementation is quite simple. Start by deleting all of the methods that correspond to the old business methods and replace them with the stubs of the two new methods. public class CustomerEntityBean implements EntityBean { … public CustomerValues getCustomerInfo() throws EJBException { } public void setCustomerInfo(CustomerValues info) throws EJBException { } } Two methods to fill in, what do you do? Well, so long as you can copy the values from the values class to the internal cached variables, it really doesn’t matter what you do. So, let’s look at the setCustomerInfo method first: public void setCustomerInfo(CustomerValues info) throws EJBException { customerId = info.customerId; userName = info.name; 385

For high quality jboss hosting services please check jboss web hosting website.

Chapter 17: Using Advanced EJB Techniques If the

July 2nd, 2009

Chapter 17: Using Advanced EJB Techniques If the goal is to reduce network traffic as much as possible, you want to get your money’s worth each time you do make a request. If you are returning only one piece of information, you might as well return as much as possible. The design implications are quite clear: Don’t use a lot of methods that only return one value, and do use a few methods that return a lot of information in one hit. In EJB terminology, the class that returns all the data as a single item is called a Value Object. Note Remember that for any method that returns a class rather than a primitive type, the returned class must be serializable. If the class is not serializable, a RemoteException will be thrown. Implementing value objects in remote beans Let’s take our customer bean example as the basis for illustrating how to change an EJB to use value objects. In the previous chapter, you saw a bean declaration that looks like this: public interface Customer extends EJBObject { public int getCustomerID() throws RemoteException; public void setCustomerID(int id) throws RemoteException; public String getName() throws RemoteException; public void setName(String name) throws RemoteException; public String getAddress() throws RemoteException; public void setAddress(String addr) throws RemoteException; public String getEmail() throws RemoteException; public void setEmail(String addr) throws RemoteException; public String getCountry() throws RemoteException; public void setCountry(String code) throws RemoteException; public String getPhoneNumber() throws RemoteException; public void setPhoneNumber(String ph) throws RemoteException; } Notice how there are a lot of methods that all return one value. In the “Beans in the wild” section of the previous chapter, you saw how to integrate an EJB with a JSP or servlet. With what you now know about performance penalties, think about how slow that JSP will be to process and then display the contents of the Web page. Each one of those lines where you wrote data out to the page, either through a bean or custom tag, required a request across a network. That means your JSP using that model is going to be a real dog. The now obvious solution to this problem is to change the bean so that it now uses a single value object to fetch the values that your JSP needs. The role of the value object is to provide a very simple container for all those values that you would have previously fetched individually. Looking through the method calls above, that looks like you will need to deal with strings and ints. Creating a value object class starts with the normal class declaration. Because value objects are returned as parameters in a remote call, they need to satisfy the same rules as any other class that you may use they must be serializable. That makes the outline of your value object class look something like this: public class CustomerValues implements Serializable { public CustomerValues() { } } Note Remember that serializable objects require an explicit public, no-argument constructor. 384

For high quality java hosting services please check tomcat web hosting website.

Chapter 17: Using Advanced EJB Techniques An example

July 2nd, 2009

Chapter 17: Using Advanced EJB Techniques An example application to introduce local interfaces LocalProduct The next step is to provide the names of the classes that have the home and remote interfaces. Of course, you don’t have a remote interface this time, but a local interface. To describe these new capabilities, you replace the home and remote elements with local-home and local elements, respectively: LocalProductHome Customer After this point in the descriptor, the file looks the same. To complete the description, you will need to provide the following elements: LocalProductEntityBean
Bean ProductID True
Now the descriptor is complete, and you can roll the EAR file as before. Method-data granularity As with any non-trivial application, performance considerations are always important in the design process. When it comes to enterprise beans, you use a set of design considerations similar to that of any other remote-object technology, such as RMI or CORBA. For the purpose of these considerations, we make the very fundamental assumption that the client will be on a separate machine from the server. Each time you ask for data, the system has to ensure that you get the latest copy and must therefore require extra network traffic. The result is that a good designer will alter the way he or she makes data available to the client. Designing for remote beans When you are designing the code surrounding remote beans, the network is your primary concern. By placing a network between the user of the data and the source of the data, you create a lot of extra overhead: Requests must be sent and received, data must be written to and from the underlying stream, error detection/correction handling and many other tasks. As a result, the response time between asking for and receiving a piece of data is very long (potentially in the order of seconds for a heavily loaded system). As a programmer you will be very aware of performance issues in any application. It’s typically the number-one complaint we programmers have to deal with. If it takes a second or so every time a request is made to a bean, then reducing the number of time-consuming requests as much as possible certainly becomes a goal. What does this mean from a design perspective? 383

For high quality website hosting services please check java web hosting website.

Chapter 17: Using Advanced EJB Techniques Note the

July 1st, 2009

Chapter 17: Using Advanced EJB Techniques Note the lack of RemoteException that the remote version of the bean had to throw in the previous chapter. The remote product EJB is an entity bean that requires declarations of a number of finder methods. You will still need to write the finder methods for the local version, too: public LocalProduct findByPrimaryKey(ProductID id) throws FinderException; public List findByCategory(String cat, String name) throws FinderException; public List findAllInCategory(String cat) throws FinderException; Primary-key information is required for all entity beans. As you might have noticed in the preceding snippet, the code reuses as the primary-key class the ProductID class from the remote version. As the primary-key class is not dependent on any form of the EJB interfaces, you are free to use it wherever you like (even using the same class for different bean types). In this case, reusing the class gives you an advantage, because the local and remote beans represent the same data. Once you have completed the local interfaces, the rest of the writing process is the same as for remote beans. Local bean-implementation classes are still required to implement EntityBean or SessionBean interfaces as appropriate. This requirement does not change between local and remote versions. Using local beans The process of gaining access to a local bean is no different from the process of gaining a reference to a remote bean. The use of home and remote interfaces remains the same, and you still use JNDI to find the initial reference to the home interface. Of course, the most important difference between using local beans and using remote beans is that you can’t use a local bean in an environment such as a servlet or JSP. You can only use local beans in the same context (EJB container) as another bean. Apart from that consideration, all the code looks the same. To complete the picture of using local beans, this is what the code looks like in an environment such as another bean: InitialContext ctx = new InitialContext(); Object ref = ctx.lookup(”ejb/LocalProduct”); LocalProductHome home = (LocalProductHome)PortableRemoteObject.narrow(ref, LocalProductHome.class); ProductID id = new ProductID(some_id); LocalProduct product = home.findByPrimaryKey(id); Deploying local beans Deploying a local bean is the same as deploying any other bean. The various classes and the deployment descriptor must be wrapped into a JAR file and deployed to an appropriate server. Normally the vendor’s tools will take care of the complete process for you. Fill in the appropriate fields of the deployment wizard, and everything is taken care of. If you wish to roll your own, the only difference between remote beans and their local brethren is the element names used in the deployment descriptor. A deployment descriptor for a local bean starts with the same headers as a normal bean: 382

For reliable and cheap web hosting services please check tomcat web hosting website.

Chapter 17: Using Advanced EJB Techniques Figure 17-1:

July 1st, 2009

Chapter 17: Using Advanced EJB Techniques Figure 17-1: A UML depiction of the relationships among local interfaces, remote interfaces, and the bean implementation From the client perspective, there are no new interfaces to deal with. Now that the bean is local to the client, no method calls that you make will need to catch a RemoteException. Maintaining the status quo is the new AccessLocalException, which indicates that the client is not allowed to use this method because the method is not a local call (for example, because a remote client such as a JSP tried to access the bean). All the other exceptions remain the same, meaning that you will still need to deal with them from their respective method calls. Writing local beans You implement local beans using the same process you use for remote beans. First create the bean interface, then write the home interface, and finally the bean implementation itself. For illustrative purposes, we shall convert the product beans of the previous chapter. Starting with the bean interface, you need to write an interface that extends the EJBLocalObject interface. public interface LocalProduct extends EJBLocalObject Note To date, no naming conventions for local interfaces have been suggested, so in this blog we will start all local objects with the prefix Local to distinguish them from the remote versions. As with all bean interfaces you will need to provide a number of methods that allow access to the data. Unlike with the remote equivalent, because the bean is local, these methods are not required to throw any exceptions. So, taking the lead from the remote Product EJB, you add methods to the interface as follows: public int getProductID(); public void setProductID(int id); public String getName(); public void setName(String name); Moving along, the home interface requires you to extend the EJBLocalHome interface as follows: public interface LocalProductHome extends EJBLocalHome As with the remote home interfaces, you need to declare a number of create() methods, each of which throws a CreateException: public LocalProduct create() throws CreateException; public LocalProduct create(int id) throws CreateException; 381

For high quality website hosting services please check cheap web hosting website.

Chapter 17: Using Advanced EJB Techniques Requirements of

June 30th, 2009

Chapter 17: Using Advanced EJB Techniques Requirements of local beans Programming local beans requires applying a few restrictions over and above those required by ordinary EJBs. These extra requirements are the result of the fact that local beans are a purely server-side construct that is, an EJB client such as a JSP or servlet will never see these beans. Local beans must exist in the same JVM as the beans that use them. This restricts their usage and deployment capabilities to whatever the user bean needs. All data is live between the local bean and the bean using it (pass-by-reference). That is, the user ends up with a live copy of the local bean, and both should assume that any data passed back and forth will be live rather than a copy. For example, an array of values from the local bean to the user bean will be a single piece of data, so the user should not write new values into the array for fear of corrupting the state of the local bean. Any bean may be a local bean. Session and entity beans are valid local clients. It is possible for a bean implementation class to have both local and remote definitions, but it is not encouraged. As any sort of bean can be a local bean, you can add a lot of flexibility to your application. That is, local beans are not a new type of bean, just an extended (or restricted, depending on your viewpoint) set of capabilities layered over the existing bean types. The choice between local beans and remote beans is highly dependent on your application. If you look at the example beans in the previous chapter, you will see that nothing really lends itself to the use of a remote bean. For example, the mailer bean must be available to every client so that the clients can send e-mail. The same goes for customer and order information, because these beans are accessed by the Web component of the application. With more analysis and a bigger set of data, our example application could make use of local beans for example, in keeping more detailed product information, like various models of the same product. Tip Sometimes it is worth having both local and remote beans for the same information. For example, if the example application had a new super-bean that performed order processing, it would be worth having a local bean that represented customer and product information in addition to the remote versions that the Web components are using. So don’t think that if you have a remote bean you can’t use a local bean for the same information and vice versa. Interfaces for local beans With each new capability comes a new set of interfaces to implement. For local beans, two new interfaces exist: the home interface (EJBLocalHome) and the bean object (EJBLocalObject). Even though you must implement these interfaces as you do the remote beans, you have a lot less work to do. Local interfaces still perform and require the same tasks as remote interfaces. You can’t take shortcuts just because your bean is now local. Accessing beans still means going through a home interface as well as taking the usual steps, such as calling create methods. If you are still confused about the various relationships, have a look at Figure 17-1, which illustrates the details using UML. 380

For reliable and cheap web hosting services please check cheap web hosting website.

Chapter 17: Using Advanced EJB Techniques Overview EJBs

June 30th, 2009

Chapter 17: Using Advanced EJB Techniques Overview EJBs provide a huge range of capabilities to the end user. In the previous chapter, we introduced you to the basics of writing the most common forms of EJBs. Those techniques are useful in many situations and form the core of any EJB-based application. However, there are many more useful techniques yet to be introduced, and as we alluded to in the previous chapter, there are more types of EJBs to cover. The techniques covered in this chapter are aimed at the true enterprise-level system a system wherein you have a central system providing hundreds of services with many different client-application types. As the first step in moving on to larger systems, we show you how to extend for better performance the basic classes that you already have from the previous chapter. Basic entity and session beans can only provide you with so much, and the EJB specification team realized this. The J2EE v1.3 specification includes the new EJB 2.0 standard, which provides for a huge increase in the number of and, more importantly, the interaction between, beans and databases. Along with this new specification come a lot of new languages and concepts, so hold on, we have a lot to cover! Extending Enterprise Beans Within the basic bean structures that we introduced in the previous chapter, you have a lot of room to explore different strategies in the enterprise application. Most of the new techniques we introduce in this section revolve around getting more out of your existing application. While you can take these approaches and bolt them into the basic design, it will be more beneficial for you to revisit the complete architecture as a result of having learned to use these new tools. Local beans for better performance At the top of the list of EJB users’ wish lists has been the ability to allow beans to be more efficient in communication. Prior to the EJB 2.0 specification, a bean was a bean. They all acted the same. It did not matter whether the bean client was used on the same machine as the bean server or on another one halfway around the world: All the underlying connections took the same approach of using the network to access the bean and its methods, even if they did exist on the same server and even in the same JVM. Many large-scale system designs took the EJB philosophy and applied it to everything not only was the outside world presented with an EJB interface, but internally the design used beans that were never seen in the outside world. The effect was a severe performance penalty for beans that referenced other beans residing on the same machine. In order to fix this problem, the new specification introduces the concept of local beans. These are beans that are never seen outside of the server context, which allows the server to make a number of performance optimizations (for example, making direct method calls rather than using RMI-IIOP). Note Local beans still maintain the concept of client and server usage. For local beans, the only permitted client is another bean residing on the same machine. Beans on other machines cannot be clients of the local bean. 379

For reliable and cheap web hosting services please check tomcat web hosting website.

Chapter 16: Introducing Enterprise JavaBeans out.write(cust.getAddress()); out.write(”"); out.write(”Country:

June 29th, 2009

Chapter 16: Introducing Enterprise JavaBeans out.write(cust.getAddress()); out.write(”
“); out.write(”Country: “); out.write(cust.getCountry()); out.write(”
“); out.write(”Email: “); out.write(cust.getEmail()); out.write(”
“); out.write(”Phone: “); out.write(cust.getPhoneNumber()); out.write(”
“); } catch(Exception e) { out.write(”There was an error processing the customer”); out.write(e.getMessage()); } return SKIP_BODY; } That’s all you need to do to integrate EJBs with custom tags in JSPs. As you can see from the two different examples, there is really not that much difference in difficulty between the approaches. Which you choose is more a matter of personal and/or company preferences. Summary During this chapter, you received an extensive introduction to the core of the J2EE specification Enterprise JavaBeans. You could reasonably argue that the rest of the specifications in J2EE are there to support the requirements for EJBs. As you can see, EJBs are a huge topic, and so far we have barely scratched the surface of what you can do with them (stay tuned for more in the next chapter!). However, what we have covered so far is enough to get you up and running on most simple and medium-complexity projects. We gave you: An introduction to the concepts and terminology of EJBs. Instructions for writing basic session and entity beans. Instructions for integrating EJBs within other J2EE systems, such as servlets and JSPs. 378

For high quality java hosting services please check tomcat web hosting website.

Chapter 16: Introducing Enterprise JavaBeans public void release()

June 29th, 2009

Chapter 16: Introducing Enterprise JavaBeans public void release() { } } From this outline, you can see most of the standard features relating to custom tags. There’s the constructor, the doStartTag() method (both of which require some code) and the methods for processing the customerID attribute. Of interest here is how you process the attribute information. Notice that the code has elected to take the value from the JSP as a String and then process it internally. You may provide alternative classes, such as Integer in the TLD rather than the default String. You are still missing the important part: interacting with the EJB. You should remember from the other examples the basic process that is needed fetch the home interface and then access the bean information. As usual, Java gives you plenty of options, but this is the one we recommend. Use the constructor to load the home interface of the Customer EJB. You would use the constructor rather than fetching the home interface in the doStartTag() method. The reason for this is for efficiency. The home interface is a common item, and you don’t need to be fetching it every single time. So place that code in the constructor: public CustomerTag() { try { Context initial = new InitialContext(); Object objref = initial.lookup(”ejb/Customer”); home = (CustomerHome)PortableRemoteObject.narrow( objref, CustomerHome.class); } catch(Exception e) { // Just print the error out System.err.println(”Error finding home interface” + e); } } If you allocate items in the constructor, you should naturally follow it up with an implementation of the release() method so that you can free them. public void release() { home = null; } That leaves the doStartTag() method for you to fill in. You should probably be able to guess exactly what needs to be done now. In this method, you fetch the EJB corresponding to the provided customer ID and then write out some formatted text to the output like this: public int doStartTag() { JspWriter out = pageContext.getOut(); try { CustomerID id = new CustomerID(customerId); Customer cust = home.findByPrimaryKey(id); out.write(”Customer ID: “); out.write(customerId); out.write(”
“); out.write(”Name: “); out.write(cust.getName()); out.write(”
“); out.write(”Address: “); 377

For high quality java hosting services please check java web hosting website.

Chapter 16: Introducing Enterprise JavaBeans That completes the

June 28th, 2009

Chapter 16: Introducing Enterprise JavaBeans That completes the code you need in order to integrate a JSP and EJB into the one action. Simply deploy the code according to your J2EE environment tools, and you’re up and running. Using beans in JavaServer Pages with custom tags An alternate way of using EJBs within a JSP is through the use of custom tags. You have already been introduced to writing custom tags for JSPs in the “Using Custom Tags” section of Chapter 4. Because of this, we’ll skip the basics here and concentrate on the work you need to do to integrate the tag library code with EJBs. Tag libraries are an extremely flexible way of creating content. There are many options for creating a custom tag, so we’ll just stick with a simple one. From this example, you can expand to include the more complex tag types. For this example, you will write a simple tag that displays the customer information. Input to this tag will be the customer ID, and the output will be a list of the information known about that customer. Let’s start the example with the JSP tag declaration: <%@ taglib uri="J2EEBible-ejblib.tld" prefix="ejb" %> The tag declaration follows the same form as you saw back in Chapter 4. This should not be surprising for you as a custom tag is a custom tag, no matter what that tag contains or where it sources its data. Our custom tag requires a single parameter that is the customer ID. Here we’ve just hardcoded the value, but in your real bean, that may be provided by a text field in a lead-up page prior to this one. Working with custom tags and EJBs has all of the interesting code in the tag class. Because the tag is a single element, with no body, you only need to extend the TagSupport class. Without a closing tag, you then only need to provide the doStartTag() method. In addition, the usual get and set methods are required to process the attribute customerID. This is the outline of what your custom tag class will need to look like: public class CustomerTag extends TagSupport { private CustomerHome home; private int customerId; public CustomerTag() { ???? } public int doStartTag() { ???? return SKIP_BODY; } public String getCustomerID() { return Integer.toString(customerId); } public void setCustomerID(String id) { customerId = Integer.parseInt(id); } 376

For high quality website hosting services please check tomcat web hosting website.

Chapter 16: Introducing Enterprise JavaBeans Note that the

June 28th, 2009

Chapter 16: Introducing Enterprise JavaBeans Note that the customer is fetched from the database each time, which allows the bean to be explicitly updated each time the user fetches the page. Most Web users check updates by checking their details after having edited them. This ensures that they will always have the right values. On to the JSP source. This follows the same patterns that you learned in Chapter 4. First include the bean in your JSP and add a scriptlet to force the execution, as follows: The wildcard is used on the setProperty tag to tell the JSP to update all properties all the time. Next is the command to execute for this when the page is requested: <% customerBean.processRequest() %> The way in which you process bean actions depends on the page you want. For a simple page to edit the customer details, use the following example code. (Note that this is just standard JSP code for accessing any JavaBean. You won’t have to do anything special to the JSP source in order for it to use EJBs.)

Show customer details

” > Customer ID: “
Name: ” >
Address: ” >
Country: ” >
Email: ” >
Phone: ” >

375

For high quality jboss hosting services please check jboss web hosting website.

Chapter 16: Introducing Enterprise JavaBeans home = (CustomerHome)PortableRemoteObject.narrow(objref,

June 27th, 2009

Chapter 16: Introducing Enterprise JavaBeans home = (CustomerHome)PortableRemoteObject.narrow(objref, CustomerHome.class); } catch(Exception e) { // Just print the error out System.out.println(”Error finding home interface” + e.getMessage()); } } } Next, you need some methods to process information coming from the JSP. First you will need a method to take the action performed by the JSP. Remember that two JSPs will be accessing this bean instance one to fetch the original data and one to update it and so the bean needs to know which action has been requested. Action information, as it always comes from a HTTP request, will be a string, as shown in the following code: public void setAction(String act) { action = act; } public String getAction() { return action; } You have to store data internally for these methods, because at the time that these values are set, the code is not be doing the processing. Processing is the responsibility of the next step the implementation of the processRequest() method. Why have we included an extra method? Well, because the process requires setting or reading quite a few properties (name, phone number, e-mail, and so on), your bean code cannot assume that any one setter is the last call to happen. The only way that it can be guaranteed is to make use of an extra trigger scriptlet that is part of the JSP source, which we haven’t covered yet. The code for our JavaBean will work for both showing the initial data and allowing the user to modify data. The processRequest() method looks at the value of the action parameter and acts accordingly, as this example shows: public void processRequest() { if(action.equals(”show”)) { CustomerID id = new CustomerID(customerId); Customer cust = home.findByPrimaryKey(id); userName = cust.getName(); address = cust.getAddress(); country = cust.getCountry(); phoneNumber = cust.getPhoneNumber(); email = cust.getEmail(); } else if(action.equals(”update”)) { CustomerID id = new CustomerID(customerId); Customer cust = home.findByPrimaryKey(id); cust.setName(userName); cust.setAddress(address); cust.setCountry(country); cust.setPhoneNumber(phoneNumber); cust.setEmail(email); } } 374

For reliable and cheap web hosting services please check tomcat web hosting website.

Chapter 16: Introducing Enterprise JavaBeans Given these different

June 27th, 2009

Chapter 16: Introducing Enterprise JavaBeans Given these different usage patterns, we recommend the following rules of thumb for dealing with beans in a servlet environment: Establish references to all the home interfaces you are going to need during the init() method. Create and remove bean instances on the fly during the processing of the service() or doXXX methods. Make sure you free the reference and call remove() on the bean before exiting from these methods if using session beans, to avoid overburdening the EJB server. Try to minimize the servlet design to use as few beans as possible. Don’t create one big super-servlet to process all request types. Smaller servlets mean fewer home interfaces to keep around, and a much easier time load balancing both servlets and beans. Remember the roles of stateful session beans and how servlets work. Stateful session beans don’t work as well in a servlet environment as the other types do. This is mainly because a different servlet instance from the one that created the bean in the first place may be called to process a given set of state information. Using beans in JavaServer Pages with JavaBeans JavaServer Pages (JSP) represent an interesting challenge when you are attempting to integrate with EJBs. This is because of the way a JSP accesses Java-based information through either custom tags or scriptlets. Unlike applications and servlets, a JSP does not contain long-term code that can be used to buffer home interfaces or even direct references to EJB objects. Instead, you must go through an intermediary in the form of a normal JavaBean that can perform these tasks for us. Cross-Reference Chapter 4 provides an introduction to JSPs and how to use them with JavaBeans. Using EJBs with servlets may take one of two paths. The simplest path is to use a JavaBean to reference the EJB. Alternatively, you can use custom tags to directly represent bean information. The examples will start with the JavaBean option. The first step in the integration of EJBs and JSPs is writing a JavaBean wrapper class. This wrapper class is responsible for acquiring the home interface, creating the target bean, processing the information, and then making the results available to the JSP. Because the wrapper is a normal JavaBean, the code is required to follow all the normal rules for beans including naming conventions for methods. As for the EJB part, because the JavaBean is just a wrapper, the methods will simply mirror the methods in the EJB. Let’s start the example by creating a page that will edit a customer’s details. After entering the user ID, this page will present the page with all the editable items on it. The user can then edit fields and submit the details back. Ignoring the start page, a single JavaBean for both dynamic pages will represent the customer in the database. This JavaBean will be named CustomerBean. The process of writing the class follows the normal procedure: You declare the class and a public constructor. Because a JavaBean has no equivalent of the servlet init() method, you will need to fetch the home interface in the constructor, as follows: public class CustomerBean { private CustomerHome home; public CustomerBean() { try { Context initial = new InitialContext(); Object objref = initial.lookup(”ejb/Customer”); 373

For high quality java hosting services please check java web hosting website.

Chapter 16: Introducing Enterprise JavaBeans Beans in the

June 26th, 2009

Chapter 16: Introducing Enterprise JavaBeans Beans in the wild Although the basics of using all types of EJBs in code are common to all users of EJBs, how do the individual user application types make use of the beans? Surprisingly, there isn’t much difference, so take a look at each of the areas in which you are likely to find an EJB popping up its head. Using beans in ordinary applications Ordinary applications, such as command-line apps, don’t require any extra work on the part of the programmer. Most of the work has to do with getting the updates out of the database and into a collection of text fields and tables, which really does not involve the bean code at all. For example, if you have a text field, this example will obtain the customer’s ID, find the related bean, and put the customer’s address into the text field: JTextField tf = new JTextField(40); … try { InitialContext ctx = new InitialContext(); Object objref = initial.lookup(”ejb/Customer”); CustomerHome home = (CustomerHome)PortableRemoteObject.narrow(objref, CustomerHome.class); String cust_id_str = idTextField.getText(); int id = Integer.parseInt(cust_id_str); Customer customer = home.create(id); tf.setText(customer.getName()); } catch(Exception e) { System.err.println(”Something died…:” + e.getMessage()); } Tip How you run a command-line application depends on the environment you are in. To learn how to run a command-line app using the J2EE reference implementation, please read Appendix A. Using beans in servlets As far as EJBs are concerned, operating in a servlet environment is no different from operating as a command line. At its most simple, just grab the initial context, ask for the home interface, and start working with the bean(s) you need. Usage patterns of beans in a servlet environment is quite different from usage patterns of beans in an application. Applications tend to have (relatively) long lives working on a single piece of data. Servlets, on the other hand, have very short and sharp usages of beans. This contrast means that the ways in which you handle the respective interfaces will be quite different. An application may grab the home interface and grab a bean instance almost immediately afterward, while a servlet will grab the home interface at startup and then sit around waiting for a request to be processed before asking for a bean. Cross-Reference You’ll find an introduction to writing servlets in Chapter 3. 372

For high quality website hosting services please check cheap web hosting website.

Chapter 16: Introducing Enterprise JavaBeans Requesting a bean

June 26th, 2009

Chapter 16: Introducing Enterprise JavaBeans Requesting a bean from the home interface With the home interface in hand, you must next request it to produce a bean. As you saw earlier in this chapter, the way to request this action is to use one of the create() methods of the bean. Naturally, the method you choose is dependent on the type of bean you have and the methods you provided in the home interface. Creating a new bean just means calling one of the create methods and making sure you catch all the exceptions, as follows: try { Mailer mailer = home.create(); } catch(RemoteException ee) { // do something } catch(CreateException ce) { // do something here too } Calling business methods on the bean Calling business methods on your newly fetched bean is just like calling any other Java method, particularly those involving RMI. Even passing in other bean references is no big deal. Again, just watch out for exceptions, including any custom exceptions you may have included. This time, the example looks at using the Customer bean to ask for the customer’s name. try { String name = customer.getName(); System.out.println(”The customer’s name is ” + name); } catch(RemoteException ee) { // do something } Cleaning up and removing bean references Once your application has finished using the bean, you should notify the EJB container that it is no longer needed. This frees the server to reclaim the bean and pass it on to the next user that needs it. You notify the server that you no longer need the bean reference using one of the remove() methods. You can do this in one of two places: on the home interface or directly from the bean. With most applications, it is probably simpler to use the direct method on the bean’s remote interface directly, as follows: mailer.remove(); Remember, after you have called the remove() method, the reference you have is dead. It cannot be used to communicate with the bean. Attempting to do so will cause an exception. If you want to use the bean again, you will need to ask the home interface to create you another one. Calling the remove() method is only suitable for the session beans as it forces the container to delete the bean. When remove() is called, the ejbRemove() method is called on your bean implementation class. You’ve seen the code that the ejbRemove() method calls. For an entity bean, that means deleting the object from the underlying data store. So, while calling remove() on a session bean is perfectly fine, it is probably not the effect you are looking for entity beans. If you no longer need the bean reference, the simplest way of releasing its resources is to just set your client’s reference to null. 371

For high quality website hosting services please check tomcat web hosting website.

Chapter 16: Introducing Enterprise JavaBeans Using Enterprise Beans

June 25th, 2009

Chapter 16: Introducing Enterprise JavaBeans Using Enterprise Beans on the Client Side Using EJBs in client code does not require the large amounts of coding that you’ve seen so far. In fact, using them in any application is a breeze and one of the seductive aspects of using the J2EE environment. With a well-written set of beans, it becomes easy to reuse them and create more and more applications for your company. You can use EJBs in any environment in which you can use normal Java code. EJBs are typically used in a Web-based environment with servlets or JSPs, but applets and standalone applications are also suitable targets for beans. Non-standard systems, such as point-of-sale devices and kiosks, are perfect environments for bean technology and represent standard places that you might find a Java application making use of them. Looking up and using beans Regardless of what sort of environment you will be using that is accessing the beans, the basic procedure is the same and consists of the following steps: 1. Look up the bean’s home interface. 2. Ask the home interface to create or find a particular bean. 3. Make calls of the bean. 4. Remove the reference, notifying the server of this so that it may reclaim the instance. Looking up a bean Finding a bean really starts with trying to find a bean’s home interface. Remember that it is the home interface that enables you to create and manage bean instances. Locating the home interface is as simple as using your old friend JNDI to perform a lookup of the name you specified in the ejb-name tag of the deployment descriptor. To look up the home interface, start with the normal JNDI InitialContext setup. After obtaining the context information, you need to perform the lookup. The name that you go looking for is not just the string from the ejb-name tag, but must also have the prefix ejb/. Finally, as the lookup() method returns an Object, you will need to cast it to the necessary home interface. For example, to locate the home interface for the mailer session bean, you write the following code (ignoring exceptions): InitialContext ctx = new InitialContext(); Object ref = ctx.lookup(”ejb/Mailer”); MailerHome home = (MailerHome)PortableRemoteObject.narrow(ref, MailerHome.class); The last line here is interesting. Note that you cannot just directly cast the returned reference from the lookup method. Because classes can be stubs for an interface and the RMI capabilities, we recommend that you take this extra verification step. The narrow() method performs a check on the returned object to make sure that it can be cast correctly to the class represented by the second argument. Although it is possible to skip this step, we highly recommend that you perform it in order to ensure that your application functions well with the rest of the world (and that the right exceptions are easily caught on the client side) the EJB specification also states that you should perform the narrow operation 370

For reliable and cheap web hosting services please check tomcat web hosting website.

Chapter 16: Introducing Enterprise JavaBeans Customer CustomerHome Customer

June 25th, 2009

Chapter 16: Introducing Enterprise JavaBeans Customer CustomerHome Customer CustomerEntityBean
Bean CustomerID True Tip All the items inside the XML file are case-sensitive, including the content between tags. For example, True is not the same as true. All these tags are defined in the DTD for the deployment descriptor. Notice how the tags basically match the configuration information we’ve been showing you throughout the chapter. A session bean has a tag that says whether it is stateful or stateless, for example. Thus you can change the behavior of the bean without needing to change the source files. The only item in the preceding file we have to explicitly point out is the ejb-name tag. This tag specifies the name under which this bean will be registered in JDNI. Take note of this, as you are going to need to know it shortly, when looking up the bean on the client. The information shown in the preceding deployment descriptor is an absolutely minimal file for the two bean types. Many more configuration options exist, most of which are for topics we have not covered yet. To learn more, we recommend reading the DTD source itself, as it contains huge numbers of comments about how to use each tag. Rolling the JAR file With the deployment descriptor written, you now need to create the basic bean JAR file. Creating the JAR file is just like creating a standard JAR you will need the class files and optional configuration information such as a manifest file and, of course, the deployment descriptor. Tip The manifest file in an EJB JAR file performs the same task it performs for standard applications. If your bean refers to other JAR files that contain code necessary for the implementation, use the Class-Path entry of the manifest to refer to those extra files. To create the JAR file, change directory to the root directory of your compiled code. Next create a directory called META-INF and copy it in your ejb-jar.xml file. If you need a manifest file, copy that in, too. Next run the standard JAR command to create your EJB archive. For example (assuming your company’s code starts with the root package name com): classes$ jar cf my_ejb.jar META-INF com Now you have a ready-to-deploy bean JAR file on your server. From this point on, consult your server-tool documentation to learn how to proceed. But now you have finished writing the Enterprise JavaBean code. All that is left to do is create an application that will use the bean. 369

For high quality website hosting services please check java web hosting website.

Chapter 16: Introducing Enterprise JavaBeans Web client

June 24th, 2009

Chapter 16: Introducing Enterprise JavaBeans Web client archive When you use servlets or JSPs, they will be placed into a file called a Web ARchive or WAR file. This is just a JAR file with a few extras: It keeps all the Web pieces of the application, such as HTML files, images, and so on. Application archive Wrapping all these other files into a single deployable unit is the Enterprise Archive or EAR file. Again, this is just a JAR file with a collection of extras: It contains all the preceding archive files and more deployment information. We haven’t covered the relevant topics regarding most of these file types yet. So for the rest of this section we are going to concentrate on building a file suitable for the beans alone. Writing a deployment descriptor Deployment descriptors are XML files, so they are relatively easy to write in almost any tool. The job of a deployment descriptor is to describe the configuration of a bean, with the idea of letting the bean code do the real functional work, and let the configuration file provide all the details about who, what, and where to find things. Cross-Reference If you are unfamiliar with XML, you’ll find a thorough introduction to the topic in Chapters 10 and 11. You start writing a deployment descriptor by creating a file named ejb-jar.xml and adding the standard XML header and DOCTYPE statement: Next, you place the opening tag, as defined by the preceding declaration. Inside that tag, you start by listing descriptions and the list of beans included in this JAR file. The DTD definition of the ejb-jar element is as follows: Of all of these elements, the most useful (and the only required tag) is the enterprise-beans element that contains the listing of all the beans in this archive file. So take a look at a typical file that might represent the example application from this chapter: An example application to introduce EJBs Mailer MailerHome Mailer MailerSessionBean ejb/MailHandler Stateless
Container
368

For high quality jboss hosting services please check jboss web hosting website.

Chapter 16: Introducing Enterprise JavaBeans Filling in the

June 24th, 2009

Chapter 16: Introducing Enterprise JavaBeans Filling in the missing spaces You’ve seen how to create a remote and home interface, as well as how to write bean implementations, but how do the interfaces talk with the bean implementation? Ah, trade secret! The J2EE specification does not specify how this communication works, only that “communication happens.” After defining the interfaces, you need to run the code through a deployment tool for that server. The server will take the files, process them, and build the appropriate classes to implement them. This all happens behind the scenes. This processing step consists of two smaller steps: automatically building the implementation classes of the interfaces, and then defining configuration information. You will no doubt have noticed that the process of writing a bean described in this chapter did not include writing implementations of the home and remote interfaces. Fulfilling this requirement is the job of the EJB container environment, because this allows each EJB server vendor to build a system optimized for their environment. In earlier versions of EJB, this meant that you could not complete your bean implementation and have different client and server software. If you used Websphere on the server, you had to use Websphere for the client, too. The EJB 2.0 specification changes this by making sure that a client and server can now be different pieces of software. Internally, during the deployment process the deployment tool will normally take your home and remote interfaces and build the implementation classes. These implementation classes built an RMI system (with the CORBA variant RMI-IIOP) that produced a client and server set of stub classes. These classes are then compiled and placed into JAR files on the client and server machines, along with a file called a Deployment Descriptor. Note Although EJB 2.0 specifies that the vendor must support RMI-IIOP communications, it also allows the use of proprietary protocols. When packaging the bean, make sure that you understand which form of communication you are generating. A bean that does not allow IIOP cannot be deployed across multiple EJB container providers. The bean files The process of deploying EJBs uses a number of files in addition to the Java code you have written so far. We have already mentioned the deployment descriptor a file for describing the setup information of a bean. In addition to this are files that describe a particular bean and its classes, the client code that uses beans (say a servlet or JSP for Web use or the application code for standalone use), and the complete EJB application, all in a single file. You will find the files just described in every EJB-server system. The following list gives a more complete description of each: Deployment Descriptor This XML file is used to describe most of the properties of the bean. At the most simple level, you need to know the class names for each of the files, while on the other end of the scale, you can include security information about who can call what methods (we cover callers and roles in Chapter 17). Bean JAR file Each bean must exist in a JAR file. Although this sounds draconian, it is because of the way the deployment descriptors work, and so the bean code of home, remote, and implementation classes all exist in the one file. Of course, each JAR file may contain more than one set of bean classes. If you have common library code that is accessed by many beans, these classes can still be located outside individual bean archives. Application client archive Standalone client application code exists in its own JAR file, if needed. The client code does not need to be in a JAR file, but at the least the code that implements the client stubs for the home and remote interfaces will be. 367

For high quality website hosting services please check cheap web hosting website.