Examining the Container s Role


Examining the Container’s Role

The components making up the J2EE architecture are executed in runtime environments called containers. The containers provide essential key infrastructure services such as an object’s life cycle management, distribution, and security. In a web-based, thin-client application, the software resides within two containers running inside an application server. J2EE servers provide both an Enterprise JavaBean container and a web container. These two individual environments serve as the foundation for constructing multi-tiered transactional business applications.

The J2EE application architecture consists of three tiers:

  • Client tier

  • Middle tier

  • Enterprise Information System (EIS) tier

The client tier contains either a web-enabled browser such as Microsoft’s Internet Explorer or a Java application client. The middle tier consists of both a web container and an Enterprise JavaBean (EJB) container. This tier hosts the application’s business logic and performs services for the client. The EIS tier consists of databases, other types of resources such as flat files, ISAM format repositories, and legacy applications.

Interaction between client and business service–oriented components requires careful application planning. The developer has several responsibilities when designing client-side software. They include the following items:

  • Presenting the application’s user interface to the client. The browser is written in either HyperText Markup Language (HTML) or the Extensible Markup Language (XML) and runs on the client machine.

  • Gathering and processing mission-critical information from an HTML form.

  • Controlling client access to resources.

  • Preventing duplicate client submissions.

An enterprise application uses the thin-client model in which functionality occurs on the server tier rather than on the client tier. In a thin-client business model layer, user interaction between client components and business layer components consists of submitting HTML forms, managing state within a user session, processing client requests, generating dynamic web pages, and returning results to the client.

The thin-client model does have some disadvantages. First, the developer has little control over presentation to clients. Each solution must be tested for browser reliability. The user agent (browser) attempts to interpret and output everything submitted to it. Consequently, the results vary and the renderings are frequently incorrect. For example, Netscape Communicator will output run-on sentences with no line breaks and not interpret the data correctly, whereas Internet Explorer version 5 and above has a sophisticated transformation engine built into it and will “pretty-print” the data. It detects syntax errors and will inform the user where errors occur by placing a caret in the offending position. In addition, the presentation is limited to interactions that can be implemented using a markup language such as XML, or a plug-in. Otherwise, the data cannot be implemented within the application. Finally, the presentation is server-side dependent. This means client access to the server is far more frequent than when using a rich-client solution, in which an applet or application has a graphical user interface programmatically built in. The rich-client methodology enables the developer to trap events, which means that the client accesses the server only when needed, rather than responding to each event that occurs in the presentation.

Best Practice: Separating Business Logic from Presentation in J2EE Applications and .NET

As discussed in Chapter 2, the design pattern Model, View, Controller (MVC) provides developers with a business model to create user interfaces. Recall that MVC consists of three types of objects: the model is the application object; view is the screen presentation; and the controller mediates between model and view by defining the way the user’s interface reacts to client input. Leveraging the MVC model conforms to object-oriented programming principles by decoupling the three objects—meaning the components are reusable, thereby eliminating object dependencies.

MVC uses a subscribe-notify protocol, meaning a view must guarantee that its appearance accurately reflects the state of the model. For example, when the model’s data is modified, the model is obligated to notify a view of any changes so it can respond accordingly, reflecting all data modifications. The MVC approach allows developers to attach multiple views to a model and provide many different presentations. This business paradigm facilitates creating new views without the necessity of subsequent rewrites.

Best Practice: Use ASP.NET’s Code-Behind Feature

The MVC model is applicable to both J2EE and the .NET Framework. The code- behind feature, new in ASP.NET, allows developers to separate the presentation interface code from business logic code in Visual Basic .NET, C# .NET, and several other languages targeting the .NET Framework. Numerous ASP.NET features add value:

  • Clean separation of HTML and code Code-behind allows HTML page designers and developers to focus on what they do best, while eliminating the possibility of mixing presentation logic with business logic and messing up each other’s code.

  • Code reuse Code bearing the .aspx extension and not interspersed with HTML is reusable in other applications.

  • Easy maintenance Separating HTML and business logic makes ASP.NET pages easier to read and maintain.

  • Deployment without source code Visual Studio .NET projects that contain code-behind modules can be deployed as compiled code. This makes it easy for developers to protect their source code.

