bea.com | products | dev2dev | support | askBEA

Download Docs | Site Map | Glossary
Search

Programming WebLogic JSP

Using the WebLogic EJB to JSP Integration Tool

The following sections describe how to use the WebLogic EJB-to-JSP integration tool to create JSP tag libraries that you can use to invoke EJBs in a JavaServer Page (JSP). This document assumes at least some familiarity with both EJB and JSP.

- Overview of the WebLogic EJB-to-JSP Integration Tool

- Basic Operation

- Interface Source Files

- Build Options Panel

- Troubleshooting

- Using EJB Tags on a JSP Page

- EJB Home Methods

- Stateful Session and Entity Beans

- Default Attributes

Overview of the WebLogic EJB-to-JSP Integration Tool

Given an EJB jar file, the WebLogic EJB-to-JSP integration tool will generate a JSP tag extension library whose tags are customized for calling the EJB(s) of that jar file. From the perspective of a client, an EJB is described by its remote interface. For example:

>     public interface Trader extends javax.ejb.EJBObject {
>       public TradeResult buy(String stockSymbol, int shares);
>       public TradeResult sell(String stockSymbol, int shares);
>     }

For Web Applications that call EJBs, the typical model is to invoke the EJB using Java code from within a JSP scriptlet (<% ... %>). The results of the EJB call are then formatted as HTML and presented to the Web client. This approach is both tedious and error-prone. The Java code required to invoke an EJB is lengthy, even in the simplest of cases, and is typically not within the skill set of most Web designers responsible for HTML presentation.

The EJB-to-JSP tool simplifies the EJB invocation process by removing the need for java code. Instead, you invoke the EJB is invoked using a JSP tag library that is custom generated for that EJB. For example, the methods of the Trader bean above would be invoked in a JSP like this:

>     <%@ taglib uri="/WEB-INF/trader-tags.tld" prefix="trade" %>
>     <b>invoking trade: </b><br>

>     <trade:buy stockSymbol="BEAS" shares="100"/>

>     <trade:sell stockSymbol="MSFT" shares="200"/>

The resulting JSP page is cleaner and more intuitive. A tag is (optionally) generated for each method on the EJB. The tags take attributes that are translated into the parameters for the corresponding EJB method call. The tedious machinery of invoking the EJB is hidden, encapsulated inside the handler code of the generated tag library. The generated tag libraries support stateless and stateful session beans, and entity beans. The tag usage scenarios for each of these cases are slightly different, and are described below.

Basic Operation

You can run the WebLogic EJB-to-JSP integration tool in command-line mode using the following command:

java weblogic.servlet.ejb2jsp.Main

or graphical mode. For all but the simplest EJBs, the graphical tool is preferable.

Invoke the graphical tool as follows:

>       java weblogic.servlet.ejb2jsp.gui.Main

Initially, no ejb2jsp project is loaded by the Web Application. Create a new project by selecting the File -> New menu item, browsing in the file chooser to an EJB jar file, and selecting it. Once initialized, you can modify, save, and reload ejb2jsp projects for future modification.

The composition of the generated tag library is simple: for each method, of each EJB, in the jar file, a JSP tag is generated, with the same name as the method. Each tag expects as many attributes as the corresponding method has parameters.

Interface Source Files

When a new EJB jar is loaded, the tool also tries to find the Java source files for the home and remote interfaces of your EJB(s). The reason is that, although the tool can generate tags only by introspecting the EJB classes, it cannot assign meaningful attribute names to the tags whose corresponding EJB methods take parameters. In the Trader example in "Overview of the WebLogic EJB-to-JSP Integration Tool" on page 2, when the EJB jar is loaded, the tool tries to find a source file called Trader.java. This file is then parsed and detects that the buy() method takes parameters called stockSymbol and shares. The corresponding JSP tag will then have appropriately named attributes that correspond to the parameters of the buy() method.

When a new EJB jar is loaded, the tool operates on the premise that the source directory is the same directory where the EJB jar is located. If that is not the case, the error is not fatal. After the new project is loaded, under the Project Build Options panel, you can adjust the EJB Source Path element to reflect the correct directory. You can then select the File -> Resolve Attributes menu to re-run the resolve process.

When looking for java source files corresponding to an interface class, the tool searches in both the directory specified, and in a sub-directory implied by the interface's java package. For example, for my.ejb.Trader, if the directory given is C:/src, the tool will look for both C:/src/Trader.java and C:/src/my/ejb/Trader.java.

