Previous Contents Index DocHome Next |
iPlanet Application Server Migration Guide |
Chapter 3 Migrating NAS 2.1 Applications
This chapter describes altering your NAS 2.1 applications to fit the iPlanet Application Server 6.0 programming model.This chapter includes the following sections:
Redesigning Your Application
Redesigning Your Application
When redesigning an existing application, it is important to keep in mind that changes made to one part will affect the others.It may be useful to think of your application as one of the following models:
A series of user interactions to reach a goal. Example: an online survey or standardized test.
In reality, your application is likely to be a combination of the two. For example, an online bank could really be a central clearinghouse where each of the pathways leads to a series of user interactions to reach a goal.An activity clearinghouse with a central front page. Example: an online bank, with a central page that leads to several activities (that is, withdrawals, transfers, and so on).
However your application is subdivided, it is often best to migrate one part at a time. For more details, see "Partial Component Migrations."
Migrating Presentation Logic
This section describes the following concepts:
Recreating AppLogics as Servlets
Recreating AppLogics as Servlets
AppLogics map directly to servlets. They are similar in that they are both called by URLs, and they both contain mechanisms to process input and generate output. The main difference, besides the layout of the code itself, is that servlets generally do not perform business logic, as AppLogics do. Rather, business logic is handled in EJBs and referenced by the servlet, similarly to the way presentation layout is handled in JSPs and referenced by the servlet. In short, a servlet is like an AppLogic with the business logic re-implemented in a separate entity.For information about servlets, see "Controlling Applications with Servlets" in the Developer's Guide.
Servlets must contain a service() method (or, for HTTP servlets, this can be implemented as doGet(), doPost(), etc. depending on the HTTP transport method), which is logically similar to the execute() method in an AppLogic. This is the main flow of execution for the component.
Moreover, where iPlanet Application Server creates an IValList member variable to contain incoming data for an AppLogic, for servlets, iPlanet Application Server instead creates a request object and passes it as a parameter to the servlet. Likewise, where AppLogics use an IValList for output, servlets use a response object, also passed to the servlet as a parameter. The following code examples illustrate both cases:
AppLogic
public class MyAppLogic extends AppLogic {
public void execute () throws IOException {
...
String lastName = valIn.getValString("lastName");
...
return result ("<html><body>\n"
+ "<p>Your last name is " + lastName + ".\n"
+ "</body></html>\n");
}
}
Servlet
public class myServlet extends HttpServlet {
public void service (HttpServletRequest req,
HttpServletResponse res)
throws IOException, ServletException
{
...
res.setContentType("text/html");
String lastName = req.getParameter("lastName");
...
PrintWriter output = res.getWriter();
output.println("<html><body>\n");
+ "<p>Your last name is " + lastName + ".\n"
+ "</body></html>\n");
}
}Note that you can also reimplement an AppLogic as a JSP, since JSPs and servlets are more or less the same entity from different viewpoints. For example:
<html><body>
<p>Your last name is <display property="request:params:lastName">.
</body></html>For information about servlets, see "Presenting Application Pages with JavaServer Pages," in the Developer's Guide.
Recreating Presentation Layout
In a sense, your 2.1 HTML templates are already migrated. The iPlanet Application Server 6.0 template engine simply compiles these templates as if they were JSPs. The new template engine supports GX tags for backward compatibility, with the exception of hierarchical queries.However, GX tag support in JSPs is deprecated, so these templates must be converted to use standard JSP tags and syntax. JSPs use beans to encapsulate output parameters, and can access arbitrary Java objects as well. You can even access EJBs directly from JSPs. Normally, however, you set attributes in the request object during the execution of a servlet and then recall them in a JSP.
For more details about JSPs, including examples, see "Presenting Application Pages with JavaServer Pages," in the Developer's Guide.
Recreating Sessions and Security
iPlanet Application Server 6.0 sessions use the HttpSession interface. The concepts are similar to the way sessions worked in NAS 2.1, though the API is different. A servlet (or AppLogic) creates a session, thereby instantiating a session object that persists for the life of the user session. A session cookie is returned to the client and reread on subsequent interactions with that client. Once the session exists, you can bind objects to it.Security in servlets has changed. For more information, see "Understanding the Security Model," in the Developer's Guide.
Migrating Business Logic
Business logic is handled in iPlanet Application Server 6.0 through Enterprise JavaBeans (EJBs) rather than in AppLogics. An important distinction between AppLogics and EJBs is that EJBs can be made to be persistent during a "session" with the user, separately designated from the user's session, in the case of session beans. Entity beans exist independently of users, and thus potentially persist through the life of the server.You write these EJBs to perform discrete tasks, then connect to them from servlets. For example you would do this if you have an electronic shopping cart.
For details on JDBC and transaction support, see "Using JDBC for Database Access," and "Handling Transactions with EJBs," in the Developer's Guide.
Migrating Data Access Logic
This section describes redeploying database calls using the JDBC API.The JDBC layer in iPlanet Application Server 6.0 supports 100% of the JDBC 2.0 specification and standard extensions.
For details on JDBC and transaction support, see "Handling Transactions with EJBs," and "Using JDBC for Database Access," in the Developer's Guide.
The JDBC 2.0 interfaces provided in $GX_ROOTDIR/solarisdbg/JDK_1.2/java (or similar directory) must be before any other JDBC interfaces in the CLASSPATH. iPlanet Application Server 6.0 works with JDK 1.2 which has JDBC 2.0 interfaces in $JAVA_HOME/lib/rt.jar, so make sure this rt.jar is after the iPlanet Application Server provided classes, as follows:
- setenv CLASSPATH :$GX_ROOTDIR/solarisdbg/JDK_1.1:...:$JAVA_HOME/lib/rt.jar:...
Incompatibility Errors
If you get a log message like the following, you probably have the JDBC 1.2 interfaces in your CLASSPATH before the JDBC 2.0 interfaces:
- [01/05/99 11:25:51:0] error: APPLOGIC-caught_exception: Caught Exception:
java.lang.NoSuchMethodError: java.sql.Statement: method
addBatch(Ljava/lang/String;)V not found
Partial Component Migrations
This section describes how to use older components (Java and C++ AppLogics) with newer components (servlets and EJBs). The following four combinations are supported:
Calling EJBs from Java AppLogics
Calling Servlets from Java AppLogics
Calling EJBs from Java AppLogics
Since there is no special context shared between servlets and EJBs, you call an EJB from an AppLogic in exactly the same way you would from a servlet.This example shows an AppLogic accessing an EJB called ShoppingCart. The AppLogic creates a handle to the cart by casting the user's session ID as a ShoppingCart after importing the cart's remote interface. The cart is stored in the user's session.
import cart.ShoppingCart;
// Get the user's session and shopping cart
//first create the session
ISession2 sess = createSession(GXSESSION.GXSESSION_DISTRIB,
0, //no timeout
"callEjb", //app name
null, //system-gen'd ID
null);
//create an IValList to store the shopping cart in the session
IValList ival = sess.getSessionData();
ShoppingCart cart = (ShoppingCart)ival.getVal("shoppingCart");
// If the user has no cart, create a new one
if (cart == null) {
cart = new ShoppingCart();
ival.setVal("shoppingCart", cart);
}You can access EJBs by using the Java Naming Directory Interface (JNDI) to establish a handle, or proxy, to the EJB. You can then refer to the EJB as a regular object; any overhead is managed by the bean's container.
This example shows the use of JNDI to look up a proxy for a shopping cart:
String jndiNm = "Bookstore/cart/ShoppingCart";
javax.naming.Context initCtx;
Object home;
try {
initCtx = new javax.naming.InitialContext(env);
} catch (Exception ex) {
return null;
}
try {
java.util.Properties props = null;
home = initCtx.lookup(jndiNm);
}
catch(javax.naming.NameNotFoundException e)
{
return null;
}
catch(javax.naming.NamingException e)
{
return null;
}
try {
IShoppingCart cart = ((IShoppingCartHome) home).create();
...
} catch (...) {...}
Calling Servlets from Java AppLogics
You can call a servlet from a Java AppLogic, for example if you want your AppLogic to call a JSP, using GXContext.NewRequest() or GXContext.NewRequestAsync(). For more details and specific examples of NewRequest(), see the documentation for the GXContext class, in the iPlanet Application Server Foundation Reference.You can also call a JSP from an AppLogic, since JSPs and servlets are the same type of object after instantiation.
To call a servlet from an AppLogic using the same process call the servlet's serlvet engine (an AppLogic called ServletRunner), consider the following example:
class SomeApplogic extends Applogic {
int execute() {
valIn.setValString("appName","nsOnlineBank");
valIn.setValString("servletName","Login");
valIn.setValString("SCRIPT_NAME","nsOnlineBank/Login");
com.netscape.server.servlet.servletrunner.ServletRunner sr =
new com.netscape.server.servlet.servletrunner.ServletRunner();
sr.valIn = valIn;
sr.valOut = valOut;
sr.context = context;
sr.stream = this.stream;
sr.ticket = this.ticket;
sr.request = this.request;
sr.COMSet(COMGet());
sr.COMAddRef();
sr.execute();
...
}
}To call a servlet from an AppLogic in a new process using NewRequest(), consider the following example:
class SomeApplogic extends Applogic {
int execute() {
valIn.setValString("appName","nsFortune");
valIn.setValString("servletName","fortune");
valIn.setValString("SCRIPT_NAME","nsOnlineBank/Login");
retValue = GXContext.NewRequest(m_Context,
"ApplogicServlet_nsFortune_fortu ne",
valIn,valOut,host,port,0);
...
}
}You can call a JSP in much the same way, as in the following example:
public class SomeApplogic extends Applogic {
int execute() {
valIn.setValString("appName","System");
valIn.setValString("servletName","JSPRunner");
valIn.setValString("JSP","nsOnlineBank/jsp/abc.jsp");
valIn.setValString("SCRIPT_NAME","nsOnlineBank/Login");
retValue =
GXContext.NewRequest(m_Context,
"Applogic Servlet_System_JSPrunner",
valIn,valOut,host,port,0);
...
}
}To call a servlet using a GUID, consider the followin example:
public class SomeApplogic extends Applogic {
int execute() {
valIn.setValString("appName","nsFortune");
valIn.setValString("servletName","fortune");
newRequest("{6F3547D0-FDCB-1687-B323-080020A16896}",
valIn,valOut,0);
}
}
Calling Java AppLogics from Servlets
You can call AppLogics from servlets using GXContext.NewRequest() or GXContext.NewRequestAsync(). For more details and specific examples, see the documentation for the GXContext class, in the iPlanet Application Server Foundation Class Reference.In order to call an AppLogic using NewRequest(), you must first cast the server's context to an IContext object, and then set up the input and output IValList objects for the AppLogic.
This example shows how to obtain an IContext object, set up parameters for the AppLogic, and finally call the AppLogic using NewRequest():
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.kivasoft.applogic.*;
import com.kivasoft.types.*;
import com.netscape.server.servlet.extension.*;
public class callAnAppLogic extends HttpServlet {
public void service(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException
{
// first set up ic as a handle to an IContext
ServletContext sctx = getServletContext();
com.netscape.server.IServerContext isc;
isc = (com.netscape.server.IServerContext) sctx;
com.kivasoft.IContext ic = isc.getContext();
//set up IValLists and GUID
IValList vi = GX.CreateValList(); // valIn
valIn.setValString("randomParameter", "Cirdan the Shipwright");
IValList vo = GX.CreateValList(); // valOut
String al = req.getParameter("AppLogicToCall");
// expect AppLogicToCall in request
//finally, call the AppLogic
GXContext.NewRequest(ic, al, vi, vo, 0);
}
}
Accessing the Servlet's AppLogic
Each servlet is contained in an AppLogic. You can access the AppLogic instance controlling your servlet using the method getAppLogic() in the iPlanet Application Server feature interface HttpServletRequest2.import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.kivasoft.applogic.*;
import com.kivasoft.types.*;
import com.netscape.server.servlet.extension.*;7
public class callAnAppLogic extends HttpServlet {
public void service(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException
{
HttpServletRequest2 req2 = (HttpServletRequest2)req;
AppLogic al = req2.getAppLogic();
//al is now a handle to the superclass
...
}
}
Calling C++ AppLogics from Servlets
The method GXContext.NewRequest() as described in calls an AppLogic by GUID and provides handles to objects as input and output parameters. This method works for calling C++ AppLogics as well as Java AppLogics, since the AppLogic is called by the specified name or GUID and not by a handle specific to Java. See the example shown in that section.
Sessions in Partially Migrated Applications
The HttpSession2 interface is an additional session interface that gives you direct access to the session object. Using this interface, you can share sessions (and therefore data) between applogics and servlets.In servlets, a session is an instance of HttpSession. But in AppLogics, session data is an IValList object. An AppLogic stores integers, strings, and blobs (byte arrays) in a session, whereas a servlet stores serializable objects in a session. As a result, there is no immediate mapping between what an AppLogic stores and what a servlet stores in a session (except for strings).
The HttpSession2 interface solves the issue of sharing session data. HttpSession2 provides methods for storing and retrieving integers, strings, blobs, and user login datamethods that parallel what an AppLogic developer uses. In this way, HttpSession2 enables sessions to work back and forth across AppLogics and servlets.
HttpSession2 provides loginSession( ) and logoutSession( ) for servlets to share the AppLogic session API. These methods have been deprecated in iPlanet Application Server 6.0. These two methods are typically used with isAuthorized( ), as is done for AppLogics. Servlets are also registered with an access control list, so that a secure session established in an AppLogic can be used in a servlet, and vice versa.
For more information, see "Writing Secure Applications," in the Developer's Guide.
Making the Session Visible
Note that, because sessions are controlled with cookies, a session created in an AppLogic is not visible in a servlet by default. This is because cookies are domain- and URI-dependent, and the URI for a servlet is different from that of an AppLogic. To work around this problem, call setSessionVisibility() before you call saveSession() when you create a session in an AppLogic.It is important to do this before calling saveSession(), since saving the session also creates the session cookie.
For example, in an AppLogic, consider the following example:
domain=".mydomain.com";
path="/"; //make entire domain visible
isSecure=true;
if ( setSessionVisiblity(domain, path, isSecure) == GXE.SUCCESS )
{ // session is now visible to entire domain }For more information about sessions, see "Creating and Managing User Sessions," in the Developer's Guide.
Converting ITemplateData to ResultSet
NAS 2.1 provided an interface called ITemplateData to represent a hierarchical source of data used for HTML template processing. In NAS 2.1, ITemplateData IGXTemplateData (Java) provides methods for iterating through rows in a set of memory-based hierarchical data and retrieving column values. This functionality is not supported in iPlanet Application Server 6.0, although group names are supported (and required).In iPlanet Application Server 6.0, ITemplateData functionality is replaced with JDBC ResultSet objects. You can convert ITemplateData objects to ResultSet objects using the method convertITemplateDataToResultSet() from the BaseUtils class. For specific usage information, see the documentation for the BaseUtils class in the iPlanet Application Server Foundation Class Reference. The following example shows an ITemplateData conversion to a ResultSet in an AppLogic. Note that you must provide a data group name as a parameter to the conversion method.
ITemplateData itd = GX.CreateTemplateDataBasic("myTemplateData");
... // populate myTemplateData
...
ResultSet rs = BaseUtils.convertITemplateDataToResultSet("dataGroup1",
itd);
Previous Contents Index DocHome Next
Copyright © 2001 Sun Microsystems, Inc. Some preexisting portions Copyright © 2001 Netscape Communications Corp. All rights reserved.
Last Updated June 14, 2001