Integrating with Java Servlets and JSP Pages


ColdFusion MX 7 lets you use ColdFusion pages, JavaServer Pages (JSPs), and servlets together in a single application, or as a means to share certain Web pages among applications. This section explores exactly what you can and cannot do with respect to these technologies.

You can't freely mix the different types of code in the same code file, but you can do any of the following:

  • Use the getPageRequest().include() method to include a JSP page or servlet midstream, within your ColdFusion page. You will be able to share variables among them.

  • Use getPageRequest().forward() to pass responsibility for the page request to a JSP page or servlet. You can set certain variables in ColdFusion beforehand to make them visible to the JSP page or servlet. Again, getPageRequest() is new for ColdFusion MX 7, so this was not possible with earlier versions of the product.

  • Use <cfhttp> to connect to a JSP page or servlet, perhaps including its output midstream. In general, the include() and forward() methods are more sophisticated, so I recommend that you use them instead of <cfhttp> unless you have a specific reason not to.

  • Create client-driven links to JSP pages or servlets by specifying the appropriate URL in link HREF attributes, form ACTION attributes, and the like. Of course, you can pass whatever parameters you wish in the URL, and the pages may still be able to share application and session variables.

NOTE

ColdFusion 5 included <cfservlet> and <cfservletparam> tags for invoking servlets in ColdFusion pages. These tags have been removed (deprecated) from the CFML language. Don't use them when developing pages for ColdFusion MX or later.


Understanding Which Variables Can Be Shared

The following variables can be shared effortlessly among ColdFusion pages, JSP pages, and servlets:

  • REQUEST variables, as long as you're using forward() or include() rather than <cfhttp> or client-driven linking

  • APPLICATION variables

  • SESSION variables, as long as the Use J2EE Session Variables option is enabled on the Memory Variables page of the ColdFusion Administrator

The following variables cannot be shared directly, but can be shared by copying their values into the REQUEST scope:

  • Local CFML variables (that is, variables in the VARIABLES scope)

  • CLIENT variables

  • SERVER variables

Sharing REQUEST Variables

Sharing REQUEST variables among ColdFusion pages, JSP pages, and servlets is easy and straightforward. Here's how it works.

All servlets and JSP pages can access an instance of a class called ServletRequest. Within the body of a JSP or servlet, this ServletRequest instance is traditionally referred to as a variable called request. Among other things, the ServletRequest object allows developers to get and set attributes (basically variables) by name using methods called request.getAttribute() and request.setAttribute(). These methods are commonly used to share values between JSP pages and servlets. If a servlet sets a variable called age using request.setAttribute("age",31), then a JSP file participating in the same page request can read that value using request.getAttribute("age"), and vice versa. Simple enough.

So, what does this have to do with integrating with ColdFusion? Well, in ColdFusion MX 7, the REQUEST scope is really a set of JSP/servlet-style request attributes in disguise. Whenever you set a variable in the REQUEST scope, ColdFusion MX 7 is really using setAttribute() to set a variable in the J2EE request object, and when you use getAttribute(), you're really getting an attribute from the request object.

You can easily prove this to yourself in a ColdFusion page by setting an ordinary REQUEST variable called REQUEST.Age. You can now output the value of the variable using the getAttribute() method of the underlying J2EE response object. In ColdFusion, you get to the underlying response object using GetPageContext().getResponse(), as explained in Table 29.5. Putting all that together, the following snippet displays "Your age is 31," and then "Your age is 32."

 <!--- Create request variable ---> <cfset REQUEST.Age = 31> <!--- Output the request variable using underlying J2EE response object ---> <P>Your age is <cfoutput>#GetPageContext().getRequest().getAttribute("age")#</cfoutput> <!--- Change the value of the request variable ---> <cfset GetPageContext().getRequest().setAttribute("age", 32)> <!--- Display the variable normally ---> <P>Your age is now <cfoutput>#REQUEST.Age#</cfoutput> 

If you have any experience with JSP or servlets, you can probably see where this is going. Assuming that it has been included in the same page request using include() or forward() as explained in Table 29.5, a JSP page could output the value of REQUEST.Age like so:

 <%= request.getAttribute("age") %> 

Similarly, a servlet could output the value using the following:

 response.getWriter().print( request.getAttribute("age") ); 

Either a servlet or a JSP page could change the variable's value like this:

 request.setAttribute("age", 32); 

Shared Variables and Case-Sensitivity

ColdFusion's REQUEST scope is not case-sensitive, but J2EE request attributes are. ColdFusion resolves the difference by always setting attributes using lowercase attribute names. That's why age is used instead of Age in getAttribute() in that last code snippet.