Access to the source files is not strictly necessary. You can always modify attribute names for each tag in a project by using the tool. However, parsing the source files of the EJB's public interface was developed as the quickest way to assign meaningful attribute names.

Build Options Panel

Use this panel to set all parameters related to the local file system that are needed to build the project. Specify the Java compiler, the Java package of the generated JSP tag handlers, and whether to keep the generated Java code after a project build, which can be useful for debugging.

You can also use this panel to specify the type of tag library output you want. For use in a J2EE web application, a tag library should be packaged one of two ways: as separate class files and a Tag Library Descriptor (.tld) file, or as a single taglib jar file. Either output type is chosen with the Output Type pull-down. For development and testing purposes, DIRECTORY output is recommended, because a Web Application in WebLogic Server must be re-deployed before a jar file can be overwritten.

For either DIRECTORY or JAR, the output locations must be chosen appropriately so that the tag library will be found by a web application. For example, if you wish to use the tag library in a web application rooted in directory C:/mywebapp, then the DIRECTORY classes field should be specified as:

>     C:/mywebapp/WEB-INF/classes

and the DIRECTORY .tld File field should be something like:

>     C:/mywebapp/WEB-INF/trader-ejb.tld

The Source Path, described earlier, is edited in the Build Options panel as well. The Extra Classpath field can be used if your tag library depends on other classes not in the core WebLogic Server or J2EE API. Typically, nothing will need to be added to this field.

Troubleshooting

Sometimes, a project fails to build because of errors or conflicts. This section describes the reasons for those errors, and how they may be resolved.

- Missing build information One of the necessary fields in the Build Options panel is unspecified, like the java compiler, the code package name, or a directory where the output can be saved. The missing field(s) must be filled in before the build can succeed.

- Duplicate tag names When an EJB jar is loaded, the tool records a tag for each method on the EJB, and the tag name is the same as the method name. If the EJB has overloaded methods (methods with the same name but different signatures), the tag names conflict. Resolve the conflict by renaming one of the tags or by disabling one of the tags. To rename a tag, navigate to the tag in question using the tree hierarchy in the left window of the tool. In the tag panel that appears in the right window, modify the Tag Name field. To disable a tag, navigate to the tag in question using the tree hierarchy in the left window of the tool. In the tag panel that appears in the right window, deselect the Generate Tag box. For EJB jars that contain multiple EJBs, you can disable tags for an entire bean may as well.

- Meaningless attribute names arg0, arg1... This error occurs when reasonable attribute names for a tag could not be inferred from the EJB's interface source files. To fix this error, navigate to the tag in question in the project hierarchy tree. Select each of the attribute tree leaves below the tag, in order. For each attribute, assign a reasonable name to the Attribute Name field, in the panel that appears on the right side of the tool.

- Duplicate attribute names This occurs when a single tag expecting multiple attributes has two attributes with the same name. Navigate to the attribute(s) in question, and rename attributes so that they are all unique for the tag.

Using EJB Tags on a JSP Page

Using the generated EJB tags on a JSP page is simply a matter of declaring the tag library on the page, and then invoking the tags like any other tag extension:

>     <% taglib uri="/WEB-INF/trader-ejb.tld"
>      prefix="trade" %>
>     <trade:buy stockSymbol="XYZ" shares="100"/>

For EJB methods that have a non-void return type, a special, optional tag attribute "_return", is built-in. When present, the value returned from the method is made available on the page for further processing:

>     <% taglib uri="/WEB-INF/trader-ejb.tld"
>       prefix="trade" %>
>     <trade:buy stockSymbol="XYZ"
>      shares="100" _return="tr"/>
>     <% out.println("trade result: " + tr.getShares()); %>

For methods that return a primitive numeric type, the return variable is a Java object appropriate for that type (for example, "int" -> java.lang.Integer, etc).

EJB Home Methods

EJB 2.0 allows for methods on the EJB home interface that are neither create() or find() methods. Tags are generated for these home methods as well. To avoid confusion, the tool prepends "home-" to the tags for each method on an EJB's home, when a new project is loaded. These methods may be renamed, if desired.

Stateful Session and Entity Beans