Best Practice: Maximize Benefits from Both Thin-Client and Rich-Client Applications Where Applicable

Best practices suggest using a rich-client solution where complex user presentations cannot be handled by browser-based applications. Numerous client round-trips to the server severely impact performance.

User Input Validation

All user data is subject to validation. This process occurs on either the client or server side. Let’s assume that IFCE financial services receive periodic stock quote updates throughout the day from Bloomberg and Reuters. Three types of validation are required for validating the quotes: syntactical, lexical, and semantic. Syntactic information is determined by checking a stock quote for proper formatting. For example, Microsoft’s stock quote may look like this: 47.5, in which the fraction is separated by a decimal point from the whole number 47. Lexical validation examines a value’s data type to ensure that the data type entered corresponds to the data type anticipated by the application. Semantic validation may check to ensure that the stock price does not exceed a limit imposed by a business rule or the SEC. A wide price swing in either direction raises a warning flag requiring manual inspection to make sure the quote has not been tampered with, or is incorrect for some other reason, before returning the stock quote to the pool for selling to clients.

Preventing Duplicate Client Requests

Submitting duplicate client requests requires validation and special treatment. The developer must ensure that a request is single threaded. Duplication occurs when several instances of client software are instantiated. Many different reasons exist for duplicate calls by multiple clients, including several clients attempting to access the same object. Applying best practices in this context means compiling a pattern such as the Pattern class in JDK 1.4 and using it with many different processes. Simply declare the Pattern as a static member of the validation class, thereby guaranteeing that only one copy is compiled. An alternative is using the Singleton pattern. It ensures that a class has only one instance and provides multiple-client access.

It is imperative for some classes to have only one instance. How does the developer ensure that a class has only one instance, accessible to all users? The solution is to make the class responsible for tracking its sole instance. A method of doing this is to intercept requests to create new objects.

The Singleton class provides this functionality. A best practice is using the Singleton class when the following situations occur:

  • There is only one instance of a class.

  • The instance is accessible to all client requests.

  • The single instance is made extensible through subclassing, and clients are able to use an extended instance without any code modification.

    Note

    An instance is a static member function in C++.

The following code demonstrates how to define a class implementation in C++:

class Singleton {
public:
static Singleton* Instance();
protected:
Singleton():
private:
static Singleton* _instance;
};

Here is the implementation for the Singleton class:

Singleton* Singleton::_instance = 0;
Singleton* Singleton::Instance (){
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}

Limiting a User’s Input Choices

Another best practice method for reducing user input error is limiting a user’s choices for input. This can occur, for example, in the .NET Framework by using ASP.NET web form controls. Radio buttons, check boxes, list boxes, and combo drop-down boxes do not need to be validated. They already provide valid choices. The only errors that can occur here are human-judgment errors.

A viable alternative to using ASP.NET web forms and controls is BEA’s Web Logic Integration (WLI) tools. They work in collaboration with the company’s WebLogic Application Server. The WLI environment allows developers to drag and drop controls onto a form. WLI tools provide similar controls limiting the user’s input to valid choices provided by the controls.

Managing Session State in a Distributed Environment

How does a developer manage session state in a web-based enterprise application? Typically, a client initiates a session with the web tier. The client request contains a beginning point and an end point. The beginning occurs when a client starts sending requests; an end is defined when a client stops sending requests. During a session, clients and web components exchange information. This information can consist of something as small as a user ID, or information submitted via a form. The component retains the information until a client request is fulfilled. The results are returned to the client, and the information is destroyed.

