iPlanet Application Server Migration Guide



Chapter 3   Reimplementing Your NAS 2.1 Application



This chapter describes altering your NAS 2.1 application to fit the iAS 6.0 programming model.



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:

A series of user interactions to reach a goal. Example: an online survey or standardized test.

An activity clearinghouse with a central front page. Example: an online bank, with a central page that leads to several activities (withdrawals, transfers, etc.).

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.

However your application is subdivided, it is often best to migrate one part at a time. For more details, see .



Migrating Presentation Logic



This section describes the following concepts:


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 in the Programmer's Guide (Java).

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 iAS creates an IValList member variable to contain incoming data for an AppLogic, for servlets iAS 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.

For example:


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 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 Chapter 4, "Presenting Application Pages with JavaServer Pages in the Programmer's Guide (Java).


Recreating Presentation Layout

In a sense, your 2.1 HTML templates are already migrated. The iAS 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 Chapter 4, "Presenting Application Pages with JavaServer Pages" in the Programmer's Guide (Java).


Recreating Sessions and Security

iAS 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 in the Programmer's Guide (Java).



Migrating Business Logic

Business logic is handled in iAS 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 beans 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 and in the Programmer's Guide (Java).



Migrating Data Access Logic



This section describes redeploying database calls using the JDBC API.

The JDBC layer in iAS 6.0 supports 100% of the JDBC 2.0 specification and standard extensions.

For details on JDBC and transaction support, see and in the Programmer's Guide (Java).

Note 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. iAS 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 iAS 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 Migration



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

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 iAS 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), do something like this:

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, i.e. using NewRequest(), do something like this:

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, do something like this:

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 iAS 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 iAS 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 data—methods 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 iAS 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 Chapter 12, "Writing Secure Applications," in the Programmer's Guide (Java).


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:

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 in the Programmer's Guide (Java).


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 provides methods for iterating through rows in a set of memory-based hierarchical data and retrieving column values. This functionality is not supported in iAS 6.0, although group names are supported (and required).

In iAS 6.0, ITemplateData functionality is replaced with JDBC ResultSet objects. You can convert ITemplateData objects to ResultSets using the method convertITemplateDataToResultSet() from the BaseUtils class. For specific usage information, see the documentation for the BaseUtils class in the iAS 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);






Copyright © 2000 Sun Microsystems, Inc. Some preexisting portions Copyright © 2000 Netscape Communications Corp. All rights reserved.

Last Updated April 25, 2000