| ★ wanayoo — archive 1999 http://www-4.ibm.com/software/ebusiness/buildapps/understand.html | Nouvelle recherche | Portail wanayoo |
|
|
| ||||||||||||||||
| |||||||||||||||
You have decided to use the Internet and/or Intranet to put your business processes on-line. And, you have wisely chosen IBM's Application Framework for e-business (an excellent introduction to which can be found at http://www.ibm.com/developer/features/framework/framework.html) as your platform. Now what?
The Application Framework for e-business addresses many important issues in the development of e-business solutions. The Framework is prescriptive; it maximizes the use of Internet and other open standards and protocols versus proprietary technologies. However, developing in the context of the Framework still leaves a choice of technologies (among those Internet and open systems) which can dramatically affect the performance, robustness and usability of a solution. After reading this paper, you will better understand the many choices of client and server technologies.
The first major section, Thin Client, is a detailed discussion of available client side technologies. At the end of each subsection you will find recommendations regarding specific client side technologies and their use in relationship to the IBM Application Framework for e-business.
The second major section, Web Application Model, addresses the Web application server components of an e-business application. Various technologies are shown via concrete implementation examples for the interaction controller, UI logic and business logic components. The examples are drawn from an on-line banking demonstration program called "Freeside". The Freeside demo is an example of an e-business application developed using the IBM Application Framework for e-business. You can benefit from the analysis and design work done by the developers of this application through looking at the provided code listings and reading the discussions of the technology choices.
In the spirit of providing something for everyone, you will get some helpful information development guidelines for creating your web pages in Appendix A.
The thin client consists of a Java enabled Web browser and a Java Virtual Machine (JVM), a TCP/IP stack and (potentially) an encryption library. With this capability, the client provides three key benefits for e-business applications based upon IBM's Application Framework for e-business.
There are several different client technologies, such as HTML, DHTML, Java applets, and JavaScript, available to the developer. The design of the client side of a Web application varies considerably depending upon which technology is employed. The choice of client side technology must be made in concert with the server side technology choice. In fact, the technology choice must be made as part of an end-to-end design.
The table below identifies the technologies that currently support the
most clients (left) to the fewest clients (right):
| Web Client | HTML 3.0 with Forms | Java 1.0.2 | Simple DHTML with JavaScript 1.1 | Java 1.1 | Complex DHTML with Non-standard JavaScript |
| Netscape 3 | Supported | Supported | Supported | Not available | Not available |
| Netscape 4 | Supported | Supported | Supported | Most functions | Support with JavaScript 1.2 |
| Internet Explorer 3 | Supported | Supported | Supported | Not available | Not available |
| Internet Explorer 4 | Supported | Supported | Supported | Most functions | Support with JScript and VBScript |
| HotJava | Supported | Supported | Not Available | Supported | Not Available |
| Network Computers (Java Based) | Supported | Supported | Not Available | Supported | Not Available |
Many e-business applications are assembled strictly using HTML. This has the advantage that the client side Web application can be a simple HTML browser, enabling a less capable client to execute an e-business application. Because most Web browsers can display HTML version 3.2, this is the lowest common denominator for building the client side of an application. A good introduction to HTML can be found at http://www.w3.org/MarkUp/.
The HTML specification defines UI elements for text with various fonts and colors, lists, tables, images, and forms (text fields, buttons, checkbooks, radio buttons). These elements are adequate to display the user interface for most applications. The disadvantage, however, is that these elements have a generic look and feel, and they lack customization. As a result, some e-business application developers augment HTML with other UI technologies to enhance the visual experience.
ECMA, a European standards body, has published a standard (ECMA-262) which is based on JavaScript (from Netscape) and JScript (from Microsoft) called ECMAScript. The ECMAScript standard defines a core set of objects for scripting in Web browsers. JavaScript is a cross platform, object oriented scripting language which is a superset of ECMAScript. It is comprised of the core ECMAScript objects that run on both Web browsers and servers, as well as a set of unique client specific and server specific objects. The core objects include array, date, math, number, and string. On the client side, there are document, form, frame, and window objects. These core objects enable the manipulation of HTML documents (checking form fields, submitting forms, and creating dynamic pages), and the manipulation of the browser (directing the browser to load other HTML pages, display messages, etc.).
To address various needs of the client side of a Web application, Netscape and Microsoft have built upon ECMAScript in their implementations of JavaScript 1.2 by adding new browser objects. Because Netscape's and Microsoft's extensions to the standard are different from each other, any script written must detect the browser being used, and select the correct statements to run. You can detect the browser information using the navigator object as shown in Listing 1.
However, versions 3.0 and earlier of both Netscape and Microsoft browsers don't support these new extensions. Thus, to ensure that a script can be run on most browsers use JavaScript1.1 which contains the elements of ECMAScript version one. You can find the ECMAScript Language Specification at http://www.ecma.ch/stand/ECMA-262.htm for the latest ECMAScript version information.
Another advantage of DHTML is that it increases the level of functionality of an HTML page through a document object model and event model. The document object model (see http://www.w3.org/DOM/) enables scripting languages such as JavaScript to control parts of the HTML page. For example, text and images can be moved about the screen, and hidden or shown, under the command of a script. Also, scripting can be used to change the color or image of a link when the mouse is moved over it, or to validate a text input field of a form without having to send it to the server.
Unfortunately there are several disadvantages with using DHTML. The greatest of these is that two different implementations, Netscape and Microsoft, exist. A small, basic set of functionality is common to both, but differences appear in most areas. The significant difference is that Microsoft allows the content of the HTML page to be modified by using either JScript or VBScript, while Netscape allows the content to only be manipulated (moved, hidden, shown).
A second disadvantage with DHTML is that only the 4.0 versions and above of the Netscape and Microsoft Web browsers support it. Depending upon the composition of the clients accessing an e-business application, some customers could be excluded.
Because of browser compatibility issues, complex DHTML using browser specific extensions is not recommended in environments where mixed levels and brands of browsers are present unless the application can be made browser and version sensitive. However, complex DHTML may be appropriate in intranet environments where there is more control over installed browser versions.
A Java applet is a program written in Java that is downloaded from the Web server and run on the Web browser. The applet to be run is specified in the HTML page using an APPLET tag:
<APPLET CODEBASE="/mydir" CODE="myapplet.class" width=400 height=100> <PARAM NAME="myParameter" VALUE="myValue"> </APPLET>
For this example, a Java applet called "myapplet" will run. An effective way to send data to an applet is with the use of the PARAM tag. The applet has access to this parameter data and can easily use it as input to the display logic. To learn more about applets take a look at http://www.javasoft.com/applets/index.html.
Java can also request a new HTML page from the Web application server. This provides an equivalent function to the HTML FORM submit function. The advantage is that an applet can load a new HTML page based upon the obvious - a button being clicked, or the unique - the editing of a cell in a spreadsheet.
A characteristic of Java applets is that they seldom consist of just one class file. To the contrary, a large applet may reference hundreds of class files. Making a request for each of these class files individually can tax any server and also tax the network capacity. However, packaging all of these class files into one file reduces the number of requests from hundreds to just one. This optimization is available in many Web browsers in the form of either a JAR file or a CAB file. Netscape and HotJava support JAR files simply by adding an ARCHIVE="myjarfile.jar" variable within the APPLET tag. Internet Explorer uses CAB files specified as an applet parameter within the APPLET tag. In all cases, executing an applet contained within a JAR/CAB file exhibits faster load times than individual class files. While Netscape and Internet Explorer use different APPLET tags to identify the packaged class files, a single HTML page containing both tags can created to support both browsers. Each browser simply ignores the other's tag.
A disadvantage of using Java applets for UI generation is that the required version of Java must be supported by the Web browser. Thus, when using Java, the UI part of the e-business application will dictate which browsers can be used for the client side e-business application. As discussed before this disadvantage may not be significant for many intranet applications
A second disadvantage of Java applets is that any classes such as widgets and business logic that are not included as part of Java must be loaded from the Web server as they are needed. If these additional classes are large, the initialization of the applet may take from seconds to minutes, depending upon the speed of the connection to the internet.
Because of the above shortcomings the use of Java applets is not recommended in environments where mixed levels and brands of browsers are present. Small applets may be used in cases where HTML UI elements are insufficient to express the semantics of the Web application user interface. If it is necessary to use an applet, care should be taken to include UI elements that are core Java classes whenever possible. Larger applets may be appropriate for intranet applications where users are LAN attached.
While we believe that HTML is the appropriate technology for many thin client e-business applications, this does not mean that an application based on the Framework consists of static, hardcoded, hand written HTML pages with an occasional CGI-BIN program. Just the opposite! The next section will describe how HTML is used and generated via server side technologies such as Java Server Pages and servlets.
The best way to think of a Web application is as a series of interactions between a client and a particular Web site. The entire Web interaction process begins with a single page displayed in the browser. The user clicks on a button or link on the page causing a request to be sent to the Web application server. The request is processed on the Web application server and a new page is sent back showing the results of the request and presenting buttons or links for the next request. Thus the Web application consists of a set of processing steps or interactions, each of which gets a request generated from a page and each of which must produce a response in the form of a page that will serve as the input for subsequent interactions.
If we examine a single interaction at the next level of detail, we see a common set of processing requirements that can be nicely mapped to the classical model/view/controller paradigm as follows:
Observing this mapping is important because experience has shown that the different types of logic frequently require different development skills and tools, and often need to evolve on different schedules. To do this, it is critical to maintain a clean separation between the different types of program logic. The Framework recommends that the business logic be wrapped with JavaBeans that it calls command beans. A command bean should usually represent a single function supported by the business logic. Its usage paradigm is: create the bean; initialize by setting the bean's properties; perform by calling the bean's methods; and inspect by getting the values of the bean's properties. Using command beans of this form provides several benefits including:
The remainder of this section will discuss the Web application elements of interaction controller, UI logic, and business logic in more detail. The business logic section will focus on the use of command beans.
The Framework supports the development of interaction controller logic using either Java servlets or Java Server Pages (JSP) technology. Both of these implementation mechanisms have significant advantages over using CGI-BIN or Web server plugins. You will need to decide whether to use JSPs or servlets or both in your interaction controller. Another design issue is the cardinality of the relationship between interactions and interaction controllers (reference [2] contains a detailed discussion of this issue.)
The chief advantage Java Server Pages have over Java servlets is that they are closer to the presentation medium. A Java Server Page is an HTML page. It contains all the HTML tags that Web authors are familiar with, and presents them in the same way as ordinary hypertext, allowing an author to leverage favorite HTML design tools. Certainly, one could write a servlet to generate complex, beautiful Web pages, but layout tools such as NetObject's Fusion make the job much easier.To learn more about JSPs visit http://www.javasoft.com/products/jsp/.
A JSP is HTML, but may also contain fragments of Java code selecting which pieces of the layout are visible and which are not. These code fragments may call out to JavaBeans or Enterprise JavaBeans (see [Enterprise JavaBeans note]) to access reusable components and back-end data. The code fragments may be reinforced by expressions, fragments of Java code that return some value (e.g. a property on a bean.) If the amount of code on a page is relatively small, that is, the page is primarily for presentation, JSP offers a way to focus on the artistic creation of the page by compiling the page into a Java servlet for the author.
Servlets make the Java code much easier to read and therefore maintain when the amount code is proportionately larger than the amount of HTML on the page. Unlike a JSPs, servlets are compiled before being usable in the runtime. They do not require a full application server runtime during the compile phase. Because servlets are deployed as .class files they are more attractive than JSPs in instances where you do not want the source code of your Web application available on the Web server.
There are compelling reasons to use the JSP wherever possible, factoring business logic into JavaBeans, and leaving JSP scripting to simple flow of control and bean property accesses. This enables rapid development of JSP, and the maintenance benefits of the JavaBean component model.
The following sections describe typical functions performed by the interaction controller in more detail with code examples taken from the Freeside demo.
Input validation can occur on the Web application server implemented in JSP or servlet form in Java; however, a performance gain can often be realized if this function is performed in JavaScript on the client preventing unnecessary exchanges between the client and the Web application server. An example of using JavaScript to verify a bank transfer is shown in Listing 2.
An e-business application may wish to obtain login information from users that have not properly logged into the application. There is a variety of choices for assigning user privileges: Web servers, such as Apache, have authentication and access control services; most current operating systems have authentication and access control services; many applications "roll their own" authentication services. The example in Listing 3, of the "roll your own" variety, shows JSP logic which redirects a user to the login page if the user request does not contain a session object or if the session object does not contain required user authentication information (see [Session object note] for a description of the session object.)
This is where command beans come into play. Command beans form a stable boundary between the business logic and user interface. The interaction controller will map input from the user request to command bean properties. The command bean hides the business logic and data behind its properties allowing the business logic to evolve independently of the user interface and vice versa. The interaction controller may execute multiple command beans to gather output which it will then route to the UI logic.
The environment for command execution is called the command target. Command targets can be located on a local server which simply calls the command bean's perform method, or located on a remote server which requires serializing the command bean and shipping it to a remote server for execution. However, the interaction controller only needs to be aware of the command bean interface to execute commands. There is a detailed discussion of the components of the command bean infrastructure in the Separation of UI and Business Logic section.
The code segment in Listing 4 shows the mapping of the user ID from the customerInfo object to the "CustomerID" input property of the viewAccounts command bean.
Once a command bean has executed it is the job of the interaction controller to invoke the proper user interface logic to convey the result information to the user. The code segment in Listing 5 executes the transfer funds command bean and invokes the correct user interface logic via the sendRedirect method of the response object.
In many cases, the interaction controller will pass dynamic data to the UI logic for formatting. In other cases, the UI logic will invoke business logic directly to obtain dynamic data. It makes sense to have the interaction controller pass the data when it has already obtained it and when the data is an essential component of the contract between the interaction controller and the UI logic. In other cases, the data needed is not an essential part of the interaction, and can be obtained independently by inserting calls to business logic directly in the UI logic.
Once the UI logic has obtained the dynamic data, either from the interaction controller, or via its own logic, it will typically format the data. This can be done several ways. The simplest mechanism is where the data is formatted using simple scripting inside the display page. An alternative is to develop reusable script or Java object formatting components that will take a data set and return formatted HTML.
The code segment in Listing 6 generates HTML to serve to the client based on the results of the execution of the viewAccounts command bean. The viewAccounts output property which is an array of account information beans is displayed in a table.
In production environments where HTML coding and JSP coding are handled by two different individuals, it's a good idea to separate the Java code from the HTML as much as possible. If the Java is intermixed with the HTML, the HTML coder might inadvertently modify the Java. Or vice versa.
There are 3 basic ways to separate JSP code from HTML:
<TD>
<%
ContentGenerator co = new ContentGenerator("15", "phydeaux", 0);
%>
<%= co.getHTML() %>
</TD>
Use of the JSP BEAN tag has all the advantages of calling external methods plus the added advantage of adding structure to the relationship between the Java bean and the JSP. The BEAN tag lends itself better to tooling than the first method mentioned above because the BEAN tag is an HTML construct with strict syntax.
Here is an example of using the BEAN tag.
<TD>
<BEAN varname="cgb"
type ="com.ibm.ContentGenBean"
introspect="yes"
beanName="com.ibm.ContentGenBean">
</BEAN>
<%= cgb.getHTML() %>
</TD>
The above methods restrict you to Java. Use of Callpage allows you to load a separate JSP. This method lends itself to more course grained applications where the grain size is a JSP.
Here is an example of using Callpage.
<%
com.sun.server.http.HttpServiceResponse httpServiceResponse =
(com.sun.server.http.HttpServiceResponse) response;
%>
...
<TD>
<%
httpServiceResponse.callPage("/freeside/c_fromAccount.jsp", request);
%>
</TD>
The business logic part of an interaction is isolated from the details of Web technology. As a result, it is valuable to consider the interface between the Web parts of the interaction (interaction controllers and UI logic) and the business logic.
The business logic part of a Web application is the piece of code ultimately responsible for satisfying client requests. As a result, business logic must address a wide range of potential requirements which include ensuring transactional integrity of application components, maintaining and quickly accessing application data, supporting the coordination of business workflow processes, and integrating new application components with existing applications. To address these requirements and help facilitate the development of business logic on the Web application server, the Framework provides the following core services:
A detailed discussion of the core Framework services is beyond the scope of this paper. A detailed discussion of the Framework services can be found at http://www.ibm.com/developer/features/framework/framework.html.
Command beans provide a standard way to invoke a business logic request using a single round-trip message. A command bean is a JavaBean that encapsulates a single request to a target server (i.e., the server where the command is to be executed). The target server can be the same JVM as the client or a separate JVM.
The command bean infrastructure allows a command to be executed within the environment of a target server, so that multiple accesses by the command to server resources avoids distributed overhead. Any server can be a target if it supports Java access to its resources and provides a protocol to copy the command bean between a Web application JVM and the command server JVM.
Command beans allow the server side of the Web application to be partitioned into efficient units of interaction. The Web application parts (i.e. interaction controller and UI logic) are independent of the style of the command bean's implementation and independent of where the command bean is physically executed.
The figure titled "Command Bean Infrastructure" shows the internal components that comprise the command bean execution environment. Command beans that execute locally (i.e. in the same JVM as the Web application) simply implement the Command interface. If a command bean is to execute remotely on another server it implements the TargetableCommand interface which is an extension of the Command interface that allows for remote execution; this is done by extending the TagetableCommandImpl class. Regardless of whether the command bean executes locally or remotely the JSP/servlet executes the command bean in the same way.
The steps in a command bean's execution are:
The following sections describe in detail command instantiation, the command bean interface and the relationship between command beans and EJB.
MyCommand myCommand = new MyCommand();
MyCommand myCommand =
(MyCommand) Beans.instantiate(null, beanName);
where the beanName is either a class or instance name.
MyCommand myCommand = (MyCommand) factory.create(...);
where parameters can be used to determine the class or bean name.
Because these different ways to instantiate each have advantages that fit different scenarios, command beans do not specify how it must be done.
The command bean interface (see Listing 7) provides the set of methods common to all commands that the Web application uses to control the life cycle of a command bean. Input and output data for a command are passed via JavaBean properties. The following describes these methods:
public void setXXX(XXX xxx);
These methods are not part of the command bean interface because they are different for each command class.
public boolean isReadyToCallPerform();
This method is part of the command bean interface.
public void perform() throws CommandException;
The perform method will not work until all of the required input properties have been set (i.e., it is in the "initialized" state.) This method moves the command from the initialized state to the "executed" state. This method is part of the command bean interface.
public YYY getYYY();
These methods will not work until the perform method has been called (i.e., it is in the "executed" state). These methods are not part of the command bean interface because they are different for each command class.
public void reset();
This resets the output properties to the values they had prior to the perform method being called (e.g., null or 0). This method is part of the command bean interface.
An obvious question is why not use IIOP to SessionBeans to accomplish the same objective as commands. The answer is that commands have the following advantages:
The overhead of 1 and 2 can often be done once for many SessionBean instances. However, there are still three round-trip messages required per instance.
On the other hand, command beans provide an EJBCommandTarget shown in Listing 8 using a CommandServerEntityBean shown in Listing 9. An EntityBean is used instead of a SessionBean so many different transactions can access the same instance and this instance has the only distributed object stub required in the Web application JVM. This instance is gotten once at server startup and subsequently cached inside EJBCommandTarget. This allows each logical request to the EJB server to cost only a single message, because the overhead in steps 1, 2, 3 and 5 above are factored out and done only once, which amortizes their cost over many command bean executions.
The CommandTarget extends java.rmi.Remote, so that it can potentially be an EJBObject (either SessionBean or EntityBean). This allows the case where the TargetableCommand.setCommandTarget parameter is an EJB.
The business logic of a Web application often accesses data in a database. EJB EntityBeans are a convenient way to wrap the relational database layer in an object layer, hiding the complexity of database access. Because a single business task may involve accessing several tables in a database, modeling rows in those tables with EntityBeans makes it easier for command beans to manipulate the data. The Freeside banking demo has several database tables representing such data as accounts, customers, funds transfers, etc. Each table is represented by an EJB EntityBean. The code in Listing 10 implements the AccountBean.
The AccountBean uses a convenience object called a databean. The databean is a JavaBean used to create a non-transactional copy of the data of the EntityBean which owns it. The code in Listing 11 implements the AccountDataBean. Command beans using the AccountBean, such as the ViewAccounts command bean in Listing 6, will actually retrieve output data as AccountDataBean objects.
This paper has addressed a wide variety of client and server technologies related to creating an e-business application. A couple of factors bare repeating here:
With the above two design concepts and a better understanding of the technology choices for e-business application development you can use the IBM Application Framework for e-business to your best advantage.
While website and Web application design is a highly volatile and personal topic, below are presented some general guidelines. Special circumstances may justify breaking some of these "rules".
This is less critical for an intranet application running over a
100Mb Ethernet than for a web-based application running over a modem, but
there is no profit in the unnecessary waste of bandwidth.
If a website consists of several large sub-areas, one option is to develop a "variation" on the central "theme" for each sub-area.
The goal here is to let the user know when they are within your website/application
environment. A common technique is to build a set of templates for the
website/application and customize them as needed.
One way to put this into practice is to avoid the "Big GIF At The Top"
syndrome, where the page is brought up in the browser and the user is expected
to wait while a 75K GIF image of a corporate logo is slowly loaded.
Note that even graphics which do not have an appropriate text description (such as a page decoration image) should at the very least use ALT="". For example, the text-only browser Lynx will display the following
<img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Fdecor.gif&y=1999" height=50 width=50>as
[IMAGE]But with the proper ALT tag
<img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Fdecor.gif&y=1999" height=50 width=50 alt="">it displays as
In this case, displaying a blank space in the document is less
confusing than displaying the text string [IMAGE].
No browser currently available does a particularly good job of expanding/contracting an image. To change the size of an image, use a graphics editor such as Photoshop to adjust the size. Additionally, if the image is made smaller, the resulting image file will be smaller and thus there will be some bandwidth savings.
Exception: it is okay to use arbitrary HEIGHT and WIDTH values to expand or contract single-color graphic images. For example, a common technique is to construct a 1-by-1 pixel GIF image where the pixel color is set to be transparent, and use this image to fill a given space:
<img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Fempty.gif&y=1999" height=28 width=14 alt="">
FRAMEs also tend to add an additional layer of complexity
to a website or web application. Make sure that this additional complexity
is justified.
An exception may be made for an intranet environment where the plug-in is a well-documented requirement.
Session object: A session is a series of requests originating from the same user, at the same browser. The Web server can maintain state information about sessions. The session state is accessed through a session object.
Use the getSession method of the HttpServletRequest object to obtain a session. When you first obtain the HttpSession object, a unique session ID is created and typically sent back to the browser as a cookie. Each subsequent request from this user (at the same browser) passes the cookie. The session ID is used to find the user's existing HttpSession object.
After a session is established, you can add and retrieve
user-defined data to the session. The HttpSession object has
methods similar to those in java.util.Dictionary for adding,
retrieving, and removing arbitrary Java objects.
[Back]
Enterprise JavaBeans (EJB): EJBs are distinguished from JavaBeans in that they are non-visual, designed to be installed on a server, and accessed remotely by a client. EJBs have a deployment descriptor (similar to JavaBeans properties). The deployment descriptor includes the primary key of the EJB (entity Beans only), the home interface and the remote interface.
There are two types of Enterprise JavaBeans:
A typical session Bean has the following characteristics:
A typical entity Bean has the following characteristics:
Typically an entity Bean is used for information that has to survive system crashes, while in session Beans, the data is transient and does not survive when the client's browser is closed. For example, a shopping cart contains information that may be discarded uses a session Bean, and an invoice issued after the purchase of the items is an entity Bean. One other difference is that an entity Bean very often makes direct calls on a database.
To learn more about Enterprise JavaBeans visit http://www.javasoft.com/products/ejb/index.html.
[Back]
//Create browser object
var browser = new Object();
//Determine browser major version
browser.version = parseInt(navigator.appVersion);
//Determine if running Netscape or IE
browser.isNetscape = false;
browser.isIE = false;
if (navigator.appName.indexOf("Netscape") != -1)
browser.isNetscape = true;
else if (navigator.appName.indexOf("Microsoft") != -1)
browser.isIE = true;
[Back]
<script>
// verifyInput is a convenience function that consolidates
// inputs and delegates to helper functions.
function verifyInput(amount, toAccountObject, fromObject) {
return verifyAmountInput(amount) &&
verifyAccountSelection(toAccountObject, fromObject);
}
// verifyAmount determines if the transfer amount is a valid
// positive number.
function verifyAmountInput(amount ) {
var newAmount = parseFloat(amount);
if (newAmount > 0 && newAmount == amount) {
return true;
}
alert("The number " + amount + " your entered is not a " +
"valid amount! \nPlease enter a positive number! ");
return false;
}
// verifyAccountSelection finds the selected accounts and
// ensures that to and from are different.
function verifyAccountSelection(toAccountObject,
fromAccountObject) {
var to_account = "";
var from_account = "";
for (var i = 0; i < toAccountObject.options.length; i++) {
if (toAccountObject.options[i].selected) {
to_account = toAccountObject.options[i].value;
}
}
for (var i = 0; i < fromAccountObject.options.length; i++) {
if (fromAccountObject.options[i].selected) {
from_account = fromAccountObject.options[i].value;
}
}
if (to_account == from_account) {
alert(" Please check your accounts selection! " +
"\nMake sure they are not the same account!" );
return false;
}
return true;
}
</script>
[Back]
<%
// try to get the session object from the request object
HttpSession session = request.getSession(false);
// construct a partial URL
String urlString = JSPUtil.getPreferredHttpScheme() + "://" +
request.getServerName() + "/freeside/";
// if there is no session or the session is new
// route the user to the login screen
if (session == null || session.isNew()) {
response.sendRedirect(urlString + "login.jsp");
return;
}
// try to get the user authentication info from the session
CustomerDataBean customerInfo =
(CustomerDataBean) session.getValue("customer");
// a null customerInfo indicates the user is not authenticated
// route the user to the login screen
if (customerInfo == null) {
response.sendRedirect(urlString + "login.jsp");
return;
}
%>
[Back]
<%
// instantiate a viewAccounts command bean
ViewAccounts viewAccountsCommand = new ViewAccounts();
// assume authentication is complete, retrieve the user ID
// and set the CustomerID property
viewAccountsCommand.setCustomerID(customerInfo.getID());
// ask the command manager to execute the command.
try {
viewAccountsCommand = (ViewAccounts)
viewAccountsCommand.perform();
} catch (Throwable e) {
out.println("<PRE>");
e.printStackTrace(out);
out.println("</PRE>");
}
%>
[Back]
<%
int transferFrom = -1;
int transferTo = -1;
double amount = 0.00;
try {
String transferFromString = request.getParameter("transferFrom");
String transferToString = request.getParameter("transferTo");
String amountString = request.getParameter("amount");
// here is an example of input validation done in Java
if (transferFromString == null ||
transferToString == null ||
amountString == null) {
// invalid input, display the account balance page
response.sendRedirect(urlString + "viewBalance.jsp?");
return;
}
// retrieve the request data
transferFrom = Integer.parseInt(transferFromString);
transferTo = Integer.parseInt(transferToString);
amount = Double.valueOf(amountString).doubleValue();
TransferFunds command = new TransferFunds();
// set the command properties from the request data
command.setDepositToAccountID(transferTo);
command.setWithdrawalFromAccountID(transferFrom);
command.setAmountToTransfer(amount);
// ask the command manager to execute the command.
command = (TransferFunds) command.perform();
} catch (CommandException e) {
e.printStackTrace();
String errorMessage =
"Sorry! Insufficient funds transfer! " + " Please try again!";
// transfer failed, re-display transfer page
response.sendRedirect(urlString + "transfer.jsp?errorMessage=" +
URLEncoder.encode(errorMessage));
return;
}
String successMessage= "Your funds transfer has been posted!";
// transfer succeeded, show account balance page with success message
response.sendRedirect(urlString + "viewBalance.jsp?successMessage=" +
URLEncoder.encode(successMessage));
%>
[Back]
<%
// create the view account command bean and set the input property
ViewAccounts viewAccounts = new ViewAccounts();
viewAccounts.setCustomerID(customerInfo.getID());
try {
// ask the command manager to execute the command.
viewAccounts = (ViewAccounts) viewAccounts.perfrom();
// populate the accounts array from the Accounts output property
AccountDataBean[] accounts = viewAccounts.getAccounts();
%>
<TABLE cellspacing=3 cellpadding=0 border=0 >
<TR>
<TD align=right><img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Fl_account.jpg&y=1999" border=0 alt="Account">
</TD>
<TD><img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Femp.gif&y=1999" width=8 height=1 alt="">
</TD>
<TD align=right><img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Fl_balance.jpg&y=1999" border=0 alt="Balance">
</TD>
<TD><img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Femp.gif&y=1999" width=8 height=1 alt="">
</TD>
</TR>
<%
FieldPosition fieldPosition = new FieldPosition(0);
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(Locale.US);
// loop through the account information displaying properly
// formatted data. Note that the table row tags are part of
// the loop construct dynamically generating the results table.
for (int i = 0; i < accounts.length; i ++) {
AccountDataBean account = accounts[i];
double balance = account.getBalance();
String formattedBalance =
currencyFormat.format(balance,
new StringBuffer(),
fieldPosition).toString();
%>
<TR>
<TD align=center bgcolor="#666666">
<FONT face="sans-serif"><%= account.getDescription() %></FONT></TD>
<TD><img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Femp.gif&y=1999" width=8 height=1 alt=""></TD>
<TD align=right bgcolor="#666666">
<FONT face="sans-serif"><%= formattedBalance %></FONT>
</TD>
<TD><img SRC="/old?u=http%3A%2F%2Fwww-4.ibm.com%2Fsoftware%2Febusiness%2Fbuildapps%2Fimages%2Fimages%2Femp.gif&y=1999" width=8 height=1 alt=""></TD>
</TR>
<%
}
} catch (Throwable e) {
e.printStackTrace();
}
%>
</TABLE>
[Back]
package com.ibm.util.command;
import java.io.*;
/**
* A command encapsulate a business logic task.
* This Command interface provides the client interface for the
* most generic form of command, which is the contract between the command
* client and the command implementation.
* The TargetableCommand and CompensatableCommand interfaces offer
* additional features.
* The TargetableCommandImpl abstract class provides a runtime
* for command execution, as well as the contract
* between the command runtime and the command writer.
* <p>
* Commands provide the following advantages over conventional
* client-server interaction:
* <ul>
* <li>They provide a simple uniform way to call business logic,
* regardless of the programming style used for the business logic
* (eg, EJB, JDBC, stored procedures, connectors, file access).
* <li>They reduce the number of messages when a client interacts
* with a remote server, often replacing several messages that
* do small pieces of work with a single message that does all
* of them.
* <li>They provide local-remote transparency (ie, the command client
* code is independent of whether the command is executed in the
* client's JVM or a remote JVM).
* </ul>
*
* A Command has the following states during its lifecycle:
* <ul>
* <li><b>New</b>: Just after the command has been created (via a new,
* a factory create, Beans.instantiate, etc.).
* In this state the isReadyToCallPerform method should return false
* and the get methods should not be called.
* <li><b>Initialized</b>: Just after all required input properties have
* been set.
* In this state the isReadyToCallPerform method should return true
* and the get methods should not be called.
* <li><b>Executed</b>: Just after the perform method has been called.
* In this state the isReadyToCallPerform method should return true
* and the get methods should work.
* </ul>
* The only enforcement of these states is that the
* TargetableCommandImpl's implementation of the perform method calls
* the command's isReadyToCallPerform method prior to executing the command.
* In this case, if isReadyToCallPerform returns false then an
* UnsetInputPropertiesException is thrown.
* Any other enforcement of these states is up to the command writer.
*/
public interface Command
extends Serializable
{
/**
* Performs the task encapsulated by this command.
* This moves the command from the initialized to the executed state.
* If the isReadyToCallPerform method returns false,
* this throws an UnsetInputPropertiesException.
*
* @exception CommandException The superclass for all command exceptions.
*/
public void
perform()
throws CommandException;
/**
* This allows the command client and the command runtime to ask
* the command whether all required input properties has been set.
* It is called in the client JVM prior to execution being given
* to the CommandTarget for execution.
*
* @return True if the command is in the initialized or executed state.
*/
public boolean
isReadyToCallPerform();
/**
* This resets the output properties to the values they had
* prior to calling the perform method, so that the get methods
* no longer work but the isReadyToCallPerform returns true.
* It provides a convenient and efficient way to reuse the same
* command instance with changes in some input properties or in
* the CommandTarget.
*/
public void
reset();
}
[Back]
package com.ibm.util.command.ejb;
import java.io.*;
import java.rmi.*;
import java.util.*;
import javax.naming.*;
import com.ibm.util.command.*;
/**
* This is the CommandTarget for commands that are executed in an
* EJB server.
* It uses a server-side EntityBean to allow concurrent access
* by different transactions to execute the command on the server.
*/
public class EJBCommandTarget
implements CommandTarget, Serializable
{
/**
* The client-side RMI/IIOP stub for the server-side EntityBean
* that executes the command on the server.
*/
protected CommandServerEntity commandServerEntity = null;
/**
* This implements method in the CommandTarget interface.
*
* @param command The TargetableCommand to be executed.
* @return The TargetableCommand that has been executed.
* If the command.hasOutputProperties returns false,
* this is allowed to be null as a performance optimization.
* @exception RemoteException The superclass for all remove exceptions.
* This is thrown to allow the possibility for this method to
* be an RMI remote method.
* An example of this is the com.ibm.util.command.ejb.EJBCommandTarget.
* @exception CommandException The superclass for all command exceptions.
*/
public TargetableCommand
executeCommand(TargetableCommand command)
throws RemoteException, CommandException
{
try {
if (commandServerEntity == null) {
initializeCommandServerEntity();
}
return commandServerEntity.executeCommand(command);
} catch (CommandException ex) {
throw ex;
} catch(Exception ex) {
ex.printStackTrace();
//should I do the user a favor and unwrapper
//anything wrapped by a RemoteException?
throw new CommandException(ex);
}
}
/**
* This creates the single EntityBean on the server,
* gets its client-side RMI/IIOP stub and caches it
* in the commandServerEntity instance variable.
*/
protected void
initializeCommandServerEntity()
{
try {
InitialContext initialContext = new InitialContext();
CommandServerEntityHome commandServerEntityHome =
(CommandServerEntityHome)
IBMJavaOrbRemoteObject.narrow(
initialContext.lookup("CommandServerEntityHome"),
CommandServerEntityHome.class);
commandServerEntity = commandServerEntityHome.create();
} catch (Throwable ex) {
ex.printStackTrace();
throw new IllegalStateException
("Initialization of CommandServerEntity failed. " +
"Is the Transarc container running?");
}
}
}
[Back]
package com.ibm.util.command.ejb;
import java.io.*;
import java.rmi.*;
import java.util.*;
import javax.ejb.*;
import javax.naming.*;
import com.ibm.util.command.*;
/**
* This is the server-side EntityBean.
* <p>
* This object has no state.
* The EJSPersister is overwritten not to read/write from/to the database.
*/
public class CommandServerEntityBean
implements EntityBean, CommandTarget
{
public static int COUNT = 0;
public int dummy = 0;
/**
* This implements the method in the CommandTarget interface.
*
* @param command The TargetableCommand to be executed.
* @return The TargetableCommand that has been executed.
* If the command's hasOutputProperties method returns false,
* this returns null to avoid an unnecessary copy across the wire.
* @exception RemoteException The superclass for all remote exceptions.
* This is thrown to allow the possibility for this method to
* be an RMI remote method (eg, an EJB server).
* An example of this is the com.ibm.util.command.ejb.EJBCommandTarget.
* @exception CommandException The superclass for all command exceptions.
*/
public TargetableCommand
executeCommand(TargetableCommand command)
throws RemoteException, CommandException
{
try {
command.executePerform();
} catch (CommandException ex) {
ex.printStackTrace();
throw ex;
} catch (Exception ex) {
ex.printStackTrace(); //for trace
//Avoid wrappering layers upon layers
if (ex instanceof RemoteException) {
RemoteException remoteException = (RemoteException) ex;
if (remoteException.detail != null) {
throw new CommandException(remoteException.detail);
}
}
throw new CommandException(ex);
}
if (command.hasOutputProperties()) {
return command;
}
return null;
}
/**
* This implements the method in the EntityBean interface.
*/
public void
ejbCreate()
throws RemoteException, CreateException
{
dummy = ++COUNT; //not really EJB legal, but good for now
}
/**
* This implements the method in the EntityBean interface.
*/
public void
ejbPostCreate()
throws RemoteException, CreateException
{
}
/**
* This implements the method in the EntityBean interface.
*/
public void
ejbLoad()
throws RemoteException
{
}
/**
* This implements the method in the EntityBean interface.
*/
public void
ejbStore()
throws RemoteException
{
}
/**
* This implements the method in the EntityBean interface.
*/
public void
ejbRemove()
throws RemoteException, RemoveException
{
}
/**
* This implements the method in the EntityBean interface.
*/
public void
setEntityContext(EntityContext entityContext)
throws RemoteException
{
}
/**
* This implements the method in the EntityBean interface.
*/
public void
unsetEntityContext()
throws RemoteException
{
}
/**
* This implements the method in the EntityBean interface.
*/
public void
ejbActivate()
throws RemoteException
{
}
/**
* This implements the method in the EntityBean interface.
*/
public void
ejbPassivate()
throws RemoteException
{
}
}
[Back]
package freeside.beans;
import java.math.*;
import java.rmi.*;
import javax.ejb.*;
public class AccountBean
implements EntityBean
{
public boolean canWriteChecks = false;
public double balance = 0.0;
public String description = null;
public int customerID = 0;
public int id = 0;
public void
ejbCreate(double balance,
String description,
int customerID)
throws RemoteException, CreateException
{
this.canWriteChecks = false;
this.balance = balance;
this.description = description;
this.customerID = customerID;
this.id =
EntityBeanUtility.autoincrement(AccountBean.class);
}
public void
ejbPostCreate(double balance,
String description,
int customerID)
throws RemoteException, CreateException
{
}
public AccountDataBean
getDataBean()
throws RemoteException
{
AccountDataBean dataBean =
new AccountDataBean(canWriteChecks,
balance,
description,
customerID,
id);
return dataBean;
}
public void
updateEntityBean(AccountDataBean dataBean)
throws RemoteException
{
this.canWriteChecks = dataBean.getCanWriteChecks();
this.balance = dataBean.getBalance();
this.description = dataBean.getDescription();
this.customerID = dataBean.getCustomerID();
this.id = dataBean.getID();
}
public void
setBalance(double balance)
throws RemoteException
{
this.balance = balance;
}
public double
getBalance()
throws RemoteException
{
return balance;
}
public void
setDescription(String description)
throws RemoteException
{
this.description = description;
}
public String
getDescription()
throws RemoteException
{
return description;
}
public void
setCustomerID(int customerID)
throws RemoteException
{
this.customerID = customerID;
}
public int
getCustomerID()
throws RemoteException
{
return customerID;
}
public void
setCanWriteChecks(boolean canWriteChecks)
throws RemoteException
{
this.canWriteChecks = canWriteChecks;
}
public boolean
getCanWriteChecks()
throws RemoteException
{
return canWriteChecks;
}
//id IS READONLY
public int
getID()
throws RemoteException
{
return id;
}
public void
ejbLoad()
throws RemoteException
{
}
public void
ejbStore()
throws RemoteException
{
}
public void
setEntityContext(EntityContext entityContext)
throws RemoteException
{
}
public void
unsetEntityContext()
throws RemoteException
{
}
public void
ejbActivate()
throws RemoteException
{
}
public void
ejbPassivate()
throws RemoteException
{
}
public void
ejbRemove()
throws RemoteException, RemoveException
{
}
}
[Back]
package freeside.beans;
import java.math.*;
import java.rmi.*;
import java.sql.*;
import javax.ejb.*;
public class AccountDataBean
implements java.io.Serializable
{
public boolean canWriteChecks = false;
protected double balance = 0.0;
protected String description = null;
protected int customerID = 0;
protected int id = 0;
public
AccountDataBean()
{
}
public
AccountDataBean(boolean canWriteChecks,
double balance,
String description,
int customerID,
int id)
{
this.canWriteChecks = canWriteChecks;
this.balance = balance;
this.description = description;
this.customerID = customerID;
this.id = id;
}
public void
readResultSet(ResultSet resultSet)
throws SQLException
{
canWriteChecks = (resultSet.getInt(1) == 1);
balance = resultSet.getDouble(2);
description = resultSet.getString(3);
customerID = resultSet.getInt(4);
id = resultSet.getInt(5);
}
public void
setCanWriteChecks(boolean canWriteChecks)
{
this.canWriteChecks = canWriteChecks;
}
public boolean
getCanWriteChecks()
{
return canWriteChecks;
}
public void
setBalance(double balance)
{
this.balance = balance;
}
public double
getBalance()
{
return balance;
}
public void
setDescription(String description)
{
this.description = description;
}
public String
getDescription()
{
return description;
}
public void
setCustomerID(int customerID)
{
this.customerID = customerID;
}
public int
getCustomerID()
{
return customerID;
}
public void
setID(int id)
{
this.id = id;
}
public int
getID()
{
return id;
}
}
[Back]
| Privacy | Legal | Contact |