Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Remote scripting servlet in action

How to build a Web-based incoming call monitor for CSR

Victor Yang (victory@ca.ibm.com), Software developer, IBM
Victor Yongwei Yang is working for IBM's Toronto Lab as a software developer. He holds a MSCS from Georgia Tech. Since 1994 he has worked for numerous companies including AT&T, S1,IBM, Sun Microsystems, SunLife, and CIBC. He is a Sun certified programmer and Web developer. He can be reached at victory@ibm.ca.com or yanixsoft@yahoo.com.

Summary:  This article presents a Web-based incoming-call monitor for a Customer Service Representative (CSR) in a Customer Relationship Management, or CRM, product based on Erik Hatcher's work, "Remote scripting using a servlet." To take that a step further, Victor Yang here analyzes those requirements and looks into such design options as why IFRAME is recommended over XML-RPC. Finally, he'll show you how to customize the original framework while explaining the key issues that take place during implementation with the code snippets.

Date:  11 Nov 2003
Level:  Introductory

Activity:  5147 views
Comments:  

The Computer Telephony Integration (CTI) component of CRM captures all calls, inbound and outbound. The CTI component also records the call length, missed calls, voice mails, personal calls, and caller IDs for demographic reporting information.

Traditionally, a CTI client such as incoming call monitor is implemented as a desktop Windows client. Now, with the increasing demand of Web interfaces among CRM products, it is no surprise that CTI is following suit.

The requirements

Here is the task.

  1. The client side uses Microsoft Internet Explorer (IE) 4 with the cookie enabled for keeping session data.
  2. Only HTTP or HTTPS can be used as a communication protocol between IE and the servlet.
  3. The incoming call monitor pops up to ask for the CSR after he or she logs on.
  4. The incoming call monitor polls the CTI server periodically and asynchronously -- say, every five seconds -- without refreshing the page, while checking for any incoming calls for the CSR.
  5. Once an incoming call is pending, the incoming call monitor displays the phone number as well as the contact name if there is a match found in the CRM database for the phone number (shown in Figure 1).

Figure 1. Contact found
Contact Found

XML-RPC versus hidden IFRAME

Obviously, the main hurdle is to poll the CTI server periodically and asynchronously for the incoming call without refreshing the page.

Remote scripting technique can solve this problem.You have two options to consider for remote scripting:

  • The XML-RPC option is a remote procedure using HTTP as the transport and XML as the encoding. XML-RPC is designed to allow complex data structures to be transmitted, processed, and returned to the browser for display. JavaScript technology has an XML-RPC client side library and Java technology has a server side library. You need to install and configure these libraries to make XML-RPC work.
  • The hidden IFRAME option has been part of the HTML specification ever since version 4, and is supported in nearly all modern browsers. With IFRAMER, you don't need to install client or server libraries.

XML-RPC requires the installation of XML-RPC libraries on both the server and client sides. XML-RPC is well suited for passing on larger amounts of data, while IFRAME is enough for small amounts of data.

Now I will analyze the amount of data that passed between client and server.

On the Java servlet side, polling for the incoming call can be done in a servlet method called getIncomingCall: String contactInfo=getIncomingCall(CSRUser csrUser).

Here is the detailed explanation of how this works.

  • CSRUser is an object of Java class CSRUser. It is key in looking for the CSR's pending call in the incoming call queue (its class is CSRUser).

    After the CSR logs on, you can create and store a CSRUser object in the HttpSession, and the servlet container will set a cookie and send it back to IE. Therefore, when IE polls the servlet, an HTTP session cookie is always passed from the IE to the servlet; the cookie can then be used to find the CSRUser object in the HttpSession object. It is familiar to any servlet developer.

    As a result, no data is passed explicitly from IE to the servlet because the session cookie is passed on as a key to look up CSRUser anyway.

  • getIncomingCall is the instance method of the servlet. You need instance method here because only an instance method can get access to HttpServletRequest, which eventually will acccess the CSRUser. The logic behind getting the CSRUser from HttpServletRequest and HttpSession is that it can be done only by the servlet's base class.

  • contactInfo is the data returned by the getIncomingCall. It gives a string of contact IDs, contact names, or phone numbers in the form of either a name value pair, or a nocall, which means no incoming calls are in queue yet for this CSR. The contact ID is the unique identifier for this customer and is useful for the subsequently generated Web pages.

Given that no data is passing explicitly from the client side to the server side, and only a String of limited length is to be passed from the server side back to the client side, IFRAME is lean and mean enough to work as the incoming call monitor. All you have to do is make an HTTP GET or POST from IE to the servlet inside a hidden IFRAME; then the servlet generates HTML (actually, JSP or JavaServer Page file) back to the hidden IFRAME. To pass the returned data, such as contactInfo, inside the JSP file, you can invoke a JavaScript function with the contactInfo as parameter. Once IE loads this JSP file, this callback function is called.

Erik's article (see Resources) builds a framework to support a hidden IFRAME. However, the framework is lacking the support it needs to invoke an instance method of the servlet (static method only in his framework), which carries HttpServletRequest or any user-defined datatype, such as CSRUser, as the input parameter. Most J2EE Web applications access the business object (csrUser, in this case) through the HttpSession because it serves as the single entry point to the object model.

