Developing a J2EE Application


Developers must implement a strategy and design that offers flexibility, scalability, and reuse of application components. Application responsibilities include application start-up and shutdown, accessing external properties, error handling, and applying interface preferences.

Developing and deploying a J2EE application requires three distinct phases: development, assembly, and deployment. During development, web component providers and developers build components that encapsulate presentation logic. The reusable components are deployed as WAR files. EJB component developers create the EJB components that encapsulate business logic, and subsequently deploy them as EJB-JAR files.

In the assembly phase, an assembler puts together both the WAR and EJB-JAR files and merges them into an EAR file. The assembler is responsible for examining both types of files and customizes fields in the deployment descriptor file.

Finally, the deployer examines the EAR file, resolving any external dependencies, and configures the application to execute and deploy in an operational environment.

Several different development models exist within the Java environment. They include the time-tested traditional client-server model, which is similar to the web services client-server model. A client submits an HTML-based request to the server for processing server-side business logic. This process typically involves submitting updates, deletes, storing, and retrieving data to a relational database. Other traditional development models include the following:

  • Remote presentation model

  • Distributed logic model

  • Remote data management model

  • Distributed data management model

Web-Based Remote Presentation Model

In the remote presentation model, commonly referred to as the thin client paradigm, the only tool a client needs for communicating with the server is a web-enabled browser for submitting HTML-based requests via the HTTP transmission protocol to the server. This model represents a simple request-response solution. All business logic sits on the server. The user invokes the desired web service, which redirects the client request to a service provider. This development model offers the following benefits:

  • All server-side components, including business logic, servlets, Java Server Pages, and data management components, reside on the server.

  • The server-side controller (a servlet) provides dynamic content to a client.

  • The only tool needed is a web browser.

Developers face minimal challenges when utilizing this model. They must deal with exception handling and noncompliant user agents—that is, the inconsistencies between Netscape, Mozilla, Opera, and Internet Explorer. For example, an HTML presentation in Internet Explorer differs from a servlet streaming HTML raw output to a Netscape browser. Presenting a consistent display to the client requires extensive testing and making provisions for outputting the correct formatted data in different browsers by querying a browser for its version, for example.

Figure 2-2 represents a client-side presentation model and demonstrates how it interacts with servlets, Java Server Pages, and their access to the business model layer, containing both traditional JavaBeans and Enterprise JavaBeans. The EJBs reside within a web container. The figure also shows how business beans access the data source layer.

click to expand
Figure 2-2: Applying a filter to the J2EE’s infrastructure

The web server is a server-side program that invokes a servlet to manage and execute a server application. The servlet’s chief task extends the functionality of a web server and functions in two separate capacities. It can stream HTML to a client as a response to its request, or it can serve as manager by receiving client requests and delegating the task to the appropriate JavaBean or Enterprise JavaBean for business logic processing. Once the task is complete, the servlet calls a Java Server Page to stream the results via HTML back to the client. The latter role is preferable because it separates presentation data from business logic.

Servlets interface with existing JavaBeans or Enterprise JavaBeans. In either case, they access databases or transactional systems, providing such core services as user authentication, authorization, and session management. The servlet’s life cycle defines the business process by loading the servlet into memory, executing the servlet, and finally, unloading it from memory. The client provides a URL that identifies a specific servlet in order to access the servlet and leverage its services.

Servlets offer excellent security by running within the context of a container such as WebSphere’s application server. The container is responsible for providing low-level application services such as automated garbage collection, memory management, user authorization, and authentication.

Distributed Logic Application Model

Distributed logic business solutions divide the application roles between client and server. This solution offers application flexibility and features both Remote Procedure Calls (RPCs) and messaging services.

Note

The more traditional RPCs are invoked on procedural-type applications rather than on object-oriented web-based applications.

RPCs are synchronous, and using them has a significant drawback. Synchronous calls mean the calling program is blocked until the procedure returns a response. The Remote Method Invocation (RMI) solution allows developers to transmit messages remotely to an object. RMI includes a naming registry, which tracks instances and associates them with remote objects. Remote objects use the activation service to activate a server object at the behest of a client when it requests the service.

All distributed object protocols are built using the same architecture. This design makes an object residing on one computer look as though it sits on a local machine. This model contains three components: the business object, the stub, and the skeleton.

The stub resides on the client, whereas the skeleton exists on a middle layer that contains the business logic. Every business object contains matching stub and skeleton classes constructed specifically and designated for an identified business object. For example, a business object called Widget would have a matching Widget_Stub and a Widget_Skeleton. The following example demonstrates how a small distributed business model called WidgetServer implements the Widget interface:

public interface Widget {
public int getSku()throws Throwable;
public String getName()throws Throwable;
}

The interface implementation contains both business logic and state for the Widget:

public class WidgetServer implements Widget {
int sku;
String name;
public WidgetServer (String name, int sku){
// perform initialization here
this.sku = sku;
this.name = name;
}
public int getSku() {
return sku;2345 }
public String getName () {
return name;
}
}

The next step is providing a way to make the WidgetServer accessible to a remote client. The Widget_Stub and Widget_Skeleton are logical choices for this task. The Widget interface describes the concept of a Widget independent of the implementation. The WidgetServer implements the interface to support both business logic and state; the Widget_Stub implements the interface so it can represent the Widget object on the client and send requests to the skeleton, which forwards requests to the object. Here is the stub:

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;

