|
Developing Applications with Java, IIS, and ASPby Robert Zembowicz (http://www.robertz.com) March 1998This paper is reproduced with permission of Information Communications Group. Copyright 1998 Informant Communications Group. For more information, please visit http://www.informant.com or http://www.javaconference.com. AbstractThis paper introduces Java developers to building complex, distributed, multi-tier systems using Visual J++, Active Server Pages, and IIS. It starts from explaining how a simple ASP component can be written in Java and ends with presenting architecture for supporting complex, distributed, multi-tier Web systems. The presented architecture allows for both ultra-thin clients (HTML, D-HTML, and Java applets running in a browser) as well as more traditional, full-function clients (like stand-alone WFC or AFC applications developed with Visual J++). This presentation also discusses the issues of how to maximize the re-use of code common to different kinds of clients and servers. This can be achieved by introducing the layer of service objects that can be used by GUI components of the full-function client and thus execute on the server, as well as by non-GUI Java components instantiated on the Web server by ASP. Table of Contents:1. Introduction 2. Your First Java ASP Component 3. More Advanced ASP Components 4. Architecture for Complex Distributed Systems 5. Evaluation and Summary Appendix A: Checklist for Developing Java ASP Components Appendix B: Checklist for Developing ASP Pages 1. IntroductionActive Server Pages (ASP) is a relatively new technology that significantly simplifies developing Web applications that require executing scripts or programs on the Web server side. Recently, with the introduction of IIS 4.0, Active Server Pages was integrated with the Microsoft Transaction Server (MTS). 1.1 Briefly About ASP and ASP ComponentsFor normal HTML pages, when a Web browser requests a page, the Web servers responsibility is to retrieve the corresponding file and hand it over to the browser. Then the browser interprets HTML tags to render the page and eventually executes scripts, if any. In this traditional approach, scripts are executed on the clients machine that runs the Web browser. Active Server Pages are processed differently. First, scripts marked in a special way are executed on the Web server before the page is handed over to the browser. Second, scripts can invoke ActiveX objects called ASP components. Both scripts and components have access to parameters that were passed to the page, cookies, etc. Finally, bodies of server-side scripts in the original file are replaced with the output they produce and the resulting page is sent to the browser. ASP files are very easy to write because they are basically HTML files that allow for placing scripts that execute on the server. This means that once you know how to create regular HTML pages, you should have no troubles learning how to create ASP pages. ASP extends HTML by adding new delimiters for designating where server-side scripts begin and end; these delimiters are <% and %>. The script you place in between these delimiters can be written in either VB Script or JScript, whichever you prefer (there is a number of add-ons for other scripting languages, too). Since the script is replaced by the output created by the script and/or ASP components it invoked, you need to remember to format the output as HTML. The ActiveX object that is used as an ASP component could designed in several ways. One possibility is to develop a simple COM server that knows nothing about ASP. In such cases, it would be the scripts responsibility to get the data from the COM server, format it as HTML, and write it to the special ASP "response" object. You can use this approach when the output that the ASP component returns is small and simple. Second possibility is to write an ASP-aware COM server that would connect to the ASP response object and then send the output directly to it (again, it needs to be in HTML format). As a Java developer, you will probably prefer this way, as it gives you more flexibility in producing the output. Since ASP components are simply COM/ActiveX components, the developer automatically has access to all COM-based goodies, including DCOM and Microsoft Transaction Server. After proper registration with DCOM, the ASP component instantiated by an ASP page can actually execute on another machine. Additionally, the Microsoft Transaction Server (MTS) could manage ASP components to ensure that all involved components succeed or all of them fail. In IIS 4.0, MTS can also manage the ASP scripts directly: the script as well as all started components and all accessed databases can execute within a single transaction. 2. Your First Java ASP Component2.1 Writing ASP Components in JavaActiveX components that can be invoked from ASP scripts can be implemented in any programming language that supports developing COM servers. However, it is especially easy when you use Visual J++ and Microsofts Java VM. What makes it so easy is the Microsofts VM for Java that can expose any public Java class as a COM or even DCOM server. The only thing you have to do is to write the class and properly register it. The latter one could not be simpler: you just use the javareg utility provided in the SDK for Java. As an example, lets write the Java ASP version of the classical "Hello, World" program. Here it is: package vjdc;
import com.ms.asp.*;
import com.ms.com.Variant;
public class HelloWorld {
public void OnStartPage(IScriptingContext aspContext) {
aspContext.getResponse().Write(new Variant("Hello, World!"));
}
}
When an ASP script instantiates our HelloWorld server, the OnStartMethod will be automatically called by the ASP system. This method is very important because it gives us a way to connect to built-in ASP objects, especially the response object that is used to prepare the output that the client will see. OnStartPage is given the context object as its parameter and you can use this object to access other ASP objects. In the example above, this context is used to retrieve the reference to the response object that is given our "Hello, World!" string to write. Please note that the string is actually passed as a COM Variant object, which should not be a big surprise: we are in the COM world here
2.2 Registering Java Classes as ASP ComponentsBefore our object could be created as an ASP component, we need to register it properly on the Web server. Once you compile the Java class shown above, you need to run the javareg utility provided in the SDK for Java 2.x. Here is how you do it: javareg /register /class:vjdc.HelloWorld /progid:vjdc.HelloWorld Lets look at the arguments in the above command line one by one. The /register option tells the javareg program to register the given Java class; you can use /unregister option to clean the registry once you are done with the HelloWorld class. The /class option lets us specify what Java class is to be registered; you need to provide the fully qualified class name here, including the package path. Finally, the /progid option gives us the possibility to assign name to our server that can be used later to invoke it. The last thing we need to do is to place the compiled Java class in the location where the Virtual Machine would be able to find it. Why cant you just modify your CLASSPATH? You need to remember that your class would be executed by the VM which, in turn, is started by the ASP system. The ASP system is a part of IIS that is started by the NT system with the special, dedicated userid. Setting the environment variables for this dedicated user is not easy. Fortunately, there is a very easy solution: Microsofts VM will always search the TrustLib directory (in winnt\java) for classes. Therefore you can just copy HelloWorld.class into winnt\java\TrustLib\vjdc directory and you are done! 2.3 Calling Java from ASP ScriptOnce you have your Java ASP component properly registered and placed in TrustLib, you can invoke it from an ASP script. Here is an example that would instantiate the HelloWorld class presented above: <% Set MyComponent = Server.CreateObject("vjdc.HelloWorld") %>
This is all what you need to activate our HelloWorld object. When our component is instantiated by invoking the Server.CreateObject method, the ASP system will call OnStartPage method passing the ASP context object to it, which in turn will result in writing the "Hello, World!" string into the response object. Finally, when done with the script, IIS will replace everything in between <% and %> delimiters, including the delimiters, with the output collected by the response object. 3. More Advanced ASP ComponentsThe example presented in the previous section demonstrated elementary steps required to write a very simple ASP component. In the real world, however, you will need to know a little bit more to be able to use all the power provided by Active Server Pages. 3.1 Going Beyond OnStartPagePutting all the components functionality inside the OnStartMethod, as in the case of our HelloWorld example, is not the best solution in the real world. A natural question to ask is how one can invoke other Java methods from a script. Fortunately, Microsofts Java VM automatically provides the IDispatch interface support for all public methods and fields, which means that they will be accessible from an ASP script. To invoke a method defined in your Java class, the method must be declared public. Additionally, the type of the methods parameters and returned value must be one of the following:
For details on how types are mapped between Java and COM, consult Visual J++ documentation. For fields to be accessible from an ASP scripts, they also need to be public and of one of the types listed above. Another nice feature of the Microsofts Java VM is its ability to expose derived properties that do not have the corresponding public fields. The VM uses the Javas reflection mechanism to examine the class. If it finds the get and set methods that follow the JavaBeans naming convention, it exposes them as attributes (after removing "get" and "set"). Lets look at the following example. package vjdc;
public class Cube {
protected int m_edgeLength = 0;
public int getEdgeLength() {
return m_edgeLength;
}
public void setEdgeLength(int length) {
if (length >= 0)
m_edgeLength = length;
}
public int getVolume() {
return m_edgeLength * m_edgeLength * m_edgeLength;
}
}
When this class is properly registered, the VM will find and expose two properties: edgeLength and volume. In the script, one can access these two properties directly: <% Set cube = Server.CreateObject("vjdc.Cube")
cube.edgeLength = 13
Response.Write cube.Volume %>
The access to the m_edgeLength is shielded through the get and set methods; in particular, the set method doesnt allow for setting the edge length to a negative value. Please also note that the volume is a read-only, computed property. 3.2 Storing the Reference to the Context ObjectIf your ASP component is to produce a lot of output or needs to access built-in ASP objects, you should store in a local field the reference to the ASP scripting context object when ASP system calls your classs OnStartPage. The following class shows a typical implementation of the OnStartPage method. package vjdc;
import com.ms.asp.*;
public class AspComponent {
private IScriptingContext m_Context;
public void OnStartPage(IScriptingContext aspContext) {
setAspContext(aspContext);
}
protected void setAspContext(IScriptingContext aspContext) {
m_Context = aspContext;
}
protected IScriptingContext getAspContext{
return m_Context;
}
}
3.3 Retrieving Parameters Passed to the PageOne of the largest benefits of using ASP is the ease of accessing data received from the user. Data can come to ASP page from several different sources:
Have you ever developed CGI scripts or programs? If you have, you will really appreciate the way in which all of the above data is accessed in ASP. ASP has a number of so-called built-in objects that you can talk to. In Java, they are accessible through the scripting context object. The following is a quick summary of what data can be retrieved from the ASP built-in objects.
There are two levels at which you can access the above data. First is at the script level: before invoking methods in an ASP component, in the script you can get the data and pass them as parameters to your component. When the component is done with processing, the script can get retrieve some results and store them in the session or the application object, if needed. The second solution is to access the data directly from the component: you can get access to the built-in objects through the given scripting context object. Which approach should be used? If you want to use the same component in several different places, it might be better to get the data in the script and pass them to the component as parameters. This way your ASP component will not depend on the source of the data once the system is in production, it is much easier to modify scripts then the components. But this is not always the best solution. If you have a large form being processed by an ASP component, the script would have to be very long. When the form is to be changed, you would have to make the changes in three places: the form, the script, and the ASP component. In such cases, simply access all the data directly from the component. 3.4 Working with the Response ObjectThe ASP response object collects all the output you write to it and gives it to IIS as the replacement for the scripts body. In the default situation, the response object takes whatever is passed as a parameter to the Write method and immediately forwards it to IIS to be sent to the requesting Web browser. It means that, if your components need a lot of time to execute on the server, the users browser will get the output in increments as soon as ASP scripts and components produce them. This might be want you want in many cases, because the user will at least see some output when waiting for the rest. You can change this behavior by telling the response object that it should collect all the output in a buffer and send it to IIS (and clients browser) only upon completion or when explicitly requested. In this approach, the user will see nothing until all scripts complete, or until your script or one of the components calls the Flush method. Why would you like to do it and let the user wait? There are two important cases here. First, the buffer can be cleared without sending its contents to the users browser. This means that when, for example, your component detects a special situation after some output was already sent to the response object, it can clear the buffer: getAspContext().getResponse().Clear(); and replace it with a special message. Second, if no output was sent to the users browser, the script or component can re-direct the browser to another location: getAspContext().getResponse().Redirect("LoginError.htm");
This is particularly useful when an error or another abnormal case was detected and another page needs to be displayed in place of the requested one. Imagine, for example, that you need to provide users with secure login to your pages. One, regular HTML page can have a form with username and password fields. The values entered are then sent to ASP page, whose component checks the validity of the users ID and password. When the validation fails, the users browser can be directed back to the login page, or to another page that informs the user of the problem. 3.5 Initialization of Static FieldsSome static fields need to be initialized only once. If this initialization can be handled in the static initialization block, or if the initialization can be safely done several times, then you dont have to worry about it. However, if your code needs to call a static method to perform the initialization only once, you need to be very careful. The reason is that your ASP component is instantiated, some of the classes could be already loaded into VM and initialized during one of previous instantiations of this or another component. This can be easily resolved by performing lazy initialization, as in the following example. protected static boolean m_Initialized = false;
public static void initializeClass() {
synchronized (m_Initialized) {
if (! m_Initialized) {
// place initialization code that
// can be executed only once
// mark that the initialization was done
m_Initialized = true;
}
}
}
Please note that since we might have many clients accessing the same .asp file, the body of the method is synchronized for the static variable to ensure that the initialization happens really only once. 3.6 OnEndPage: Cleanup of ResourcesWhat if your Java ASP component uses some resources that need to be released after the component is no longer needed? Fortunately, there is an easy solution here. When the component is instantiated by calling Server.CreateObject method, the component's OnStartPage is called. Similarly, when the component is no longer needed, ASP system calls the OnEndPage method. OnEndPage method is a perfect place to release all the resources used by the component. 3.7 Debugging ASP Scripts and ComponentsASP gives you nice environment for developing complex Web systems. However, the number of bugs grows with the complexity of the system. How can you debug your ASP scripts and components? This is not easy so easy with IIS 3.0, especially considering the fact that the Java VM that executes your ASP components is started by IIS under a dedicated user ID. It means that you cant easily attach to VM and debug your classes you cant even send debug stuff to System.out because there is no console window to display the output.
Is there a way out here? Yes, if your scripts are written in VB Script. Ladies and Gentlemen, Start Your VBA EnginesAs a Java developer, most likely you would prefer to write all your scripts in JScript rather than VB Script, but you may change your mind when you try to debug your system. VB Script is a subset of VBA, the Visual Basic for Applications. VBA is included, for example, in Microsoft Excel, which also comes with a simple VBA debugger. Your ASP components are just COM objects, so they can be instantiated from VBA, too. Now you can see that all of the sudden debugging becomes easy, provided that your ASP scripts are written in VB Script. When you have a problem with your script or components, copy the script to a VBA window in Excel and start the debugger. The beauty of COM and Java VM comes into light once your component is created by the script and stored in a local script variable. Using the debugger, you can now see all public properties of your component, including those inferred from the get and set methods! You can even change the properties, which will result in changing the corresponding public field in your Java class or invoking the corresponding set method. Capturing Output Sent to the Response ObjectWhen you run your script from Excel, your components will fail when accessing the built-in ASP objects. However, resolving this issue is really simple because components access the built-in objects through Java interfaces rather than the actual classes. This means that you can just define your own classes that implement the corresponding interfaces. Since these classes will be used only for debugging, you might not need to implement all methods for all interfaces, just the ones that are used by the component that requires debugging. On the other hand, once you implement the classes, make sure you keep them for future debugging sessions. You will need to start from defining two classes, one implementing the IScriptingContext interface and one implementing the IResponse interface because these will be the most frequently used. Then you can add other classes when you need them. Here is the example of the simplest class that implements IScriptingContext and answers the response object: package vjdc;
import com.ms.asp.*;
public class AspDebugContext implements IScriptingContext {
protected AspDebugResponse m_Response = new AspDebugResponse();
public IRequest getRequest() { return null; }
public IResponse getResponse() { return m_Response; }
public IApplicationObject getApplication() { return null; }
public IServer getServer() { return null; }
public IsessionObject getSession() { return null; }
}
Similarly, you will need to implement the IRespone interface. Start with implementing the Write method that would capture the given piece of output so you could examine it. You can write given value to a text file, append it to a String field, or do whatever is convenient for you and easy to check. Here is an example: package vjdc;
import com.ms.asp.*;
import com.ms.com.Variant;
public class AspDebugResponse implements IResponse {
public String buffer = new String();
public void Write(Variant v) { buffer += v.toString(); }
public void Clear() { buffer = new String(); }
// other methods from IResponse come here...
}
Note that the buffer field is public, so you could easily examine it in the debugger (after you register AspDebugContext and AspDebugResponse classes with javareg, of course). Finally, since there is no ASP system that could call the OnStartPage method passing the context object, you will have to call OnStartPage method by hand passing the instance of AspDebugContext. One possible way is to add a new field holding the context and a new public method to your Java ASP class and call it from the script, for example: package vjdc;
import com.ms.asp.*;
public class MyAspComponent extends AspComponent {
...
public debugContext;
public void initDebug() {
debugContext = new AspDebugContext();
OnStartPage(debugContext);
}
...
}
In the script, you will need to add a call to the initDebug method just after the instance is created. Since the debugContext field is public, you will be able to see its contents in the debugger. Similarly, our implementation of the context class has the buffer field that also can be seen in the debugger. Clearing Virtual Machine CashOne more thing you need to know regarding debugging is how update Java classes on the Web server. The problem is that the Java VM cashes classes (this "problem" in testing mode is a huge benefit in the production mode) if you simply copy new class files over older versions, the VM might still use the older version. When you work with IIS 3.0, the most reliable way of clearing the cash that I found is quite brutal: stop IIS for a moment, get a cup of tea or coffee, and restart IIS. In case of IIS 4.0, you can run IIS as a stand-alone application and simply stop and run it again. Using Script Debugger in IIS 4.0Debugging with the latest IIS 4.0 is simpler than with IIS 3.0, because IIS 4.0 comes with the Microsoft Script Debugger, which allows for debugging scripts running on the server. Scripts running on the client can also be debugged with the same debugger, because it works with IE 4.0. Therefore, if your scripts are not very complex, you shouldnt have to run Visual Basic. On the other side, the debugging approach presented above is still very useful, because it allows developers to test components locally before they are installed on the Web server as ASP components. Another reason for emulating ASP classes as described in this section is that this approach allows for automated testing. You can create a database that will contain the data needed for a number of test cases. Then you can loop through all the records in the database, initialize the request object from the values read from the record, execute the script and components, and compare the produced response against the expected output. You can now see that debugging ASP components is not that hard as it seemed to when we first looked at it. Basically, you need to prepare the debug environment that would emulate ASP by implementing your own versions of the needed ASP built-in objects and calling the OnStartPage and OnStopPage methods by hand. The rest is easy thanks to (i) Java VM, which can expose any public class as a COM object, (ii) Java language, which introduced interfaces, and (iii) VBA, which is usually easily available. 4. Architecture for Complex Distributed SystemsIn the previous sections, you have learned how to develop simple, stand-alone ASP components. This section focuses on developing complex, multi-tier systems consisting of several components running on different machines. 4.1 The Need for Architectural SolutionIf you work for a large, established company, like a financial institution or a utility company, most likely the application you are developing has to connect to the existing infrastructure. For example, you may have to extract data from several different sources, from modern databases to mainframe systems. It is also very likely that the same data would be used by different application. For example, there might be a "traditional", stand-alone client application used in a customer service as well as a Web application accessed by the companys clients through Internet. Additionally, it is not uncommon to have a number of GUI-less jobs executed periodically in an automated way (like customer billing or verification of daily financial transactions). A typical question that developers face in such environments is how to maximize the re-use of code, both on the client as well as pieces running on the server(s). Re-using the code on the client is not a simple issue because there are several diverse kinds of clients: an ultra-thin one in Web browser, traditional stand-alone fat client, and background, periodic jobs. The architecture discussed in this section attempts to address all of the issues mentioned above, plus more:
Figure 1 below shows a typical run-time configuration for a heterogeneous, distributed system that supports a number of different types of clients.
Figure 1. Physical view of the architecture: this UML deployment diagram presents a possible run-time architecture of a multi-tier, distributed system. The example presented on the figure above identifies three kinds of clients:
Lets assume that all of these clients will be implemented in Java. In this example, each of the clients communicates with the transaction server through DCOM. The transaction server manages the retrieval and storage of data from/to multiple sources: modern relational databases as well as DB2 and COBOL jobs running on a mainframe. 4.2 Overview of the ArchitectureFigure 2 presents the overview of the logical architecture that supports the above three kinds of clients.
Figure 2. Logical view of the architecture: major packages and dependencies between them. The top layer consists of the specialized classes that are specific to each type of client. The middle layer provides the common services reused for all applications within this domain, including business services and business objects. Finally, the bottom layer provides general-purpose classes that are not specific to the business domain, like transactioning support, data access, GUI library, etc. The reuse comes from the separation of the code specific to individual kinds of clients from all business logic code that was encapsulated into business services and business objects. Note that on the above diagram the middle layer classes are reused by all client types. 4.3 Traditional Client SupportClasses that support traditional, stand-alone clients are mostly GUI screens built on the top of your favorite Java GUI library. The GUI components receive data as encapsulated into business objects that shield the client code from the actual source of data. Most actions requested by the user are forwarded to the business service classes. For the traditional client, a significant portion of the code resides on the client machine (whence the name "fat client"). Part of the data access layer (business objects or services) may also reside on the client machine and is responsible for retrieving the data either from a transactioning server or directly from the corresponding databases. Alternatively, some of those services may be executed on a remote machine through DCOM or MTS. The front-end of the traditional client can utilize the Application Foundation Classes (AFC) or the latest Windows Foundation Classes (WFC) to create an advanced, modern-looking GUI. 4.4 Web Client SupportIn the presented architecture, Web clients are supported through ASP components implemented in Java. In this approach, a clients request is processed by an ASP page that uses a number of ASP components. ASP components use common business services and objects. Remember that ASP system runs on the Web server the client gets only the output (thats why it is called an ultra-thin client). If the output is limited and can be easily tabulated, it can be sent to the users Web browser as an HTML page. For more complex cases, one can have a small Java applet running inside the clients Web browser that receives the output from an ASP page and renders it, for example, in a graphical form. To simplify developing ASP components in Java, introduce a base class that implements OnStartPage and OnStopPage methods and provides place holders for instance initialization and cleanup. The following code presents one of possibilities. package vjdc;
import com.ms.asp.*;
public class AspComponent {
private IScriptingContext m_Context;
public void OnStartPage(IScriptingContext aspContext) {
setAspContext(aspContext);
initialize();
}
public void OnEndPage() {
cleanup();
}
protected void initialize() {
// empty implementation - may be redefined in subclasses
}
protected void cleanup() {
// empty implementation - may be redefined in subclasses
}
protected void setAspContext(IScriptingContext context) {
m_Context = context;
}
protected IScriptingContext getAspContext{
return m_Context;
}
}
The OnStartPage method stores the reference to the ASP context and calls the initialize method. Similarly, OnEndPage calls the cleanup method. Additionally, this base class will be very handy if you decide to switch to using the latest ASP Java Component Framework classes. 4.5 Background Job SupportIn the discussed architecture, background jobs are implemented as Java classes executed periodically or per request. Again, those classes use the same common business layer as the traditional and Web clients. 4.6 Business Objects and Services LayerBusiness objects and services is the key to reuse. Business objects encapsulate data stored in databases and retrieved through the data access layer. They represent the "logical" view of the data rather than physical: to extract data for a particular business object, sometimes several queries need to be ran against different persistent storage systems. By introducing business objects and services we can shield the client code from details like where the data is actually stored. This is particularly important when there is several very different kinds of clients that can present or work with the same data. Business objects can be implemented as non-visible JavaBeans to simplify building GUI screens and connecting individual fields in the business object with the corresponding GUI controls that display them. Similarly, all business logic can be encapsulated into business service objects. Those service objects are responsible for implementing all actions required by the business processes used by the company. Some of these services require data extraction, processing, and updating databases with new data. Other services may simply forward the action requests to other systems, like COBOL jobs running on a mainframe. Frequently, a service is given business objects as parameters and/or returns a number of business objects as the output. In other words, it isolates the client code from knowledge how business objects are mapped to databases and what low-level actions are required to implement business functions. In some cases, like in the example presented on the Figure 1, part of (or all) the code from this layer may be executed under a supervision of a transaction server, like MTS or Tuxedo, to ensure the consistency of the business data. In such cases, this layer would also hide from the client code all communications to/from the transaction server, which could be implemented through DCOM (for MTS) or other means. 4.7 Error HandlingThe needs for uniform error handling are always obvious. However, when the same Java object can be executed as a part of a traditional client as well as inside an ASP component on a Web server, there is one more dimension to error handling. In a stand-alone application, an error box can be open to notify the user about the problem. In the case of ASP, error report may have to be written to the output HTML page or the user should be re-directed to another page. Background jobs should log all the problems in an external file or database. This means the actual error handling mechanism in use has to be transparent to all Java code. This can be handled by introducing the ErrorManager class that holds onto the actual ErrorHandler object to be used. The UML diagram in Figure 3 illustrates this possible solution.
Figure 3. Class diagram for error handling classes. The ErrorManager class has a static reportError() method and a static collection (vector) of error handlers. The abstract ErrorHandler class defines the abstract reportError() method, which each subclass needs to implement. When the top-level Java object that represents an ASP component is instantiated, it needs to initialize the error manager by specifying what error handler should be used. This could be done in the OnStartPageMethod, as in the following example: public void OnStartPage(IScriptingContext aspContext) {
setAspContext(aspContext);
setErrorHandler(new AspErrorHandler());
}
On the other hand, the application-level object for the traditional client should at the very beginning setup the error manager to use another error handler: public void init() {
setErrorHandler(new AfcErrorHandler());
// other application initialization code
}
Finally, in this example a background job would only use the LogErrorHandler: public void init() {
setErrorHandler(new LogErrorHandler());
// other application initialization code
}
The reportError() method of ErrorManager simply passes down the error message to the error reporter. In this scenario, errors are reported by calling ErrorManager.reportError(String message) without worrying what actual error handlers are in use. 5. Evaluation and Summary5.1 ASP Java Component FrameworkIIS 4.0 comes with ASP Java Component Framework, which is a small set of classes that isolate Java developers from working directly with COM interfaces (or, more precisely, Java wrappers for COM interfaces). When you use the ASP Java Component Framework, you do not have to worry about OnStartPage, OnEndPage, and storing the reference to the ASP IScriptingContext. All this is done behind the scenes by the framework. When you need to use one of the ASP built-in objects, use the corresponding static method from the AspContext class: public class AspContext {
public static Request getRequest();
public static Response getResponse();
public static Server getServer();
public static Session getSession();
public static Application getApplication();
public static IObjectContext getObjectContext();
}
Each of the five first methods returns another framework class. The last method, getObjectContext(), enables you to work with Microsoft Transaction Server (MTS). Debugging with Java Component FrameworkJava Component Framework classes are easier to use because they work with native Java classes rather than COM interfaces. However, currently debugging is not easy because debugging Java components on the server is not supported yet - you need to wait for Visual J++ 6.0. Since AspContext methods return objects of specific classes rather than interfaces, the debugging approach presented in the section 3.7 is harder to implement. If you really want to use the new framework but also want to have a way to debug your classes, here is a short summary of how to support debugging. First, define your own interfaces for the built-in objects that have method signatures exactly as those provided by the corresponding framework methods. Second, for each framework class that encapsulated a built in object, create a subclass that implements the interface, for example: public class AspResponse extends Response implements IAspResponse {
// all IAspResponse methods are already implemented in Response
}
Note that the base class already implements the methods defined in the interface, therefore the actual class definition is empty. Third, enhance the AspComponent class introduced in section 4.4 by providing methods that return the interfaces to built in objects and use them instead of direct calls to static AspContext methods. Finally, when you need to debug you components, change the AspComponent class to return the debug versions of the ASP built-in objects. Of course, for each interface you introduced, you will have to define a debug class that implements it, for example: public class AspDebugResponse implements IAspResponse {
// implement all IAspResponse methods!
...
}
This time you will have to implement each method defined in the corresponding interface, as it was discussed in section 3.7. 5.2 Using MTSIIS 4.0 has been integrated with Microsoft Transaction Server. MTS can manage the execution of the whole ASP script: the script and components created with Server.CreateObject method can be executed within the same transaction. New Java Component Framework classes also support MTS. For example, you have access to the MTS's object context. For more information, please see the online documentation for IIS 4.0. 5.3 Another Use of ASPThis article introduced "conventional" use of ASP, where ASP application consists of .asp files containing scripts that activate ASP components, and the output produced by the scripts and components is presented by a Web browser. However, there is another possibility. ASP pages are processed by IIS when a Web client requests them. This request could come from a Web browser that wants to download and display the page, or from a Java applet (or from any other application that attempts to open the ASP file). The former method was the base for this presentation. The latter one is a new approach. In this case, the Java applet (or any other program written in a language that supports access to files on the Internet, like VB, VC++, etc.) opens the page using HTTP protocol (possibly passing some parameters to it). At the point, the Web server processes the ASP page by executing all scripts and replacing them by the generated response text. Finally, the Java applet reads the output and presents it to the user. Most likely, you response text should come with no HTML formatting, as it will not be read and rendered by a Web browser. Instead, the output should be formatted in the form that is most convenient for the Java applet. Everything that was presented in this paper still applies, the only difference is who presents the data on the users machine. One of the benefits of this approach is that the user is not send to another page, but rather sees the same page where the Java applet shows the data retrieved in "background". 5.4 Why not Java Applets instead of ASP?One of the questions some developers ask is why not include the functionality of ASP components into an applet that would execute on the clients machine. At first, this might sound like a reasonable solution, and in some cases this may really be a good approach. However, before you follow this path, please look at the potential problems enumerated below.
If you need to present data to the user in a format that goes beyond capabilities of HTML, then one of the possibilities is to use a mixed approach:
5.5 Pros and Cons of Java on the Web ServerAnother question to ask is whether ASP components should be actually written in Java rather than other languages, especially C++ or Visual Basic. Here are some points for consideration. Pros:
Cons:
Possible approach to address the performance:
Appendix A: Checklist for Developing Java ASP ComponentsHere is a quick checklist that summarizes the steps necessary to develop an ASP component using Visual J++:
Appendix B: Checklist for Developing ASP PagesHere is a quick checklist for writing and installing ASP pages:
|
For more information, send email to:
or fill in the online contact form. |