Unfortunately, components lack persistence. Therefore, it is up to the developer to find a way to preserve state. State can be preserved on either the client side or on the server side on the J2EE Enterprise JavaBeans tier.

ASP.NET applications make it simple to manage session state. The session is created automatically. Furthermore, a SessionID is assigned to the session. This enhances the ability to identify multiple client visits to the web site via the SessionID. It is also possible to store session state in an offline mode. This feature demonstrates a distinct advantage over preserving state in J2EE.

Best Practices: Client-Side Session State

Two kinds of session beans exist: stateless and stateful. Stateless session beans have no capability of preserving state, and developers must use one of the following methods to preserve state on the client tier. Stateful session beans preserve state between multiple visits by a single client by using one of these methods:

  • Hidden fields in an HTML form

  • Rewriting URLs

  • Using cookies

Usually, enterprise applications use an HTML form to collect information and store it in a hidden field:

<INPUT TYPE="TEXT" NAME="LASTNAME" SIZE = "50">
<INPUT TYPE = "SUBMIT" VALUE = "SUBMIT">
<INPUT TYPE = "RESET" VALUE="CLEAR">

When a user clicks on the Submit button, the browser takes the information from the fields and places it in a query string. The browser then calls a specified component on the web tier, typically a JSP or servlet, and passes the field data as parameters to the component. Once the component processes the information, it generates a dynamic web page containing another form and returns the results embedded within that form to the client. It could look something like the following:

www.dpsoftware.com/jsp/myjsp.jsp?LASTNAME=Peltzer

Best Practice: Using Hidden Fields

Components can make use of a hidden field within an HTML form to store information between multiple sessions by a single client. This field is not displayed on the form but is hidden. This field is similar to other form fields but provides a valuable mechanism for holding the submitted information. The component, rather than the user, assigns the data to this field. Just as before, the browser gathers all form field information and passes this data to the component for processing. Let’s see what a hidden field looks like:

<INTPUT TYPE="HIDDEN" NAME="CLIENTID" VALUE="12345">
<INPUT TYPE="TEXT" NAME="LASTNAME" VALUE="PELTZER">
<INPUT TYPE = "SUBMIT" VALUE="SUBMIT">
<INTPUT TYPE="RESET" VALUE="CLEAR">

The best practice when using a hidden field to maintain state is including a hidden field only when processing small units of information, such as a client ID. Performance degradation occurs when large amounts of information require extensive processing. Along with this process, passing session state to the browser with each page will also impact performance. This is true even if session state does not relate to this particular session. Additionally, hidden fields may only contain string values rather than other data types such as dates. If, for example, a date is passed, the component will need to convert the data to a string data type.

Note

In .NET, the HttpSessionState class provides similar functionality to that of Java.

Best Practice: Rewriting URLs

Rewriting URLs is another method available to developers for preserving session state. What is URL rewriting? The URL is a web page element that identifies a component used by the browser to request a web service. The browser can associate with the URL field names and values that are passed to the component if the component needs this information to process the client’s request. This always occurs when a user submits an HTML form. The developer places field names and values into a query string as an integral component of the URL. Subsequently, when the user selects the hyperlink associated with the URL statement, the browser calls the component specified by the URL and passes the component field names and values contained within the URL statement.

The best practice when using URL rewriting to preserve session state is using it only when a client does not use an HTML form.

URL rewriting is not always a good idea because it is always dependent on the client machine. Any OS failure or machine problem will cause the session to lose state. Keep in mind that server-side session management is more efficient.

Best Practice: Using Cookies

A cookie is frequently used in an enterprise application to store a small unit of data on a client’s machine. A developer can create a JSP program to generate a page dynamically that writes and reads a cookie. This mechanism preserves session state between pages.

It is prudent to use a client-side cookie to preserve state only when storing a client ID. A developer must have a contingency strategy should a client decide to disallow cookies or delete them.

Preserving Server-Side State in J2EE and .NET