public class Widget_Stub implements Widget {
Socket socket;
public Widget_Stub throws Throwable {
/* Create a connection to the skeleton.
Select either local host or the skeleton's IP address if it resides
on a remote computer. */
socket = new Socket("localhost" 9000):
public int getSku() throws Throwable {
ObjectOutputStream oStr =
new ObjectOutputStream(socket.getOutputStream());
oStr.writeObject("sku");
oStr.flush();
ObjectInputStream inStr =
new ObjectInputStream(socket.getInputStream());
return inStr.readInt();
}
public String getName() throws Throwable {
ObjectOutputStream oStr =
new ObjectOutputStream(socket.getOutputStream());
oStr.writeObject("name");
oStr.flush();
ObjectInputStream inStr =
new ObjectInputStream(socket.getInputStream());
return (String)inStr.readObject();
}
}

A String token is created and streamed to the skeleton when a method is invoked on the Widget_Stub. The token identifies the specific method invoked on the stub. Next, the skeleton parses the token and calls the corresponding method on the business object, and subsequently streams back the result. When the stub reads the skeleton’s reply, it parses the value and returns it to the client. This process actually makes the stub look as though it were processing the request locally.

Here is the skeleton code:

import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.net.Socket;
import java.net.ServerSocket;

public class Widget_Skeleton extends Thread {
WidgetServer myServer;
public Widget_Skeleton(WidgetServer server){
//this establishes a reference to the object this skeleton wraps
this.myServer = server;
}
public void run(){
try {
//generate a server socket on port 9000
ServerSocket servSocket = new ServerSocket(9000);
Socket socket = servSocket.accept();
while(socket != null){
//create an input stream to receive requests from the stub
/*remember, the skeleton sits on the middle tier and listens
for requests from the stub */
ObjectInputStream inStr =
new ObjectInputStream(socket.getInputStream());
//Read the next stub method request.
String method = (String)inStr.readObject();
if(method.equals ("sku")){
int sku = myServer.getSku();
ObjectOutputStream oStr =
new ObjectOutputStream(socket.getOutputStream());
//send results back to the stub
oStr.writeInt(sku);
oStr.flush();
}else if(method.equals("name")){
//invoke business method on the server object
String name = myServer.getName();
//Create an output stream to send return values to the stub
ObjectOutputStream oStr =
new ObjectOutputStream(socket.getOutputStream());
//return the results to the stub
oStr.writeObject(name);
oStr.flush();
}
}
}catch(Throwable t) {t.printStackTrace();System.exit(0);}
}
public static void main(String args[]){
WidgetServer widget = new WidgetServer("DLink100", 2345);
Widget_Skeleton wSkel = new Widget_Skeleton(widget);
wSkel.start();
}
}

The Widget_Skeleton directs requests received from the stub to the business object, WidgetServer. The Widget_Skeleton functions solely as a listener awaiting stub requests. When it receives a request, the skeleton parses it and delegates the task to the corresponding method on the WidgetServer. The business object’s return value is streamed back to the stub, returning the result and making it look as though it were processed locally rather than remotely.

The final step in describing the roles of both stub and skeleton is creating a client that utilizes the Widget:

public class WidgetClient {
public static void main(String [] args){
try {
Widget widget = new Widget_Stub():
int sku = widget.getSku();
String name = getName();
System.out.println(name+" is "+sku+ " hub product ");
}catch(Throwable t ) {t.printStackTrace();}
}
}

The client application demonstrates how the stub is used on a client machine. Note how the client is unaware that the Widget business object is in reality a network proxy to the business object on the middle tier.

RMI represents the basis for distributed object systems. Its primary task is making distributed objects location transparent. This means a server’s actual object location is always unknown to the client.

Summarizing the functionality for this example, the developer creates an interface that extends the java.rmi.Remote interface. This interface describes all remote methods that a client object can invoke. Then, the developer creates a server class to implement the newly declared subtype that extends the java.rmi.Remote interface. The final step involves using the RMI compiler (rmic) to accept the subtype of the remote interface as an input parameter and generate both a client stub class and server-side skeleton class, in addition to creating object instances of them. These two classes then interact with the RMI reference layer.

Remote Data Management Model

The remote data management model provides a consistent methodology for clients to access remote databases sitting on networked servers distributed over the Internet. The Java Database Connectivity (JDBC) API offers a shared interface to various relational dataset implementations. The JDBC API provides the following benefits:

  • Retrieve and scroll through query results returned by a server.

  • Treat database results as JavaBeans.

  • Manage and pool database connections.

  • Persist objects in relational databases.

  • Forward SQL statements to the database server.

The following steps are required for establishing a database connection and manipulating data:

  • Initialize and allocate drivers and database connections.

  • Create and prepare statements for database execution.

  • Navigate and process query results.

  • Perform any cleanup tasks before disconnecting from the data source.

Distributed Data Management Model

Replication is the key to distributed data processing. This business solution requires data management on both client and server. The administrator must synchronize both client and server databases. The drawback to this scenario is that it is a proprietary solution. Concurrency is also an issue.




.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