Typical usage of a "stateful" bean is to acquire an instance of the bean from the bean's Home interface, and then to invoke multiple methods on a single bean instance. This programming model is preserved in the generated tag library as well. Method tags for stateful EJB methods are required to be inside a tag for the EJB home interface that corresponds to a find() or create() on the home. All EJB method tags contained within the find/create tag operate on the bean instance found or created by the enclosing tag. If a method tag for a stateful bean is not enclosed by a find/create tag for its home, a run-time exception occurs. For example, given the following EJB:

>     public interface AccountHome extends EJBHome {

>       public Account create(String accountId, double initialBalance);
>       public Account findByPrimaryKey(String accountID);
>         /* find all accounts with balance above some threshold */
>       public Collection findBigAccounts(double threshold);
>     }

>     public interface Account extends EJBObject {
>       public String getAccountID();
>       public double deposit(double amount);
>       public double withdraw(double amount);
>       public double balance();
>     }

Correct tag usage might be as follows:

>     <% taglib uri="/WEB-INF/account-ejb.tld" prefix="acct" %>
>     <acct:home-create accountId="103"
>       initialBalance="450.0" _return="newAcct">
>      <acct:deposit amount="20"/>
>      <acct:balance _return="bal"/>
>      Your new account balance is: <%= bal %>
>     </acct:home-create>

If the "_return" attribute is specified for a find/create tag, a page variable will be created that refers to the found/created EJB instance. Entity beans finder methods may also return a collection of EJB instances. Home tags that invoke methods returning a collection of beans will iterate (repeat) over their tag body, for as many beans as are returned in the collection. If "_return" is specified, it is set to the current bean in the iteration:

>     <b>Accounts above $500:</b>
>     <ul>
>     <acct:home-findBigAccounts threshold="500" _return="acct">
>     <li>Account <%= acct.getAccountID() %>
>          has balance $<%= acct.balance() %>
>     </acct:home-findBigAccounts>
>     </ul>

The preceding example will display an HTML list of all Account beans whose balance is over $500.

Default Attributes

By default, the tag for each method requires that all of its attributes (method parameters) be set on each tag instance. However, the tool will also allow "default" method parameters to be specified, in case they are not given in the JSP tag. You can specify default attributes/parameters in the Attribute window of the EJB-to-JSP tool. The parameter default can come from an simple EXPRESSION, or if more complex processing is required, a default METHOD body may be written. For example, in the Trader example in "Overview of the WebLogic EJB-to-JSP Integration Tool" on page 2, suppose you want the "buy" tag to operate on stock symbol "XYZ" if none is specified. In the Attribute panel for the "stockSymbol" attribute of the "buy" tag, you set the "Default Attribute Value" field to EXPRESSION, and enter "XYZ" (quotes included!) in the Default Expression field. The buy tag then acts as if the stockSymbol="XYZ" attribute were present, unless some other value is specified.

Or if you want the shares attribute of the "buy" tag to be a random number between 0-100, we would set "Default Attribute Value" to METHOD, and in the Default Method Body area, you write the body of a Java method that returns int (the expected type for the "shares" attribute of the "buy" method):

>     long seed = System.currentTimeMillis();
>     java.util.Random rand = new java.util.Random(seed);
>     int ret = rand.nextInt();
>     /* ensure that it is positive...*/
>     ret = Math.abs(ret);
>     /* and < 100 */
>     return ret % 100;

Because your default method bodies appear within a JSP tag handler, your code has access to the pageContext variable. From the JSP PageContext, you can gain access to the current HttpServletRequest or HttpSession, and use session data or request parameters to generate default method parameters. For example, to pull the "shares" parameter for the "buy" method out of a ServletRequest parameter, you could write the following code:

>     HttpServletRequest req =
>      (HttpServletRequest)pageContext.getRequest();
>     String s = req.getParameter("shares");
>     if (s == null) {
>       /* webapp error handler will redirect to error page
>        * for this exception
>        */
>       throw new BadTradeException("no #shares specified");
>     }
>     int ret = -1;
>     try {
>       ret = Integer.parseInt(s);
>     } catch (NumberFormatException e) {
>       throw new BadTradeException("bad #shares: " + s);
>     }
>     if (ret <= 0)
>       throw new BadTradeException("bad #shares: " + ret);
>     return ret;

The generated default methods are assumed to throw exceptions. Any exceptions raised during processing will be handled by the JSP's errorPage, or else by the registered exception-handling pages of the Web Application.