Maintainer: Richard Vowles, rvowles@esperanto.org.nz (http://www.esperanto.org.nz)
For text users of this document, there is now an HTML version at the above web address.
Other topics + descriptions & additions gladly accepted. Looking for information on:
JSP is a dynamic scripting capability for web pages that allows Java as well as a few special tags to be embedded into a web file (HTML/XML, etc). The suffix traditionally ends with .jsp to indicate to the web server that the file is a JSP file. JSP is a server side technology - you can't do any client side validation with it. JSP files actually get compiled into Servlets, so what is the point? Why not just write Servlets? For most people, the benefit is twofold:
JSP is a dynamic scripting capability for web pages that allows Java as well as a few special tags to be embedded into a web file (HTML/XML, etc). The suffix traditionally ends with .jsp to indicate to the web server that the file is a JSP file. JSP is a server side technology - you can't do any client side validation with it.
JSP files actually get compiled into Servlets, so what is the point? Why not just write Servlets?
For most people, the benefit is twofold:
In the past, people have used servlets because of the problem of redirection - because by the time the JSP engine gets around to writing information back down the HTTP pipe, you could not do a redirect effectively in JSP - leading to the concepts of Model 1 vs Model 2 (see question 38). This has been fixed in JSP 1.0 with the addition of buffered output streams. JavaSoft also has a FAQ, covering different questions, and it is located at http://java.sun.com/products/jsp/faq.html.
In the past, people have used servlets because of the problem of redirection - because by the time the JSP engine gets around to writing information back down the HTTP pipe, you could not do a redirect effectively in JSP - leading to the concepts of Model 1 vs Model 2 (see question 38). This has been fixed in JSP 1.0 with the addition of buffered output streams.
JavaSoft also has a FAQ, covering different questions, and it is located at http://java.sun.com/products/jsp/faq.html.
The current version of JSP is 1.0. It is available from http://java.sun.com/products/jsp. The public draft of JSP 1.1 is available from http://java.sun.com/products/jsp/techinfo.html. The 0.92 spec is available from http://java.sun.com/products/jsp/jsp092.html The 0.91 spec is a popular version though, and much software that supports the JSP pre-standard actually supports 0.91 of JSP. The 0.91 spec is available from http://www.burridge.net/jsp/Spec91/jsp_spec.html
The current version of JSP is 1.0. It is available from http://java.sun.com/products/jsp.
The public draft of JSP 1.1 is available from http://java.sun.com/products/jsp/techinfo.html.
The 0.92 spec is available from http://java.sun.com/products/jsp/jsp092.html
The 0.91 spec is a popular version though, and much software that supports the JSP pre-standard actually supports 0.91 of JSP.
The 0.91 spec is available from http://www.burridge.net/jsp/Spec91/jsp_spec.html
You can get the current spec from http://java.sun.com/products/jsp. This is along with the reference implementation which works with its own web server.
There are the following implementations available: Name Version of JSP Supported Location Cost Comments JSP Reference 1.0 PD** http://java.sun.com/products/jsp free GNU JSP 0.91 http://www.klomp.org/gnujsp/ free, open source Java Web Server 2.0 1.0 http://java.sun.com/products/jws commercial JavaSoft's own Java Web Server. Being replaced with iPlanet (Alliance) PolyJSP 0.92 http://www.plenix.org/polyjsp free, open source PolyJsp is based on XML/XSL and has been designed to be extensible. Now supports WebL Resin 1.0 http://www.caucho.com/ free for personal use A 0.92 implementation for compiled JavaScript SJSP 1.1 http://web.iol.cz/sator/projects/sjsp-1-1/index.html free for personal use Uses compile time introspection zJSP 0.91 http://www.zachary.com/creemer/zjsp.html JRUN 0.92, 1.0PD http://www.livesoftware.com/ commercial LiveSoftware are key players in the JSP standards process . WebSphere 0.92 http://www.software.ibm.com/webservers/ commercial IBM's WebSphere is part of a larger Application Server product. Orion 0.92, 1.0PD http://orion.evermind.net/ commercial Orion is a web server that implements JSP internally. ServletExec 1.0 http://orion.evermind.net/ commercial Supports large number of web servers RocketJSP 1.0 http://rocketjsp.homepage.com/ GPL Java implementation 1.0PD = JSP 1.0 Public Draft ** - when I went to download it again after the full release announcement, it hadn't changed in size. This leads me to believe it still supports the public draft specification.
There are the following implementations available:
1.0PD = JSP 1.0 Public Draft
** - when I went to download it again after the full release announcement, it hadn't changed in size. This leads me to believe it still supports the public draft specification.
There are now a number of books available on JSP from various publishers. There is a group of people working on a Web book for JSP - information is located at http://www.esperanto.org.nz/jspbook. There is another at http://www.aptura.com/technology/jspBook_Architectures.html.
There are now a number of books available on JSP from various publishers.
There is a group of people working on a Web book for JSP - information is located at http://www.esperanto.org.nz/jspbook. There is another at http://www.aptura.com/technology/jspBook_Architectures.html.
This is a matter of great debate. Many punters think that JavaSoft has the benefit of hindsight - what works well and what does't. ASP is very complex but supports multiple scripting languages and the ActiveX model of Microsoft. Although ASP _is_ available on many platforms, the ActiveX library support that makes it as powerful as it is is missing and thus makes ActiveX only feasible for an NT platform. According to recent statistics (see the RedHat site), 22% of web servers are NT, (21% are Linux), that means there is 78% needing something else, and JSP advocates believe that JSP fits the bill nicely that you very much.
This is a matter of great debate. Many punters think that JavaSoft has the benefit of hindsight - what works well and what does't. ASP is very complex but supports multiple scripting languages and the ActiveX model of Microsoft. Although ASP _is_ available on many platforms, the ActiveX library support that makes it as powerful as it is is missing and thus makes ActiveX only feasible for an NT platform.
According to recent statistics (see the RedHat site), 22% of web servers are NT, (21% are Linux), that means there is 78% needing something else, and JSP advocates believe that JSP fits the bill nicely that you very much.
Most of the visual developers do not support JSP in any way, shape or form, they mess up the tags totally. The following HTML editors have been known to work with JSP: Product Location Comments HomeSite http://www.allaire.com/ JSP colour coding will be in HS 4.0.1, but you can get a plug in now from http://www.burridge.net/jsp/homesite.html NetObjects ScriptBuilder 3.0 http://www.netobjects.com/products/html/nsb3.html Win32 product supports JSP 0.91 Any text editor DrumBeat 2000 For use with WebSphere and DB2 There is some rumour that DreamWeaver 2 is also able to support JSP - any confirmation?
Most of the visual developers do not support JSP in any way, shape or form, they mess up the tags totally. The following HTML editors have been known to work with JSP:
There is some rumour that DreamWeaver 2 is also able to support JSP - any confirmation?
I have been picking up some comments:Brian Burridge, brian_burridge@VALPAK.COM "Our extranets for 300 franchises, 500+ users, our Intranet for thousands of employees, and eventually all of our other web sites. New Atlanta has been running for 6 weeks now without even one problem. Programming in JSP has turned out to be as easy as Perl, yet all our tests show it to be up to 10x faster."
I have been picking up some comments:
Brian Burridge, brian_burridge@VALPAK.COM "Our extranets for 300 franchises, 500+ users, our Intranet for thousands of employees, and eventually all of our other web sites. New Atlanta has been running for 6 weeks now without even one problem. Programming in JSP has turned out to be as easy as Perl, yet all our tests show it to be up to 10x faster."
JSP files are just like HTML files, so if your index.jsp file is in your root directory of your web site, use http://localhost/index.jsp
(Contributed by: Thomas-Bernhard.O-Hare@Dresdner-Bank.com) After scanning through archives of the JSP mailing list to no effect I finally remembered that I'd pasted this example into a document I wrote. It was originally sent by Satish Dharmaraj of Sun to show the model 2 approach (as described in the 0.92 specification): how to pass data from a servletto a JSP. Create a directory called model1/ under the samples/ directory. Place foo.jsp and Foo.java inside this directory. Compile FooServlet.java and place FooServlet.class in TOP/servlets/directory. Then invoke using http://host:8080/servlet/FooServlet In this example, FooServlet creates a list and then stores the result in Foo.class. Foo.Class is then passed as a datasource to foo.jsp. The sources are: 1) FooServlet.javaimport java.io.*; import javax.servlet.*; import javax.servlet.http.*; import model1.Foo; public class FooServlet extends HttpServlet { public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String s[] = new String[] {"blue", "green", "red"}; Foo f = new Foo(s); req.setAttribute("foo", f); getServletContext().getRequestDispatcher("/samples/model1/foo.jsp").forward (req, res); }} 2) foo.jsp<html> <usebean name=foo type=model1.Foo lifespan=page> </usebean> <ul> <loop property=foo:list propertyelement=x> <li> <display property=x> </loop> </ul> </html> 3) Foo.javapackage model1; public class Foo { String s[]; public String[] getList() { return s; } public Foo(String s[]) { this.s = s; } }(from "O¢¥Hare, Thomas Bernhard" <Thomas-Bernhard.O-Hare@Dresdner-Bank.com>)
(Contributed by: Thomas-Bernhard.O-Hare@Dresdner-Bank.com)
After scanning through archives of the JSP mailing list to no effect I finally remembered that I'd pasted this example into a document I wrote. It was originally sent by Satish Dharmaraj of Sun to show the model 2 approach (as described in the 0.92 specification): how to pass data from a servletto a JSP.
Create a directory called model1/ under the samples/ directory. Place foo.jsp and Foo.java inside this directory.
Compile FooServlet.java and place FooServlet.class in TOP/servlets/directory.
Then invoke using http://host:8080/servlet/FooServlet
In this example, FooServlet creates a list and then stores the result in Foo.class. Foo.Class is then passed as a datasource to foo.jsp.
The sources are:
1) FooServlet.java
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import model1.Foo; public class FooServlet extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { String s[] = new String[] {"blue", "green", "red"}; Foo f = new Foo(s); req.setAttribute("foo", f); getServletContext().getRequestDispatcher("/samples/model1/foo.jsp").forward (req, res); }
}
2) foo.jsp
<html> <usebean name=foo type=model1.Foo lifespan=page> </usebean> <ul> <loop property=foo:list propertyelement=x> <li> <display property=x> </loop> </ul> </html>
3) Foo.java
package model1; public class Foo {
String s[]; public String[] getList() { return s; } public Foo(String s[]) { this.s = s; } }
(from "O¢¥Hare, Thomas Bernhard" <Thomas-Bernhard.O-Hare@Dresdner-Bank.com>)
There are actually three different ways to do it, depending on how long the reference should last, and which JSP pages (and servlets, for that matter) should be able to see it. In each of the cases, assume that "myBean" is a reference to the bean you want to send, and that "theBean" is the key I'm going to use to store the bean under (from the servlet perspective), and use as the identity of the bean in the JSP page. These techniques are portable to any environment compliant with the servlet API 2.1 and JSP 1.0 specifications. In each case, the passingworks from servlet->JSP, servlet->servlet, JSP->JSP, or JSP->servlet transitions. (1) Request Lifetime Use this technique to pass beans that are relevant to this particular request to a bean you are calling through a request dispatcher (using either "include" or "forward"). This bean will disappear after processing this request has been completed.SERVLET: request.setAttribute("theBean", myBean); RequestDispatcher rd = getServletContext().getRequestDispatcher('/thepage.jsp"); rd.forward(request, response); JSP PAGE: <jsp:useBean id="theBean" scope="request" class="....." /> (2) Session Lifetime Use this technique to pass beans that are relevant to a particular session (such as in individual user login) over a number of requests. This bean will disappear when the session is invalidated or it times out, or when you remove it.SERVLET: HttpSession session = request.getSession(true); session.putValue("theBean", myBean); /* You can do a request dispatcher here, or just let the bean be visible on the next request */ JSP PAGE: <jsp:useBean id="theBean" scope="session" class="..." /> (3) Application Lifetime Use this technique to pass beans that are relevant to all servlets and JSP pages in a particular app, for all users. For example, I use this to make a JDBC connection pool object available to the various servlets and JSP pages in my apps. This bean will disappear when the servlet engine is shut down, or when you remove it.SERVLET: getServletContext().setAttribute("theBean", myBean); JSP PAGE: <jsp:useBean id="theBean" scope="application" class="..." /> Craig McClanahan
There are actually three different ways to do it, depending on how long the reference should last, and which JSP pages (and servlets, for that matter) should be able to see it. In each of the cases, assume that "myBean" is a reference to the bean you want to send, and that "theBean" is the key I'm going to use to store the bean under (from the servlet perspective), and use as the identity of the bean in the JSP page.
These techniques are portable to any environment compliant with the servlet API 2.1 and JSP 1.0 specifications. In each case, the passingworks from servlet->JSP, servlet->servlet, JSP->JSP, or JSP->servlet transitions.
(1) Request Lifetime
Use this technique to pass beans that are relevant to this particular request to a bean you are calling through a request dispatcher (using either "include" or "forward"). This bean will disappear after processing this request has been completed.
SERVLET: request.setAttribute("theBean", myBean); RequestDispatcher rd = getServletContext().getRequestDispatcher('/thepage.jsp"); rd.forward(request, response); JSP PAGE: <jsp:useBean id="theBean" scope="request" class="....." />
(2) Session Lifetime
Use this technique to pass beans that are relevant to a particular session (such as in individual user login) over a number of requests. This bean will disappear when the session is invalidated or it times out, or when you remove it.
SERVLET: HttpSession session = request.getSession(true); session.putValue("theBean", myBean); /* You can do a request dispatcher here, or just let the bean be visible on the next request */ JSP PAGE: <jsp:useBean id="theBean" scope="session" class="..." />
(3) Application Lifetime
Use this technique to pass beans that are relevant to all servlets and JSP pages in a particular app, for all users. For example, I use this to make a JDBC connection pool object available to the various servlets and JSP pages in my apps. This bean will disappear when the servlet engine is shut down, or when you remove it.
SERVLET: getServletContext().setAttribute("theBean", myBean); JSP PAGE: <jsp:useBean id="theBean" scope="application" class="..." />
Craig McClanahan
It depends on your JSP server, but generally, JSP works by compiling your JSP file into a servlet, then executing that servlet. The JSP server checks for changes between the compiled servlet and the JSP page each time there is a request. See (30) for more info.
Controlling connections to the database is a desirable thing - having to connect to the database for each page is is expensive, and keeping a connection in a session variable is far too expensive in terms of client connections to the database. Thus, people often create pools for connections to the database that the client comes in and gets and then returns when complete (making sure a try/catch is used to ensure the connection is returned!). My personal bias indicates that you shouldn't pool connections to your database inside JSP, you should be using a middleware layer and communicating to it (like RMI or CORBA). However, people do write entire applications in JSP and beans that reside in the web server, so how do you do it? From: Bradley Wood <Brad@MARKETING.CO.UK> probably instantiate this as a singleton in the global.jsa and then call it. for more on this and how its called check the downloadable code examples for this book at www.ora.comimport java.sql.*; import java.util.*; public class ConnectionPool { private Hashtable connections; private int increment; private String dbURL, user, password; public ConnectionPool(String dbURL, String user, String password, String driverClassName, int initialConnections, int increment) // int max? throws SQLException, ClassNotFoundException { // Load the specified driver class Class.forName(driverClassName); this.dbURL = dbURL; this.user = user; this.password = password; this.increment = increment; connections = new Hashtable(); // Put our pool of Connections in the Hashtable // The FALSE value indicates they're unused for(int i = 0; i < initialConnections; i++) { connections.put(DriverManager.getConnection(dbURL, user, password), Boolean.FALSE); } } public Connection getConnection() throws SQLException { Connection con = null; Enumeration cons = connections.keys(); synchronized (connections) { while(cons.hasMoreElements()) { con = (Connection)cons.nextElement(); Boolean b = (Boolean)connections.get(con); if (b == Boolean.FALSE) { // So we found an unused connection. // Test its integrity with a quick setAutoCommit(true) call. // For production use, more testing should be performed, // such as executing a simple query. try { con.setAutoCommit(true); } catch(SQLException e) { // Problem with the connection, replace it. con = DriverManager.getConnection(dbURL, user, password); } // Update the Hashtable to show this one's taken connections.put(con, Boolean.TRUE); // Return the connection return con; } // if } // while } // synchro // If we get here, there were no free connections. // We've got to make more. for(int i = 0; i < increment; i++) { connections.put(DriverManager.getConnection(dbURL, user, password), Boolean.FALSE); } // Recurse to get one of the new connections. return getConnection(); } public void returnConnection(Connection returned) { Connection con; Enumeration cons = connections.keys(); while (cons.hasMoreElements()) { con = (Connection)cons.nextElement(); if (con == returned) { connections.put(con, Boolean.FALSE); break; } } } // returnConnection } // class From: Andre Richards <AndreRic@mweb.co.za> A very good example on connection pooling when using Servlets can be found at : http://webdevelopersjournal.com/columns/connection_pool.htmlI succesfully used it in JSP 0.91 as follows :<script RUNAT="SERVER"> DBConnectionManager connMgr = DBConnectionManager.getInstance(); </script> <% Connection con = connMgr.getConnection("freetds"); if (con == null) { out.println("Can't get connection"); return; } try { Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery ("SELECT Hello FROM World"); while(rs.next()) { out.println(rs.getString("Hello")); } stmt.close(); rs.close();} catch (SQLException e) { e.printStackTrace(out) } connMgr.freeConnection("freetds", con); %>
Controlling connections to the database is a desirable thing - having to connect to the database for each page is is expensive, and keeping a connection in a session variable is far too expensive in terms of client connections to the database. Thus, people often create pools for connections to the database that the client comes in and gets and then returns when complete (making sure a try/catch is used to ensure the connection is returned!).
My personal bias indicates that you shouldn't pool connections to your database inside JSP, you should be using a middleware layer and communicating to it (like RMI or CORBA). However, people do write entire applications in JSP and beans that reside in the web server, so how do you do it?
From: Bradley Wood <Brad@MARKETING.CO.UK>
probably instantiate this as a singleton in the global.jsa and then call it.
for more on this and how its called check the downloadable code examples for this book at www.ora.com
import java.sql.*; import java.util.*; public class ConnectionPool {
private Hashtable connections; private int increment; private String dbURL, user, password; public ConnectionPool(String dbURL, String user, String password, String driverClassName, int initialConnections, int increment) // int max? throws SQLException, ClassNotFoundException { // Load the specified driver class Class.forName(driverClassName); this.dbURL = dbURL; this.user = user; this.password = password; this.increment = increment; connections = new Hashtable(); // Put our pool of Connections in the Hashtable // The FALSE value indicates they're unused for(int i = 0; i < initialConnections; i++) { connections.put(DriverManager.getConnection(dbURL, user, password), Boolean.FALSE); } } public Connection getConnection() throws SQLException { Connection con = null; Enumeration cons = connections.keys(); synchronized (connections) { while(cons.hasMoreElements()) { con = (Connection)cons.nextElement(); Boolean b = (Boolean)connections.get(con); if (b == Boolean.FALSE) { // So we found an unused connection. // Test its integrity with a quick setAutoCommit(true) call. // For production use, more testing should be performed, // such as executing a simple query. try { con.setAutoCommit(true); } catch(SQLException e) { // Problem with the connection, replace it. con = DriverManager.getConnection(dbURL, user, password); } // Update the Hashtable to show this one's taken connections.put(con, Boolean.TRUE); // Return the connection return con; } // if } // while } // synchro // If we get here, there were no free connections. // We've got to make more. for(int i = 0; i < increment; i++) { connections.put(DriverManager.getConnection(dbURL, user, password), Boolean.FALSE); } // Recurse to get one of the new connections. return getConnection(); } public void returnConnection(Connection returned) { Connection con; Enumeration cons = connections.keys(); while (cons.hasMoreElements()) { con = (Connection)cons.nextElement(); if (con == returned) { connections.put(con, Boolean.FALSE); break; } } } // returnConnection } // class
From: Andre Richards <AndreRic@mweb.co.za>
A very good example on connection pooling when using Servlets can be found at : http://webdevelopersjournal.com/columns/connection_pool.htmlI succesfully used it in JSP 0.91 as follows :
<script RUNAT="SERVER"> DBConnectionManager connMgr = DBConnectionManager.getInstance(); </script> <% Connection con = connMgr.getConnection("freetds"); if (con == null) { out.println("Can't get connection"); return; } try { Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery ("SELECT Hello FROM World"); while(rs.next()) { out.println(rs.getString("Hello")); } stmt.close(); rs.close();} catch (SQLException e) { e.printStackTrace(out) } connMgr.freeConnection("freetds", con); %>
JSP is *Java* Server Pages, and the tags for other languages were taken out in 0.92. That said, two implementations (as of writing) support other languages: - PolyJsp, 0.92, http://www.plenix.org/polyjsp, free + open source- Resin. A JSP 0.92 implementation for compiled JavaScript, http://www.caucho.com/, free for personal use
JSP is *Java* Server Pages, and the tags for other languages were taken out in 0.92. That said, two implementations (as of writing) support other languages:
- PolyJsp, 0.92, http://www.plenix.org/polyjsp, free + open source- Resin. A JSP 0.92 implementation for compiled JavaScript, http://www.caucho.com/, free for personal use
This should work:response.setHeader("Set-Cookie", "cookie string"); To give the response-object to a bean, write a method setResponse(HttpServletResponse response)- to the bean, and in jsp-file:<% bean.setResponse (response); %> (from Aapo Kyrölä <aapo.kyrola@SATAMA.COM>)
This should work:
response.setHeader("Set-Cookie", "cookie string");
To give the response-object to a bean, write a method setResponse(HttpServletResponse response)- to the bean, and in jsp-file:
<% bean.setResponse (response); %>
(from Aapo Kyrölä <aapo.kyrola@SATAMA.COM>)
Example: I used Beans and Session with my servlet, JSP can use same Beans and Session or not? From: Robert Hodges <hodges@TILDENPARK.COM> This can be done, but you are likely to run into problems with class loaders. For instance, we have Apache/JServ which uses the AdaptiveClassLoader along with GNU-JSP which has a different class loader. If you just casually allocate objects in a servlet and then pick them up in JSP pages, you'll most likely get the dreaded ClassCastException, which signals the VM's pleasure when you try to cast a class that was brought in by a different class loader. Note that there are sometimes problems even within JSP, as GNU-JSP drops the class loader every time you recompile a page, so if you allocated a class instance using one version of the page, then recompiled and tried to fish that instance back again, you would either (1) not find it or (2) get the ClassCastException (but see para #1 above). If you really need to pass information around, the best way for Apache and GNU-JSP is to do the following: Have one server per person when developing. Make sure that all your Java classes, including servlet code, load through the system class path. This means they load through the primordial loader, which does not go away or change. Make sure that your compiled JSP pages go to another location than your regular Java classes. That way, the JSP loader will just pick them up through the primordial loader. In this scheme, you will need to reboot the Web server each time you make a change to the regular Java classes or else great confusion will ensue. (And possibly outrage among your users, I might add.) If you need to share a Web Server between multiple people, or cannot reboot whenever you make class changes, the solution is much more complex. I can post a treatise on one approach at a later time (big project, deadline Friday) if there is interest.
Example: I used Beans and Session with my servlet, JSP can use same Beans and Session or not?
From: Robert Hodges <hodges@TILDENPARK.COM>
This can be done, but you are likely to run into problems with class loaders. For instance, we have Apache/JServ which uses the AdaptiveClassLoader along with GNU-JSP which has a different class loader. If you just casually allocate objects in a servlet and then pick them up in JSP pages, you'll most likely get the dreaded ClassCastException, which signals the VM's pleasure when you try to cast a class that was brought in by a different class loader.
Note that there are sometimes problems even within JSP, as GNU-JSP drops the class loader every time you recompile a page, so if you allocated a class instance using one version of the page, then recompiled and tried to fish that instance back again, you would either (1) not find it or (2) get the ClassCastException (but see para #1 above).
If you really need to pass information around, the best way for Apache and GNU-JSP is to do the following:
In this scheme, you will need to reboot the Web server each time you make a change to the regular Java classes or else great confusion will ensue. (And possibly outrage among your users, I might add.)
If you need to share a Web Server between multiple people, or cannot reboot whenever you make class changes, the solution is much more complex. I can post a treatise on one approach at a later time (big project, deadline Friday) if there is interest.
JSP spec 0.92 wont work with JWS 1.x. There is a version mismatch in the Servet API releases and JWS (till 1.1.2) does not support JSP. Try an implementation of JSP 0.91 with JWS. (From: Anand Kumar S <anandsan@WIPSYS.SOFT.NET>) Note, JWS 2.0 is now in beta and can be downloaded from Sun's site. It supports JSP 1.0PD.
JSP spec 0.92 wont work with JWS 1.x. There is a version mismatch in the Servet API releases and JWS (till 1.1.2) does not support JSP.
Try an implementation of JSP 0.91 with JWS.
(From: Anand Kumar S <anandsan@WIPSYS.SOFT.NET>)
Note, JWS 2.0 is now in beta and can be downloaded from Sun's site. It supports JSP 1.0PD.
(Contributed by: Thomas-Bernhard.O-Hare@Dresdner-Bank.com) Using ERRORPAGE in JSP 0.92 I'm not sure if I'm using the correct approach here but in the application I'm developing each JSP page includes the line<%@ ERRORPAGE="01_error.jsp" %> and the 01_error.jsp page reads:<HTML> <USEBEAN name = "AISRB" type = "prj.servlet_utils.PresentError" lifespan = page> </USEBEAN> <HEAD> <TITLE><DISPLAY PROPERTY=AISRB:Error PLACEHOLDER="--Error Title--"></TITLE> </HEAD> <BODY> <BLOCKQUOTE> <TABLE BORDER="0"> <TR> <TD><img src="icon/oops.gif"></TD> <TD><FONT SIZE="5"> <DISPLAY PROPERTY=AISRB:Error PLACEHOLDER="--Error Title--"> </FONT></CENTER></TD> </TR> </TABLE> <P> <BR> <DISPLAY PROPERTY=AISRB:Error_Line PLACEHOLDER="--Error Line--"> <BR> <%= exception.getMessage() %> <!DISPLAY PROPERTY=exception:message PLACEHOLDER="--Error Message--"> <BR> <P> <HR size ="1"> <FONT SIZE="1">Footer</FONT> <BR> </BLOCKQUOTE> </BODY> </HTML> The bean is always present in the current request (placed there by preceding servlet); I'm actually using this approach for internationalization - the bean contains strings callled Error_line etc to say "An error has occurred" in the appropriate language. Of course, it doesn't actually contain any information on the error - this is supposed to be supplied by the exception bean. Speaking of which, I wanted to use the line<DISPLAY PROPERTY=exception:message PLACEHOLDER="--Error Message--"> to display the exception but that didn't seem to work so now I'm using<%= exception.getMessage() %> instead because it does seem to work. I rather suspect ths is not the best aprroach to reporting unexpected errors so you may not want to put it in the FAQ. If you have something better I'dbe pleased to hear about it.
Using ERRORPAGE in JSP 0.92
I'm not sure if I'm using the correct approach here but in the application I'm developing each JSP page includes the line
<%@ ERRORPAGE="01_error.jsp" %>
and the 01_error.jsp page reads:
<HTML> <USEBEAN name = "AISRB" type = "prj.servlet_utils.PresentError" lifespan = page> </USEBEAN> <HEAD> <TITLE><DISPLAY PROPERTY=AISRB:Error PLACEHOLDER="--Error Title--"></TITLE> </HEAD> <BODY> <BLOCKQUOTE> <TABLE BORDER="0"> <TR> <TD><img src="icon/oops.gif"></TD> <TD><FONT SIZE="5"> <DISPLAY PROPERTY=AISRB:Error PLACEHOLDER="--Error Title--"> </FONT></CENTER></TD> </TR> </TABLE> <P> <BR> <DISPLAY PROPERTY=AISRB:Error_Line PLACEHOLDER="--Error Line--"> <BR> <%= exception.getMessage() %> <!DISPLAY PROPERTY=exception:message PLACEHOLDER="--Error Message--"> <BR> <P> <HR size ="1"> <FONT SIZE="1">Footer</FONT> <BR> </BLOCKQUOTE> </BODY> </HTML>
The bean is always present in the current request (placed there by preceding servlet); I'm actually using this approach for internationalization - the bean contains strings callled Error_line etc to say "An error has occurred" in the appropriate language. Of course, it doesn't actually contain any information on the error - this is supposed to be supplied by the exception bean.
Speaking of which, I wanted to use the line
<DISPLAY PROPERTY=exception:message PLACEHOLDER="--Error Message--">
to display the exception but that didn't seem to work so now I'm using
<%= exception.getMessage() %>
instead because it does seem to work.
I rather suspect ths is not the best aprroach to reporting unexpected errors so you may not want to put it in the FAQ. If you have something better I'dbe pleased to hear about it.
IBM's WebSphere, LiveSoftware's JRun and New Atlanta's ServletExec all provide plug ins for IIS 4.0.
Live Software has a new newsgroup for JSP discussion at news://news.livesoftware.com/livesoftware.jsp
From: Joe Shevland <J_Shevland@TurnAround.com.au> The spec is not clear on what the Application level scope actually means, but the general discussion has it that an Application is a single JSP whose beans persist from call to call - unlike those beans which have the "page" scope. That said, the 0.92 spec still stores "application" beans at the servlet level so they can actually be used by multiple servlets. (From Gabriel Wong <gabrielw@EZWEBTOOLS.COM>)In purely Servlet terms, they mean: page - NO storage session - servletrequest.getSession(true).putValue("myobjectname",myobject); application - getServletConfig().getServletContext().setAttribute("myobjectname",myobject); request - The storage exists for the lifetime of the request, which may be forwarded between jsp's and servlets.
From: Joe Shevland <J_Shevland@TurnAround.com.au>
The spec is not clear on what the Application level scope actually means, but the general discussion has it that an Application is a single JSP whose beans persist from call to call - unlike those beans which have the "page" scope. That said, the 0.92 spec still stores "application" beans at the servlet level so they can actually be used by multiple servlets.
(From Gabriel Wong <gabrielw@EZWEBTOOLS.COM>)In purely Servlet terms, they mean:
Archives of the JSP mailing list are available at http://archives.java.sun.com/archives/jsp-interest.html These archives are searchable.
Archives of the JSP mailing list are available at http://archives.java.sun.com/archives/jsp-interest.html
These archives are searchable.
1) Instantiate an instance of the JDBC driver you're trying to use (jdbc-odbc bridge name from memory so pls check):Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ).newInstance(); This determines if the class is available and instantiates a new instance of it, making it available for the next step. 2) Ask the DriverManager for a Connection object based on the JDBC URL you are using:Connection connDB = DriverManager.getConnection( "jdbc:odbc:MyDSN", "username", "password" ); DriverManager searches through any registered drivers (instantiating a new instance above is enough to register a driver with the DriverManager, as each implementation is required to) and, based on the JDBC URL you are using, returns the appropriate implementation of Connection. 3) Create a Statement object to retrieve a ResultSetStatement smentDB = connDB.createStatement(); ResultSet rsDB = connDB.executeQuery( "SELECT * FROM Foo" ); or rsDB = connDB.executeUpdate( "UPDATE Foo SET Bar = NULL" ); 4) Close down connections to free resources:rsDB.close(); smentDB.close(); connDB.close(); Note smentDB.close() closes the rsDB object, and connDB will close smentDB, cascading down, so you can really just: connDB.Close(). Also note there's no exception handling given here. With the release of the JDBC 2.0 API, there is a CachedResultSet capability which would provide some assistance in making your pages perform better: From: DIGNE Marc <jmdigne@MEUDON.NETCABLE.TM.FR> I tested the JDBC CachedRowSet http://developer.java.sun.com/developer/earlyAccess/crs/index.html "JDBCTM CachedRowSet is an implementation of the Rowset interface. The Rowset interface is part of the JDBC 2.0 Standard Extension API. CachedRowSet provides a disconnected, serializable, scrollable container for tabular data. A CachedRowSet object can be thought of as a disconnected set of rows that are being cached outside of a data source. Data contained in a CachedRowSet may be updated and then resynchronized with the underlying tabular data source. "
1) Instantiate an instance of the JDBC driver you're trying to use (jdbc-odbc bridge name from memory so pls check):
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ).newInstance();
This determines if the class is available and instantiates a new instance of it, making it available for the next step.
2) Ask the DriverManager for a Connection object based on the JDBC URL you are using:
Connection connDB = DriverManager.getConnection( "jdbc:odbc:MyDSN", "username", "password" );
DriverManager searches through any registered drivers (instantiating a new instance above is enough to register a driver with the DriverManager, as each implementation is required to) and, based on the JDBC URL you are using, returns the appropriate implementation of Connection.
3) Create a Statement object to retrieve a ResultSet
Statement smentDB = connDB.createStatement(); ResultSet rsDB = connDB.executeQuery( "SELECT * FROM Foo" ); or rsDB = connDB.executeUpdate( "UPDATE Foo SET Bar = NULL" );
4) Close down connections to free resources:
rsDB.close(); smentDB.close(); connDB.close();
Note smentDB.close() closes the rsDB object, and connDB will close smentDB, cascading down, so you can really just: connDB.Close(). Also note there's no exception handling given here.
With the release of the JDBC 2.0 API, there is a CachedResultSet capability which would provide some assistance in making your pages perform better:
From: DIGNE Marc <jmdigne@MEUDON.NETCABLE.TM.FR>
I tested the JDBC CachedRowSet http://developer.java.sun.com/developer/earlyAccess/crs/index.html
"JDBCTM CachedRowSet is an implementation of the Rowset interface. The Rowset interface is part of the JDBC 2.0 Standard Extension API.
CachedRowSet provides a disconnected, serializable, scrollable container for tabular data. A CachedRowSet object can be thought of as a disconnected set of rows that are being cached outside of a data source.
Data contained in a CachedRowSet may be updated and then resynchronized with the underlying tabular data source. "
From: Alexander Yavorskiy <Alexander_Yavorskiy@VANTIVE.COM> Hi,An interesting observation about the variables declared in JSP pages. Any variable declared inside <% .... %> is local to the page and is not visible to outside functions, even those declare on the same JSP. Example:<% int evilVariable = "666"; %> ... function testFunction() { // do not see evilVariable from here } Why? evilVariable eventually becomes a local variable in the service() method of the resulting servlet and so is not accessible by other methods of that servlet. Any variable declared inside <%! %> become global for any function declared in the servlet.Example: <%! int evilVariable = "666"; %> ... function testFunction() { int x = evilVariable; //can get to it } Why? evilVariable declared this way becomes a private member variable of the resulting servlet and so is accessible by all other methods of that servlet. Conclusion It is important to understand this difference because in servlet environment there will only be a single(!!!) instance of the resulting servlet running and serving all requests for a particular page. Thus, potentially all of the member variables of that servlet will be share across the requests as opposed to variables local to the service() method that will be recreated for each request. So, we should be careful about putting none constant variables in <SERVER></SERVER>. At the same time, it might be useful to do so in some situations.
From: Alexander Yavorskiy <Alexander_Yavorskiy@VANTIVE.COM>
Hi,An interesting observation about the variables declared in JSP pages.
Any variable declared inside <% .... %> is local to the page and is not visible to outside functions, even those declare on the same JSP.
Example:
<% int evilVariable = "666"; %> ... function testFunction() { // do not see evilVariable from here }
Why? evilVariable eventually becomes a local variable in the service() method of the resulting servlet and so is not accessible by other methods of that servlet.
Any variable declared inside <%! %> become global for any function declared in the servlet.
Example: <%! int evilVariable = "666"; %> ... function testFunction() { int x = evilVariable; //can get to it }
Why? evilVariable declared this way becomes a private member variable of the resulting servlet and so is accessible by all other methods of that servlet.
Conclusion
It is important to understand this difference because in servlet environment there will only be a single(!!!) instance of the resulting servlet running and serving all requests for a particular page. Thus, potentially all of the member variables of that servlet will be share across the requests as opposed to variables local to the service() method that will be recreated for each request. So, we should be careful about putting none constant variables in <SERVER></SERVER>. At the same time, it might be useful to do so in some situations.
The method forward() in the Servlet API works for JSP pages, but this is only true for resources with _active_ content, like JSP pages. If you wish to forward to an HTML page, you have to use a different method: From: Volker Stiehl <stiehl@ZNNBG.SIEMENS.DE> In order to access HTML files you have to use the new "resource abstraction" feature of 2.1.Try the following:URL url = getServletContext().getResource("/abc/xyz.html"); out.println(url.getContent());
The method forward() in the Servlet API works for JSP pages, but this is only true for resources with _active_ content, like JSP pages.
If you wish to forward to an HTML page, you have to use a different method:
From: Volker Stiehl <stiehl@ZNNBG.SIEMENS.DE>
In order to access HTML files you have to use the new "resource abstraction" feature of 2.1.Try the following:
URL url = getServletContext().getResource("/abc/xyz.html"); out.println(url.getContent());
From: "Craig R. McClanahan" <cmcclanahan@mytownnet.com> http://www.software.ibm.com/ebusiness/pm.html It is titled "The Web Application Programming Model", and provides a nice overview of the basic architecture IBM proposes for web applications (essentially the "Model 2" approach from the JSP specification). There are few IBM-specific product references in this document -- simply translate their term "dynamic server pages" into JSP, and generalize "WebSphere" to any useful combination of web server, servlet engine, and app server components. There are more IBM-specific references in several of the other white papers, but they still provide a useful overview of the technology basis for large scale web-based application development and deployment. The white paper index is at: http://www.software.ibm.com/ebusiness/library.html
From: "Craig R. McClanahan" <cmcclanahan@mytownnet.com>
http://www.software.ibm.com/ebusiness/pm.html
It is titled "The Web Application Programming Model", and provides a nice overview of the basic architecture IBM proposes for web applications (essentially the "Model 2" approach from the JSP specification). There are few IBM-specific product references in this document -- simply translate their term "dynamic server pages" into JSP, and generalize "WebSphere" to any useful combination of web server, servlet engine, and app server components. There are more IBM-specific references in several of the other white papers, but they still provide a useful overview of the technology basis for large scale web-based application development and deployment. The white paper index is at:
http://www.software.ibm.com/ebusiness/library.html
From: Matti Kotsalainen <matti@RAZORFISH.COM> If you want to create GIFs, use ACME labs excellent free gifencoder(http://www.acme.com/), and then do something like this:Frame frame = null; Graphics g = null; FileOutputStream fileOut = null; try { //create an unshown frame frame = new Frame(); frame.addNotify(); //get a graphics region, using the frame Image image = frame.createImage(WIDTH, HEIGHT); g = image.getGraphics(); //manipulate the image g.drawString("Hello world", 0, 0); //get an ouputstream to a file fileOut = new FileOutputStream("test.gif"); GifEncoder encoder = new GifEncoder(image, fileOut); encoder.encode(); } catch (Exception e) { ; } finally { //clean up if (g != null) g.dispose(); if (frame != null) frame.removeNotify(); if (fileOut != null) { try { fileOut.close(); } catch (IOException ioe) { ; } } }
From: Matti Kotsalainen <matti@RAZORFISH.COM>
If you want to create GIFs, use ACME labs excellent free gifencoder(http://www.acme.com/), and then do something like this:
Frame frame = null; Graphics g = null; FileOutputStream fileOut = null; try { //create an unshown frame frame = new Frame(); frame.addNotify(); //get a graphics region, using the frame Image image = frame.createImage(WIDTH, HEIGHT); g = image.getGraphics(); //manipulate the image g.drawString("Hello world", 0, 0); //get an ouputstream to a file fileOut = new FileOutputStream("test.gif"); GifEncoder encoder = new GifEncoder(image, fileOut); encoder.encode(); } catch (Exception e) { ; } finally { //clean up if (g != null) g.dispose(); if (frame != null) frame.removeNotify(); if (fileOut != null) { try { fileOut.close(); } catch (IOException ioe) { ; } } }
As a matter of fact... (NB: This is an implementation of the HTMLEncode function that ASP has) From: Eric Lunt <elunt@YAHOO.COM> Somewhere in my net-travels I picked up this version which performs pretty well:/** * Returns an HTML rendition of the given <code>String</code>. This was * written by <a href=mailto:kimbo@biddersedge.com>Kimbo Mundy</a>. * @param text A <code>String</code> to be used in an HTML page. * @return A <code>String</code> that quotes any HTML markup * characters. If no quoting is needed, this will be * the same as <code>text</code>. */ public static String asHTML(String text) { if (text == null) return ""; StringBuffer results = null; char[] orig = null; int beg = 0, len = text.length(); for (int i = 0; i < len; ++i){ char c = text.charAt(i); switch (c){ case 0: case '&': case '<': case '>': case '"': if (results == null){ orig = text.toCharArray(); results = new StringBuffer(len+10); } if (i > beg) results.append(orig, beg, i-beg); beg = i + 1; switch (c){ default: // case 0: continue; case '&': results.append("&"); break; case '<': results.append("<"); break; case '>': results.append(">"); break; case '"': results.append("""); break; } break; } } if (results == null) return text; results.append(orig, beg, len-beg); return results.toString(); }
As a matter of fact...
(NB: This is an implementation of the HTMLEncode function that ASP has)
From: Eric Lunt <elunt@YAHOO.COM>
Somewhere in my net-travels I picked up this version which performs pretty well:
/** * Returns an HTML rendition of the given <code>String</code>. This was * written by <a href=mailto:kimbo@biddersedge.com>Kimbo Mundy</a>. * @param text A <code>String</code> to be used in an HTML page. * @return A <code>String</code> that quotes any HTML markup * characters. If no quoting is needed, this will be * the same as <code>text</code>. */ public static String asHTML(String text) { if (text == null) return ""; StringBuffer results = null; char[] orig = null; int beg = 0, len = text.length(); for (int i = 0; i < len; ++i){ char c = text.charAt(i); switch (c){ case 0: case '&': case '<': case '>': case '"': if (results == null){ orig = text.toCharArray(); results = new StringBuffer(len+10); } if (i > beg) results.append(orig, beg, i-beg); beg = i + 1; switch (c){ default: // case 0: continue; case '&': results.append("&"); break; case '<': results.append("<"); break; case '>': results.append(">"); break; case '"': results.append("""); break; } break; } } if (results == null) return text; results.append(orig, beg, len-beg); return results.toString(); }
See (30)
JSP pages are focused around HTML (or XML) with Java codes and JSP tags inside them. When a web server that has JSP support is asked for a JSP page, it checks to see if it has already compiled the page into a servlet. Thus, JSP pages become servlets and are transformed into pure Java and then compiled, loaded into the server and executed. Different JSP implementations do this in more or less efficient ways.
The following web sites contain information about JSP: An IBM Tutorial on JSP: http://www.software.ibm.com/developer/education/java/online-courses.html An IBM Red Book : http://www.redbooks.ibm.com/SG245423/sg245423.pdf Other IBM Information: http://www.software.ibm.com/webservers/appserv/doc/v20dcadv/doc/index.html The following web sites focus on JSP solutions Servlets Taverne - http://www.interpasnet.com/JSS/Oi Servlet World - http://i.am/servletformeWeb Development with JSP - http://www.burridge.net/jsp/
The following web sites contain information about JSP:
The following web sites focus on JSP solutions
Servlets Taverne - http://www.interpasnet.com/JSS/Oi Servlet World - http://i.am/servletformeWeb Development with JSP - http://www.burridge.net/jsp/
From: Andre Richards <AndreRic@MWEB.CO.ZA> I did as follows: On every page which must be authenticated, I check for a user ID in the session object - if it doesn't exit, I do a redirect to a login page, passing the url the user was trying to access as a parameter. On the login page, if the user successfully logs in, I create a session for him/her, and add the user ID to the session. I then redirect back to the original page the user tried to access. This way, even if the user bookmarks a page, he/she will be asked to login once the session has become invalid. Some code:On every page I add the following:HttpSession session = request.getSession(true); if (session.getValue("CustomerID") == null) { response.sendRedirect (response.encodeRedirectUrl ("Login.jsp?Origin=SharePortfolio.jsp")); } else { // the rest of the page ... In Login.jsp once the user has provided the correct logon credentials:session.putValue("CustomerID", CustomerID); response.sendRedirect(response.encodeRedirectUrl(request.getParameter("Origin"))); Another developer has a different approach: From: Christopher Cobb <ccobb@usgs.gov> After researching several approaches, I have finally settled on the following approach. I would like to hear how othersare solving this problem. (FAQ maintainers note: This syntax won't work with JSP 1.0) 1. User accesses GuardedPage.jsp via http://localhost/path/to/GuardedPage.jsp 2. GuardedPage.jsp includes a login checking page:<!--#include file="/admin/" file="LoginChecker.jsp" --> Every page that needs to be login-protected should include this file (which, depending on how your site is set up, may beevery page.) 3. LoginChecker.jsp accesses a bean that does the login checking:<USEBEAN lifespan="session" name ="loginChecker" type="package.LoginChecker"> <setfromrequest beanproperty = "*"> </USEBEAN> 4. The LoginChecker bean has a property 'loggedIn'. (It also has properies for Username and Password, and aprocessRequest() method, which are used later). LoginChecker.jsp checks the value of the loggedIn property. If it is not true (i.e., the user is not logged in), a loginpage is displayed:<excludeif property ="loginChecker:loggedIn" value = "true"> <FORM action="/servlet/DBAccess/path/to/GuardedPage.jsp" method="post"> Username: <input name="userName" size="15" maxlength="15" > Password: <input type="password" name="password" size="15" maxlength="15"> <input type="submit" name="loginUser" value="Submit"> </FORM> </excludeif> The first time through, this bean will be 'empty' and the loggedIn property will not be set. The login form will thereforebe displayed. 5. There is a little trick in the action clause above. When the user types in his login info and presses submit, theinvoked URL is /servlet/DBAccess/path/to/GuardedPage.jsp The action passes through the servlet DBAccess, then continues on to our original page. This servlet does nothing morethan attach an open database connection to the current session: session.putValue("open.connection", connection); The servlet then picks up the trailing part of the URL with: String trailingURL = request.getPathInfo(); It then calls forward() to pass control back to the requested page. In this example, the new page happens to be the sameas the page we came from. getServletConfig( ).getServletContext( ).getRequestDispatcher(response.encodeURL(trailingURL) ).forward(request,response); 6. Now we are back to our original page and the logginChecker bean gets invoked again. Because of the: <setfromrequest beanproperty = "*"> in the loginChecker USEBEAN tag, and because our username and password field names in the LoginChecker.jsp page match ourbean's property names, the username and password that the user typed in get 'magically' populated in the correspondingproperties of the bean. 7. The LoginChecker bean has a processRequest() method which checks to see if a username and password has been supplied.If so (and if we are not logged in), it performs a database lookup to log the user in. If the lookup is successful, theloggedIn property is set to true. 8. We are finally back to our GuardedPage.jsp page. It will probably not want to display itself unless the user is loggedin. The page should therefore only be included if loggedIn is true:<includeif property="loginChecker:loggedIn" value="true" > The contents of GuardePage.jsp are displayed only if loggedIn is true.</includeif> We're done! GuardedPage.jsp is only displayed if the user is logged in. If the user is not logged in, a login page isdisplayed, which if successful, returns the user to the original page. 9. There is one small cleanup which is needed in Step 4. As coded above, a passthrough servlet is used to attach adatabase connection to the session. If the user repeatedly fails to login, the servlet prefix will get repeatedlypre-pended to the URL. Furthermore, the 'current page' is hardcoded into the LoginChecker.jsp page which restricts it'sreusability. A little JavaScript fixes both of these problems. The following JavaScript should be used in place of the<FORM> tag in Step 4. above. <script language="JavaScript"> <!-- if (document.location.pathname.indexOf("/servlet/package.DBAccess") == 0) document.write( '<FORM action="' + document.location.pathname + '"method="post">'); else document.write( '<FORM action="/servlet/package.DBAccess' + document.location.pathname + '" method="post">'); //--> </script>
From: Andre Richards <AndreRic@MWEB.CO.ZA>
I did as follows:
On every page which must be authenticated, I check for a user ID in the session object - if it doesn't exit, I do a redirect to a login page, passing the url the user was trying to access as a parameter.
On the login page, if the user successfully logs in, I create a session for him/her, and add the user ID to the session. I then redirect back to the original page the user tried to access. This way, even if the user bookmarks a page, he/she will be asked to login once the session has become invalid.
Some code:On every page I add the following:
HttpSession session = request.getSession(true); if (session.getValue("CustomerID") == null) { response.sendRedirect (response.encodeRedirectUrl ("Login.jsp?Origin=SharePortfolio.jsp")); } else { // the rest of the page ...
In Login.jsp once the user has provided the correct logon credentials:
session.putValue("CustomerID", CustomerID); response.sendRedirect(response.encodeRedirectUrl(request.getParameter("Origin")));
Another developer has a different approach:
From: Christopher Cobb <ccobb@usgs.gov>
After researching several approaches, I have finally settled on the following approach. I would like to hear how othersare solving this problem. (FAQ maintainers note: This syntax won't work with JSP 1.0)
1. User accesses GuardedPage.jsp via
http://localhost/path/to/GuardedPage.jsp
2. GuardedPage.jsp includes a login checking page:
<!--#include file="/admin/" file="LoginChecker.jsp" -->
Every page that needs to be login-protected should include this file (which, depending on how your site is set up, may beevery page.)
3. LoginChecker.jsp accesses a bean that does the login checking:
<USEBEAN lifespan="session" name ="loginChecker" type="package.LoginChecker"> <setfromrequest beanproperty = "*"> </USEBEAN>
4. The LoginChecker bean has a property 'loggedIn'. (It also has properies for Username and Password, and aprocessRequest() method, which are used later).
LoginChecker.jsp checks the value of the loggedIn property. If it is not true (i.e., the user is not logged in), a loginpage is displayed:
<excludeif property ="loginChecker:loggedIn" value = "true"> <FORM action="/servlet/DBAccess/path/to/GuardedPage.jsp" method="post"> Username: <input name="userName" size="15" maxlength="15" > Password: <input type="password" name="password" size="15" maxlength="15"> <input type="submit" name="loginUser" value="Submit"> </FORM> </excludeif>
The first time through, this bean will be 'empty' and the loggedIn property will not be set. The login form will thereforebe displayed.
5. There is a little trick in the action clause above. When the user types in his login info and presses submit, theinvoked URL is
/servlet/DBAccess/path/to/GuardedPage.jsp
The action passes through the servlet DBAccess, then continues on to our original page. This servlet does nothing morethan attach an open database connection to the current session:
session.putValue("open.connection", connection);
The servlet then picks up the trailing part of the URL with:
String trailingURL = request.getPathInfo();
It then calls forward() to pass control back to the requested page. In this example, the new page happens to be the sameas the page we came from.
getServletConfig( ).getServletContext( ).getRequestDispatcher(response.encodeURL(trailingURL) ).forward(request,response);
6. Now we are back to our original page and the logginChecker bean gets invoked again. Because of the:
<setfromrequest beanproperty = "*">
in the loginChecker USEBEAN tag, and because our username and password field names in the LoginChecker.jsp page match ourbean's property names, the username and password that the user typed in get 'magically' populated in the correspondingproperties of the bean.
7. The LoginChecker bean has a processRequest() method which checks to see if a username and password has been supplied.If so (and if we are not logged in), it performs a database lookup to log the user in. If the lookup is successful, theloggedIn property is set to true.
8. We are finally back to our GuardedPage.jsp page. It will probably not want to display itself unless the user is loggedin. The page should therefore only be included if loggedIn is true:
<includeif property="loginChecker:loggedIn" value="true" >
The contents of GuardePage.jsp are displayed only if loggedIn is true.
</includeif>
We're done! GuardedPage.jsp is only displayed if the user is logged in. If the user is not logged in, a login page isdisplayed, which if successful, returns the user to the original page.
9. There is one small cleanup which is needed in Step 4. As coded above, a passthrough servlet is used to attach adatabase connection to the session. If the user repeatedly fails to login, the servlet prefix will get repeatedlypre-pended to the URL. Furthermore, the 'current page' is hardcoded into the LoginChecker.jsp page which restricts it'sreusability. A little JavaScript fixes both of these problems. The following JavaScript should be used in place of the<FORM> tag in Step 4. above.
<script language="JavaScript"> <!-- if (document.location.pathname.indexOf("/servlet/package.DBAccess") == 0) document.write( '<FORM action="' + document.location.pathname + '"method="post">'); else document.write( '<FORM action="/servlet/package.DBAccess' + document.location.pathname + '" method="post">'); //--> </script>
See the QuickStart section of the JSP Book at http://www.esperanto.org.nz/jspbook
There is no requirement that a session object will stay around as far as I can tell, but some web servers will serialize objects if they support the serialization interface.
JRUN, ServletExec and GNUJSP allow you to specify (it was in the 0.91 spec):<%@ include="./header.jsp" %> - where header.jsp is the file you want to include. The spec does say that it supports NCSA style includes as in<!--#include virtual="/pathfromdocdir/" file="copyright.html" --> <!--#include file="data/table.html" --> But there is no requirement that they support JSP.
JRUN, ServletExec and GNUJSP allow you to specify (it was in the 0.91 spec):
<%@ include="./header.jsp" %> - where header.jsp is the file you want to include.
The spec does say that it supports NCSA style includes as in
<!--#include virtual="/pathfromdocdir/" file="copyright.html" --> <!--#include file="data/table.html" -->
But there is no requirement that they support JSP.
From: "Kirkdorffer, Daniel" <daniel.kirkdorffer@ATTWS.COM> HttpSessionBindingListener will hear the events When an object is added and/or remove from the session object, or when the session is invalidated, in which case the objects are first removed from the session, whether the session is invalidated manually or automatically (timeout).
From: "Kirkdorffer, Daniel" <daniel.kirkdorffer@ATTWS.COM>
HttpSessionBindingListener will hear the events When an object is added and/or remove from the session object, or when the session is invalidated, in which case the objects are first removed from the session, whether the session is invalidated manually or automatically (timeout).
There is a little tool called JSPExecutor that allows you to do just that. The developers (Hendrik Schreiber <hs@webapp.de> & Peter Rossbach <pr@webapp.de>) aim was not to write a full blown servlet engine, but to provide means to use JSP for generating source code or reports. Therefore most HTTP-specific features (headers, sessions, etc) are not implemented, i.e. no reponseline or header is generated. Nevertheless you can use it to precompile JSP for your website. JSPExecutor is GPLed and available at no charge at: http://www.webapp.de/jspexecutor.html
There is a little tool called JSPExecutor that allows you to do just that. The developers (Hendrik Schreiber <hs@webapp.de> & Peter Rossbach <pr@webapp.de>) aim was not to write a full blown servlet engine, but to provide means to use JSP for generating source code or reports. Therefore most HTTP-specific features (headers, sessions, etc) are not implemented, i.e. no reponseline or header is generated. Nevertheless you can use it to precompile JSP for your website. JSPExecutor is GPLed and available at no charge at:
http://www.webapp.de/jspexecutor.html
Whichever one works for you. Model 2 can give you more control, especially if you are doing things such as filtering the actual web pages a client receives because of language. Model 1 is generally more simple. A more full description of Model 1 vs Model 2 is at http://www.aptura.com/technology/jspBook_Architectures.html.
From: Chris Fesler <cfesler@InstantObjects.com> A little more experimentation, and I came up with a method to delete cookies. Say that I have a cookie called "foo," that I set a while ago & Iwant it to go away. I simply:<% Cookie killCookie = new Cookie("foo", null); killCookie.setPath("/"); killCookie.setMaxAge(0); response.addCookie(killCookie); %> Note that this is -not- how the JSDK documentation indicates cookies are to be deleted, but what the heck -- it seems to work.
From: Chris Fesler <cfesler@InstantObjects.com>
A little more experimentation, and I came up with a method to delete cookies. Say that I have a cookie called "foo," that I set a while ago & Iwant it to go away. I simply:
<% Cookie killCookie = new Cookie("foo", null); killCookie.setPath("/"); killCookie.setMaxAge(0); response.addCookie(killCookie); %>
Note that this is -not- how the JSDK documentation indicates cookies are to be deleted, but what the heck -- it seems to work.
There is a problem with the startserver.bat file that comes with the Reference implementation when it goes to try and compile JSPs. The problem is that the tools.jar file is missing from the classpath. The symptom occurs as a page like:Unhandled error! You might want to consider having an error page to report such errors more gracefully java.lang.NoClassDefFoundError: sun/tools/javac/Main at com.sun.jsp.compiler.Main.compile(Main.java:194) at com.sun.jsp.runtime.JspLoader.loadJSP(JspLoader.java:114) at com.sun.jsp.runtime.JspServlet$JspServletWrapper.loadIfNecessary(JspServlet. java:69) at com.sun.jsp.runtime.JspServlet$JspServletWrapper.service(JspServlet.java:77) at com.sun.jsp.runtime.JspServlet.serviceJspFile(JspServlet.java:125) at com.sun.jsp.runtime.JspServlet.service(JspServlet.java:152) at javax.servlet.http.HttpServlet.service(HttpServlet.java:840) To fix it, you need to add the tools.jar file from your JDK 1.2 LIB directory to the classpath that is in the startserver.bat file (or just add it to your environment variables). An alternative (from John Zukowski) is to put the tools.jar file into your jre\lib\ext directory.
There is a problem with the startserver.bat file that comes with the Reference implementation when it goes to try and compile JSPs. The problem is that the tools.jar file is missing from the classpath. The symptom occurs as a page like:
Unhandled error! You might want to consider having an error page to report such errors more gracefully java.lang.NoClassDefFoundError: sun/tools/javac/Main at com.sun.jsp.compiler.Main.compile(Main.java:194) at com.sun.jsp.runtime.JspLoader.loadJSP(JspLoader.java:114) at com.sun.jsp.runtime.JspServlet$JspServletWrapper.loadIfNecessary(JspServlet. java:69) at com.sun.jsp.runtime.JspServlet$JspServletWrapper.service(JspServlet.java:77) at com.sun.jsp.runtime.JspServlet.serviceJspFile(JspServlet.java:125) at com.sun.jsp.runtime.JspServlet.service(JspServlet.java:152) at javax.servlet.http.HttpServlet.service(HttpServlet.java:840)
To fix it, you need to add the tools.jar file from your JDK 1.2 LIB directory to the classpath that is in the startserver.bat file (or just add it to your environment variables). An alternative (from John Zukowski) is to put the tools.jar file into your jre\lib\ext directory.
There are a number of things to beware of I'm sure, I have found one in particular so far: From John Langley (langley@NEOTEK.MV.COM), don't have directories in your path that are not valid Java identifiers (for example, they start with a number, or are a number). A number of JSP implementations use the directory your JSP is in as part of the package name and if that is in a directory with an invalid identifier then you are out of luck. Beware of server side includes not recompiling when you have changed them. Some JSP engines won't check into your JSP or create dependency lists to ensure that the entire content of your JSP will be recompiled if a dependency has changed. Many servlet engines don't notice that you change your beans, so that if you change your JSP and change a bean that it uses, although the JSP will reload, the bean will not. This will require you to restart your server. The Virtual Machine has some intrinsic limitations as well (contributed by Costin Manolache), and these affect your JSP. From Virtual Machine Spec: 64k entries in constant pool ( that means the count of strings you can use in out.println(), plus all other constants < 64k ) 64k as the size of a method ( that mean the service() method can't have unlimited number of instructions ) constant string limit is 64k (bytes - not characters!) That may explain the 32K ( since Unicode chars are ~ 2 bytes - sometimes).( it's not the limit of a String - just constant String ). Other tips appreciated! Email me at rvowles@esperanto.org.nz
There are a number of things to beware of I'm sure, I have found one in particular so far:
The Virtual Machine has some intrinsic limitations as well (contributed by Costin Manolache), and these affect your JSP. From Virtual Machine Spec:
Other tips appreciated! Email me at rvowles@esperanto.org.nz
From: Niels Peter Strandberg <nps@HEM1.PASSAGEN.SE> This mail is for all Mac users that want to get started with Java Server Pages on the Mac. This list is base on the mails I got from Mike Engelhart <mengelhart@earthtrip.com>. Who helped me to get my server started. Thanks Mike! Java Server Pages is the Java worlds answer to Active Server Pages on NT. Sun has made a free version witch includes a WebServer and an JSPengine. The package is made in 100% pure Java. So it runs on every Java platform, and it is free. Before you can cook you own Java Server Pages, You need to build the "JSP machine". And here is how to do it. You need the latest MRJ from Apple. MRJ2.1 can be found here: http://www.apple.com/java/. After download run the installer and installthe MRJ. You also need the latest MRJ SDK 2.1 (Im using 2.0 and that works great), that can be found here: http://developer.apple.com/java/text/download.html#sdk. After download run the installer and install the MRJ SDK. You also need the "JavaServer WDK EA (JavaServer Web Development Kit 1.0 EA)" from Sun. This can be found here: http://developer.java.sun.com/developer/earlyAccess/jsp/. I downloaded the Win version, but there should be no problem if you download theSolaris version. After you have downloaded the Zip, unzip it using ZipIt or StuffIt. You have to be a registered member of developer connectionto get access to the files, but that it's free. So go ahead an register yourself. After you have unziped the zip file, place the unziped folder "jswdk-1.0-ea" on the desktop. Now locate the "MRJ SDK 2.1" folder andopen it. Inside that folder is another folder named "JBindery" and inside that folder an app with the same name. Now launche the app "jBindery". Click on the"Command" icon and add this to the Class name field: "com.sun.web.shell.Startup". Leave theoptional parameters blank. Click on the "Classpath" icon. Click on the "add .zip file..." button and add the following files: "webserver.jar" which is in the root of your "jswdk-1.0-ea" folder. Also add the following files which are in the "lib" folder: "jsp.jar" and "jspengine.jar" and "servlet.jar" Click on the "add folder..." button and ad the following folder "beans" locate in examples/WEB-INF/jsp/ Now you are ready to save these setting as an click able application. Click on the "Save Settings..." button, and give your "app" a name (ex.JSP Server) and make sure the check box "save as App" is checked. Make sure that you save the app in the root of the "jswdk-1.0-ea" folder. Now you have embedded these setting in an application file. Now locate your "JSP Server" application and double click on it. Wait a few seconds, and your server should be up an running. The app will quit if it cant find a IP number. Go into your TCP/IP control panel and assign a permanent IP number (ex. 127.0.0.1). Then try to run the app again. The JPS Server will run at port 8080 by default. You can change that by opening the "default.cfg" file in a text editor and change the "server.port" from 8080 to 80, witch is the default port for WebServers. Now here is where the fun begins. Open your web browser and type in the IP number you assigned to you mac in the TCP/IP control panel. (http://127.0.0.1) or (http://127.0.0.1:8080) if you didn't change the port setting in the "default.cfg" file. Now, explore the example and when your are ready, cook your own JSP.
From: Niels Peter Strandberg <nps@HEM1.PASSAGEN.SE>
This mail is for all Mac users that want to get started with Java Server Pages on the Mac.
This list is base on the mails I got from Mike Engelhart <mengelhart@earthtrip.com>. Who helped me to get my server started. Thanks Mike!
Java Server Pages is the Java worlds answer to Active Server Pages on NT. Sun has made a free version witch includes a WebServer and an JSPengine. The package is made in 100% pure Java. So it runs on every Java platform, and it is free.
Before you can cook you own Java Server Pages, You need to build the "JSP machine". And here is how to do it.
Originally contributed by Daniel Kirkdorffer, daniel.kirkdorffer@attws.com. See also http://www.interpasnet.com/JSS/textes/jsp2.htm or http://www.flashline.com/components/appservermatrix.jsp
They were left out in JSP 1.0 onwards. There was no explanation given. They may be able to be expressed as tag extensions but I have not investigated the 1.1 API yet to determine how that could be done.
The reference implementation for 1.0 got the name of the import tag wrong. They put "import" in the specification and "imports" into the reference implementation. Thus, when you would have expected to use <%@ page import="myclasses.*" %> you need to use <%@ page imports="myclasses.*" %> instead.
The reference implementation for 1.0 got the name of the import tag wrong. They put "import" in the specification and "imports" into the reference implementation. Thus, when you would have expected to use
<%@ page import="myclasses.*" %>
you need to use
<%@ page imports="myclasses.*" %>
instead.
Get a look at the MultipartRequest object from the author of "Java Servlet Programming" (O'Reilly). Home page is http://www.servlets.com/index.html. The zip file for this class and other useful classes is at http://www.servlets.com/resources/com.oreilly.servlet/cos.zip.
Yes. Because your JSP is just a servlet method, you can just put (whereever necessary) a<% return; %>
Yes. Because your JSP is just a servlet method, you can just put (whereever necessary) a
<% return; %>