A preferable alternative to preserving state on the client is storing information between sessions on the server. Recall that preserving session state on the client side has serious implications, mainly because preserving state is dependent on the client machine. In contrast, corporations go out of their way to make sure that networks and servers are functional 24 hours a day, seven days a week. This is an IT top-priority item.

Best Practice: Using the HttpSession Interface in J2EE

The best practice is to preserve session state on the Enterprise JavaBeans tier by employing the services of an Enterprise JavaBean, or on the web tier by using the HttpSession interface. Each session is assigned a unique session ID associated with a particular client session.

It is always a best practice to assign a specific server to a client, making sure the client always uses that server during a session. Additionally, check to ensure that session state is always stored on the same server.

Most applications use pieces of data, or variables, that need to be maintained across a series of requests or shared among multiple users. As previously stated, in a rich-client application it is easy to maintain state by allocating space on the client machine. However, web applications present significant challenges because HTTP is inherently stateless. ASP.NET presents a solution to this.

Defining Application State in .NET

Application state refers to any data a developer wishes to share with multiple users. This can include connection information for a DBMS, although this information is better restricted to the business tier of an application, which includes cached datasets.

Note

ASP.NET provides a cache engine for storing datasets.

Best Practice: Using the HttpApplicationState Class

ASP.NET provides a collection of key-value attributes that enable developers to store data values and object instances. A best practice is to store application state using the .NET HttpApplicationState class, an instance exposed as the application property of the Page class. The collection can be accessed in the following manner:

'VB.NET
Application("MyApplicationVar") = "MyValue"
MyLocalVar = Application("MyApplicationVar")

Here is the same code written in C#:

Application["MyApplicationVar"] = "MyValue";
MyLocalVar = Application["MyApplicationVar"]

Best practices make it possible to add new items to the Application collection using the Add method exposed by the Application object. In addition, use the Remove method exposed by the Application.Contents collection as follows:

'VB.NET
Application.Add("MyApplicationVar", "MyValue")
Application.Remove("MyOtherApplicationVars")
//In C#
Application.Add["MyApplicationVar", "MyValue"];
Application.Remove["MyOtherApplicationVars"];

It is also possible to clear the contents of the Application collection by using the Clear method exposed by the Application object. The following code demonstrates this:

'VB.NET
Application.Clear()
ApplicationRemoveall()

Best Practice: Synchronizing Access to Application State

ASP.NET’s Application object provides Lock and Unlock methods that developers can use to guarantee that only a single consumer can update application state data at any given time. Developers should call Application.lock() before modifying any data stored in the application collection. Once the modification is completed, the developer can call Application.Unlock().

Many times it is not appropriate to store Application state for DBMS connections and other application configuration settings. The best practice for storing infrequently accessed settings is to place these settings in a Web.config file and retrieve them with the GetConfig() method of the Context object.

Another best practice is caching frequently read datasets using the ASP.NET cache engine to cache expensive (large) or frequently accessed data.

Yet another best practice is storing shared application flags in a database. This method provides fine-grained control over the reading and updating of individual units of data. Additionally, consider storing references to an object instance and ensuring that the class from which the class is created is thread safe.

Using Session State in ASP.NET

Session state in classic ASP posed several challenges for developers. They included

  • Web farms Session state could not be scaled across multiple servers in a web farm.

  • Endurance Session state could be destroyed by a server crash or restart. In this context, shopping cart applications were difficult to develop and/or maintain.

  • Cookie reliance Classic ASP provided no solutions for preserving state with browsers that would not accept cookies, or users who chose to reject cookies.

Best Practice: Using ASP.NET Session State

ASP.NET’s Session object is exposed as a property of the Page class. This allows access to the Session object using the Session keyword, as demonstrated here:

'VB.NET
Session("MySessionVar") = "MyValue"
MyLocalVar = Session("MySessionVar")
//C#
Session["MySessionVar"]= "MyValue";
MyLocalVar = Session["MySessionVar"]

