This document describes the WebLogic EJB to JSP integration tool. Given an EJB jar file, the tool will generate a JSP tag extension library, whose tags are customized for calling the EJB(s) of that jar file. This document assumes at least some familiarity with both EJB and JSP.
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 EJB's, 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 invoking an EJB from a JSP page by removing the need for java code. Instead, the EJB is invoked using a JSP tag library that was 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/stateful session beans, and entity beans. The tag usage scenarios for each of these cases are slightly different, and are described below.
TopThe tool can be run in command-line mode, or else can be run in graphical mode. For all but the simplest of EJB's, The graphical tool is preferable.
The graphical tool is invoked like this:
java weblogic.servlet.ejb2jsp.gui.Main
Initially, no ejb2jsp project is loaded by the application. A new project may be created by selecting the File -> New menu item, browsing in the file chooser to an EJB jar file, and selecting it. Once initialized, ejb2jsp projects may be modified, saved, and reloaded later 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.
TopWhen 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, while it 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 above, when the EJB jar is loaded, the tool will try to find a source file called Trader.java. This file will then be parsed, and it will see 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 assumes that the source directory is the same directory where the EJB jar is located. If that isn't the case, it isn't a fatal error. After the new project is loaded, under the Project Build Options panel, you may adjust the EJB Source Path element to reflect the correct directory. You may 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 will look 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.
Note that access to the source files is not strictly necessary. Attribute names for each tag in a project can always be modified 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.
TopThis panel is used to set all of the parameters related to the local filesystem that are needed to build the project. You may specify the java compiler to use, the java package of the generated JSP tag handlers, and whether or not to keep the generated java code after a project build (this can sometimes be useful for debugging purposes).
This panel is also used 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, since a web application in WLS must be re-deployed before a jar file may 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 may 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.
TopSometimes, a project will fail to build because of one or more conflicts. This section describes the reasons for those errors, and how they may be resolved.
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 (e.g., "int" -> java.lang.Integer, etc).
TopEJB 2.0 allows for methods on the EJB home 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.
TopTypical usage of a "stateful" bean is to acquire an instance of the bean from the bean's Home, 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's home that corresponds to a find() or create() on the home. All EJB method tags contained within the find/create tag will operate on the bean instance found or created by the enclosing tag. If an method tag for a stateful bean is not enclosed by a find/create tag for its home, a runtime 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.
TopBy 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. Default attributes/parameters may be specified in the Attribute window. 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, suppose we 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, we would set the "Default Attribute Value" field to EXPRESSION, and enter "XYZ" (quotes included!) in the Default Expression field. The buy tag will then act as if the stockSymbol="XYZ" attribute were present, unless some other value were specified.
Or if we wanted 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, we would 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;
Since 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 things like 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 Exception. 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.