In order to do that, I need to enhance Erik's RemoteScriptingServlet base class. Furthermore, the framework can be simplified to improve efficiency, given that polling from each CSR's incoming call monitor can put a heavier load on the server side. Again, I can do this because I don't need to send large amounts of data back and forth.


Enough talk; here comes the code

The code snippets are arranged in the same order in which they execute.

The client side

Figure 2 shows the Incoming Call Monitor as created with the monitor.jsp file.


Figure 2. Incoming call monitor (monitor.jsp)
Incoming Call Monitor

A few lines of JavaScript and HTML can get the job done in monitor.jsp and rpc.jsp.

Define a zero height- and width-hidden IFRAME called "ctiframe" (making it invisible on the Web page).


Listing 1. Define a hidden IFRAME (monitor.jsp)
<iframe id="ctiframe" width=0 height=0 border=0 > </iframe>

init() polls the server every five seconds inside checkCall() after the page loads.

checkCall() makes an HTTP GET request inside the hidden IFRAME to AnyCallServlet's (mapped from /anycall according to WEB-INF/web.xml) getIncomingCall method (instance method).


Listing 2. Create an HTTP GET request in the hidden IFRAME (monitor.jsp)
 function init() {
   setInterval(checkCall, 5000);
 }
 // RPC function on server side 
 function checkCall() {
 document.all.ctiframe.src='/cti/anycall?rsfunc=
      getIncomingCall&callback=gotCall';
}

The server side

All I have to do now is implement the remote method: String getIncomingCall(CSRUser user) in the AnyCallServlet class.

This remote method is called by the superclass RSServlet's doGet(). RSServlet is the major workhorse for invoking the remote method using the Java Reflection API. The idea comes from Erik's work, except the remote method is an instance method here rather than a static one. This gives the advantage gaining access to the object model in the CRM system.

Consider the sky your limit when it comes to scripting remotely. As long as that remote method takes CSRUser as an argument, you can make any remote method call on any subclass of RSServlet. Go ahead and apply this to any of the ideas in your imagination.


Listing 3. Make remote method calls on RSServlet subclasses
  public class AnyCallServlet extends RSServlet {

    static final String NO_CALL="nocall";

    // helper method get the User

    public CSRUser getUser(HttpServletRequest request) {

      // get the HttpSession from the request
      HttpSession session=request.getSession(false);
      // get the CSRUser from HttpSession
      CSRUser user=(CSRUser)session.getAttribute("user");

      return user;
 }


    public String getIncomingCall(CSRUser user)
    {
      IncomingCall call = CallQueueManager.getPendingCall(user);

      String retVal=NO_CALL;
      if (call!=null) retVal=call.toString();


      return retVal;
 }

The IncomingCall class has a toString() method that returns contactInfo in an ampersand-separated name value pair that eventually gets sent to IE.


Listing 4. toString() method returns contactInfo
 public class IncomingCall {
 
  public String toString() {

   return "contactid="+contact.getId()+"&name="+callerName+
        "&no="+callerNumber;
  }
 }

The servlet forwards to a JSP file (rpc.jsp) for this hidden IFRAME. The JSP file calls window.parent.gotCall() (window.parent refers to the windows that monitor.jsp lives in) with the returned value as a String from the remote method getIncomingCall. Note that the values for callback and rpcvalue will be set in RSServlet.doGet().


Listing 5. Servlet requests results from the hidden IFRAME (rpc.jsp)
 <script>
 window.parent.<%=request.getParameter("callback")%>
      ('<%=request.getAttribute("rpcvalue")%>')
 </script>

gotCall() is the callback function which is invoked by IFRAME's rpc.jsp as above with the contactInfo as parameter. Then it invokes contact.jsp to display the contact name and phone number to the CSR.


Listing 6. IFRAME's rpc.jsp invokes the callback function (monitor.jsp )
  // call back function
  function gotCall(retVal) {
    if (retVal.indexOf('nocall')!= 0) {
      document.location.href="/cti/jsp/contact.jsp?"+retVal;
    }
  }


Demo instructions

The code is tested on Tomcat 4.1.27 and can be simply unzipped to Tomcat's webapps directory where you'll find the README file. After Tomcat starts up successfully, go to http://localhost:8080/cti/ to see the demo. The code is distilled to illustrate key design and implementation techniques, though not for a full blown version.



Download

NameSizeDownload method
wa-remotescrpt-cti.zip HTTP

Information about download methods


Resources

About the author

Victor Yongwei Yang is working for IBM's Toronto Lab as a software developer. He holds a MSCS from Georgia Tech. Since 1994 he has worked for numerous companies including AT&T, S1,IBM, Sun Microsystems, SunLife, and CIBC. He is a Sun certified programmer and Web developer. He can be reached at victory@ibm.ca.com or yanixsoft@yahoo.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, Java technology
ArticleID=10885
ArticleTitle=Remote scripting servlet in action
publish-date=11112003
author1-email=victory@ca.ibm.com
author1-email-cc=