Session functionality is provided by the HttpSessionState class.

Note

The Session collection stores references or object instances, utilizing similar syntax to store object references at the application level. Note the following code:

'Global.asax
<object runat="server"
scope="Session">
</object>
'Web Forms page
Response.Write("Value =" & MyClassInstance.Myvalue)

Best Practice: Enabling Session State

A best practice to preserve state is enabling session state before using it. The default configuration file at the server level automatically enables session state in Machine.config.

In the event developers wish to delay the creation of a session until necessary, a best practice allows them to add the following code to the @Page directive:

<%@ Page EnableSessionState="False" %> 

It is also possible to set the session state to read-only for a specified page by setting the EnableSessionState to ReadOnly.

Configuring Session State Storage

ASP.NET provides several methods for storing session state. They include the following:

  • In-process (InProc) InProc is the default setting. This is also true for classic ASP.

  • Out-of-process (StateServer) StateServer indicates that a server executing the ASP.NET state service will store session state.

  • SQLServer (SQLServer) This setting specifies that session state will be stored in an SQL Server database.

  • Cookieless session This setting allows the developer to maintain session state for users whose browsers do not support cookies.

Best Practice: Storing Session State In-Process and Out-of-Process

The best practice for storing session state in-process requires no changes to the application configuration file. However, the best practice for storing session state out-of-process is as follows:

  1. Open the Web.config file for your application and locate the sessionState configuration session.

  2. Change the mode attribute from “InProc” to “StateServer”.

  3. Modify the stateConnectionString attribute to represent the server name or IP address of the state server and the port that the ASP.NET state service is monitoring (by default this is 42424).

  4. The complete sessionState configuration file will typically look like the following code:

    <sessionState
    mode="stateserver"
    stateConnectionString = "tcip=127.0.0.1:42424"/>

  5. Start the Services MMC snap-in by selecting Start | Programs | Administrative Tools | Services.

  6. Start the ASP.NET state service on the desired server from the Services MMC snap-in. ASP.NET will automatically connect to the specified state server and store session state for your application.

Preserving State in SQL Server

Preserving state in SQL Server has numerous advantages. Storing session out-of- process means that a specified SQL Server database can receive requests from multiple servers. It is particularly significant that storing session out-of-proc can provide scalable session state across a web farm. Session state is stored in SQL Server and survives any crashes of web servers or web application processes. The best practice for storing session SQL Server is as follows:

  1. Execute the installSqlState.sql batch file (located in the .NET Framework installation directory %windir%\Microsoft.NET\Framework\%version%) against the SQL Server specified for use.

  2. Locate the Web.config file and navigate to the sessionState configuration section.

  3. Change the mode attribute from “InProc” to “SQLServer”.

  4. Modify the sqlConnectionString attribute so it identifies the IP address of the designated SQL Server, and include the user ID and password used to gain access to SQL Server.

  5. The sessionState configuration section will look like the following:

    <sessionState
    mode="SQLServer"
    sqlConnectionString="data source 127.0.0.1:user id=sa:password="/>

    Note

    A best practice uses a trusted connection in SQL Server rather than placing the SQLServer user ID and password in the connection string in the Web.config file.

Cookieless Sessions

ASP.NET provides a simple way to store session state for users whose browser will not accept cookies. The best practice for storing session state in this context is to take the following steps:

  1. Locate the sessionState configuration section in the Web.config file.

  2. Modify the Cookieless attribute so it reads “true” rather than “false”.

  3. The complete sessionState configuration section will look like the following (note that the stateConnectionString, sqlConnectionString, and timeout have been omitted):

    <sessionState
    Cookieless="true"/>

When the Cookieless attribute is set to “true”, ASP.NET automatically embeds the SessionID in the URL for all user requests. A best practice is always to use a relative URL for internal links within the application. Relative URLs contain only path and file information for the requested resource but not protocol and domain information.