Because ColdFusion isn't case-sensitive, this is all less of an issue when reading variables in your ColdFusion code. If you use setAttribute() to set a request variable in your JSP or servlet code, ColdFusion can get to the variable using REQUEST.Age or REQUEST.age or REQUEST.AGE, regardless of whether you used Age or age or some other capitalization in your setAttribute() call.

In the unlikely event that your JSP or servlet code is actually using setAttribute() to set two separate attributes called age and Age, the CFML REQUEST scope won't be able to discern between them; the one you would actually get at run time isn't defined. In such a situation, you can use GetPageContext().getRequest().getAttribute() in your ColdFusion code as a workaround.

TIP

Just to avoid confusion, you should consider using all lowercase variable names for any REQUEST variables that you intend to share with JSP pages or servlets. If you do so in your ColdFusion, JSP, and servlet code, you won't have any of these minor case-sensitivity issues to keep in mind.


Shared Variables and Data Types

In addition to being easy and forgiving in terms of case, ColdFusion is easy and forgiving when it comes to data types. Most simple CFML variables (strings and numbers) are stored internally as strings until you use them in some other context, in which case they are "automagically" parsed or converted to the appropriate type for you. This means that Java will receive most variables as strings unless you take specific steps otherwise.

For instance, when you create a variable like the following, it's stored internally as a string, even though there aren't any quotation marks around the right side of the statement:

 <cfset REQUEST.Age = 31> 

As such, request.getAttribute("age") will return a string in Java Land, which could be a problem if you are trying to refer to the value as an integer. For instance, the following will fail at run time because of a type mismatch between java.lang.String and java.lang.Integer:

 Integer age = (Integer)request.getAttribute("age"); 

It's up to you whether you solve this issue on the ColdFusion side or Java side. In most cases, it probably makes the most conceptual sense to solve it on the ColdFusion side using JavaCast() whenever possible. The recommended way out of this particular dilemma, then, would be to cast the value as an int when you set the REQUEST variable, like so:

 <cfset REQUEST.Age = JavaCast("int", 31)> 

NOTE

I hope this won't confuse the issue, but if a value is already known to be a number on the ColdFusion side, it will be exposed to Java as a Double. For instance, if the REQUEST.Age variable were created as a result of a mathematical computation, or using Val(31) instead of just 31, any Java code expecting the value to be a java.lang.Double would work fine without the need for an explicit JavaCast() in your ColdFusion code. To put it another way, Val() and JavaCast("double") are more or less synonymous in ColdFusion MX 7.


Shared Variables and Multifaceted Values

If you are using a multifaceted ColdFusion variable such as an array, you should be aware of how it will be received by Java. Table 29.6 summarizes the object types that will be received when Java's getAttribute() method is used to access a value in ColdFusion's REQUEST scope.

Table 29.6. How CFML Variables Are Exposed to Java

COLDFUSION TYPE

JAVA TYPE

string

String

date

java.util.Date

number

java.lang.Double, unless cast specifically as an int or long with JavaCast()

structure

coldfusion.runtime.struct, which implements the java.util.Map interface, meaning that you can use it in the same basic way you use java.util.Hashtable objects. Nested structures within the structure will also be objects that implement java.util.Map.

array

coldfusion.runtime.Array, which is a subclass of java.util.Vector

query recordset

coldfusion.sql.QueryTable, which implements the java.sql.ResultSet interface.


A Simple Example

The next few code listings show how easy it is to create ColdFusion pages that incorporate logic and output from existing JSP pages or servlets. Listing 29.9 is a ColdFusion page that uses GetPageContext().include() to include output from a JSP page and then a servlet. The JSP page and servlet are both able to refer to the REQUEST.Name variable set by ColdFusion. The servlet also changes the value of the variable, and the change is reflected in ColdFusion and displayed at the bottom of the page (Figure 29.5).