Using Client-Side Cookies for Storing State

A best practice for storing state in a client-side cookie is to complete the following steps:

  1. Create a new instance of the HTTPCookie class as follows:

    Dim MyCookie as New HttpCookie("MyCookieName")
  2. Set the Value property of the cookie to a desired value:

    MyCookie.Value = "MyValue"
  3. Add the cookie to the Cookies Collection of the Response object:

    Response.Cookies.Add(MyCookie)

This sets a cookie named “My Cookie” that lasts until the user closes the browser.

Using Persistent Cookies to Store State

Persistent cookies are used to store state across multiple browser sessions. In order to do this, an expiration date must occur. One method for doing this is to add the following code before adding the cookie to the Response.Cookies collection:

MyCookie.Expires = Now.AddDays(3)

A best practice for using persistent cookies is to keep the expiration date within a short amount of time, such as a few hours or days.

Note

Never store user data such as credit card numbers or other critical data that could subsequently be compromised or stolen.

Persistence on the Enterprise JavaBeans Tier

Enterprise JavaBeans residing on the Enterprise JavaBeans tier provide business logic to other tiers. Developers must be careful when deciding what functionality should be built into an Enterprise JavaBean. Frequently, developers make a mistake when defining tasks that an EJB should perform, by assigning multiple tasks to an EJB. For example, let’s assume a customer is submitting an order for a large number of widgets. Fulfilling this task requires more than one trip to a database: first, to ensure the customer’s status is okay and, second, to make sure the EJB checks the DBMS for available stock. These conditions present a challenge to the developer. Should these tasks be grouped together and the EJB allowed to fulfill both tasks, or should two EJBs be designated for performing the operations independently?

The best practice is to make each Enterprise JavaBean self-contained and design the logic so each EJB performs a separate task. An appropriate solution is using three Enterprise JavaBeans. One Enterprise JavaBean verifies the customer’s status, the second processes the request, and the third functions as a controller. What is a controller? A controller is an Enterprise JavaBean called by a JSP application. The controller calls the EJB to validate a customer’s status. Based on the results, the controller either sends a rejection notice or calls the appropriate EJB to process and fulfill the order.

Designing a Maximized Data Exchange

JSP programs and Enterprise JavaBeans communicate frequently during application execution. They may exchange individual chunks of data or exchange what is called a value object. This is an efficient method of transmitting data in bulk. In contrast, transmitting individual units of information is inefficient and increases network overhead. Therefore, a best practice is to keep exchanges of remote data to a minimum. This is accomplished by placing components on the same server to exchange information.

Inheritance in J2EE and .NET

Much has been written about using traditional inheritance. Unfortunately, inheritance promotes class dependencies, thereby violating the object-oriented practice of designing classes so they are independent. There are two kinds of classes—base classes and derived classes. Keep in mind that an object of the subclass has access to some or all data and member functions of the base class, including all data and methods of the derived class. The relationship between a base class and the derived class is referred to as coupling. This is not a good practice. It is prudent to encourage strong cohesion and loose coupling, a best practice. Always program to interfaces rather than using traditional inheritance. Both J2EE and .NET are component based and program to interfaces—a strong factor in their success because the components are designed as reusable units of data. Declaring classes as abstract makes it mandatory for developers to redeclare the classes and provide their own implementations.

A best practice is to identify commonality between objects and place those features in a base class. Place the noncommon features in a derived class. Where there is a function that is common among real-world objects, place the function in an interface. As long as the class conforms to the function’s signature, the developer is free to provide a unique implementation. Try to minimize inheritance in an enterprise application. Instead, use composition when an object is a type-of rather than a kind-of object. A type-of object should inherit commonality from the base class.




.NET & J2EE Interoperability
Microsoft .NET and J2EE Interoperability Toolkit (Pro-Developer)
ISBN: 0735619220
EAN: 2147483647
Year: 2004
Pages: 101
Authors: Simon Guest

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net