Listing 29.9. IntegratingCFML.cfm A ColdFusion Page that Includes a JSP Page and a Servlet Page
 <!---  Filename: IntegratingCFML.cfm  Author: Nate Weiss (NMW)  Purpose: Shows how ColdFusion pages, JSP pages, and Servlets can  participate in the same page request ---> <html> <head><title>ColdFusion, JSP, and Servlet Integration</title></head> <body> <h2>A Friendly Conversation</h2> <!--- Set a variable in the REQUEST scope. ---> <!--- This variable will be visible to any included JSP and Servlet pages ---> <cfset REQUEST.Name = "Nate"> <!--- Display a simple message, using normal ColdFusion syntax ---> <cfoutput>  <b>Hello, #REQUEST.Name#. This is ColdFusion talking.</b><br>  You and really I have some issues that we need to work out, don't we?<br>  Oh wait, Dr. JSP wants to have a word with you.<br> </cfoutput> <!--- Include a JSP page ---> <cfset GetPageContext().include("IntegratingJSP.jsp")> <!--- Another ColdFusion message ---> <cfoutput>  <p><b>Um, hi, this is ColdFusion again.</b><br>  What happened, did Dr. JSP forget what she was going to say again?  Those JSPs tend to flake out from time to time.  I'll pass you over to IntegratingServlet now.  A word of warning: he's a bit... stressed out lately.  I hope you make it back in one piece...<br> </cfoutput> <!--- Include a Java Servlet ---> <cfset GetPageContext().include("/servlet/IntegratingServlet")> <!--- Show that REQUEST variable can be changed by JSP pages or Servlets ---> <cfoutput>  <p><b>Hi, this is ColdFusion once again.</b><br>  Well, it's sure been nice talking to you, #REQUEST.Name#.<br>  Have a nice afternoon!<br> </cfoutput> </body> </html> 

Figure 29.5. A ColdFusion page, JSP page, and servlet can all participate in the same page request


Listing 29.10 shows the code for the JSP page that is included by the ColdFusion page in Listing 29.9. Note that it is able to use standard JSP-style request.getAttribute() syntax to refer to the value that ColdFusion calls REQUEST.Name.

Listing 29.10. IntegratingJSP.jspJSP Page Included by Listing 29.9
 <%--  Filename: IntegratingJSP.jsp  Author: Nate Weiss (NMW)  Purpose: Demonstrates variable-sharing between environments --%> <%-- The REQUEST variable that was set in the ColdFusion page --%> <%-- is available here as an attribute of the JSP "request" object --%> <p> <b>Hi there <%= request.getAttribute("name") %>. Dr. JSP here... how ya doing?</b><br> Gosh, this is embarassing, but I completely forgot what I was going to say.<br> I''m going to pass you back to ColdFusion now. Peace out, dude!<br> 

NOTE

ColdFusion MX 7 can process JSP pages, so you're probably already all set to execute this part of the example. If you're not using ColdFusion MX 7's built-in Web server, it's possible that you'll need to add a mapping to your Web server software so it knows to pass requests for .jsp pages to ColdFusion. See your Web server documentation for details.


Listing 29.11 shows the Java code for the simple Java servlet that is included by the ColdFusion page from Listing 29.9. Again, the code is able to use standard servlet-style getAttribute() syntax to get the value of the REQUEST.Name variable known to ColdFusion. Similarly, it's able to use setAttribute() to change the value. The servlet could, of course, use setAttribute() to create entirely new variables, which would also become visible to ColdFusion in the REQUEST scope.

Listing 29.11. IntegratingServlet.javaJava Servlet Included by Listing 29.9
 /*  Filename: IntegratingServlet.java  Author: Nate Weiss (NMW)  Purpose: Demonstrates variable-sharing between environments */ import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class IntegratingServlet extends HttpServlet {  public void doGet(HttpServletRequest req, HttpServletResponse resp)  throws IOException, ServletException {  // Get reference to the servlet's PrintWriter. This object's print()  // method is similar conceptually to <cfoutput> or WriteOutput() in CFML  PrintWriter out = resp.getWriter(); out.print("<p><b>Well, hellooooo there.</b> ");  out.print("<b>This is IntegratingServlet speaking.</b><br>");  out.print("I'm not sure how much you've heard about me, but I am a bit");  out.print(" crazy. In particular, I like to refer to everyone I meet");  out.print(" as if they were teen pop sensation Belinda Foxile. So, ");  out.print( req.getAttribute("name") );  out.print(", you don't mind if I call you Belinda, do you? In fact, ");  out.print(" I'm going to ask ColdFusion to call you Belinda too, ok?");  // Change the value of the name attribute  // (which corresponds to the REQUEST.name variable in ColdFusion)  req.setAttribute("name", "Belinda");  } } 

If you want to test out this servlet example, you need to use javac to compile the Java class into the corresponding IntegratingServlet.class file, and then place it into the appropriate location on your Web server. If you are using the stand-alone version of ColdFusion MX 7, that location is typically the CFusionMX/wwwroot/WEB-INF/classes folder. If you're running ColdFusion under a different J2EE server, the location may be different. If you're using ColdFusion under IIS or some other non-J2EE server, then you may need to install a separate servlet host to see this example in action.



Advanced Macromedia ColdFusion MX 7 Application Development
Advanced Macromedia ColdFusion MX 7 Application Development
ISBN: 0321292693
EAN: 2147483647
Year: 2006
Pages: 240
Authors: Ben Forta, et al

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net