The problem is that in this case, your TesteDispatcher, while it may be a
servlet, it's not one that's been configured by the container. Your JSP is
using it simply as a class.
The container will process the <Context> entry and set up the internal data
properly before calling your Servlet. In your case, YOU are calling your
Servlet, and YOU haven't gone through all of the work that the container
does. So, there lies the core of your misunderstanding. Just by simply being
of the class Servlet does not necessarily make Magic Happen the way you're
thinking. The Servlet class is just the holder of the information, the
container (Tomcat in this case) does the actual Magic.
So how to work around it?
The first thing to note is that if you want your Data Access Class (the one
actually calling JDBC) to fetch and use the URL, then you can't use any of
the Servlet/WebApp based configuration methods, as your class won't have any
direct access to the Servlet based information. You can fix that by passing
the Servlet info into the class, but that's kind of yucky.
So, the other alternative is to make your Data Access Class more self
contained, relying on something from the environment to get your
information. We've already talked about a lot of those techniques, including
Properties and JNDI.
Properties are a bit of a pain because while they can be in the webapp,
they'd be just as static as anything else from deploy to deploy. To use them
properly, you'd have to put the properties someplace in the system classpath
of Tomcat, making it one extra file to lose in the confusion of deployment
and multiple classpaths. (Page 1, Paragraph 1 of the "How to Solve Java
Problems" 'Check Your ClassPath').
JNDI, however, is a global resource accessible to everything. It can also be
really complicated to set up, with yet more properties and classpaths.
But, both the Servlet spec and Tomcat handle a lot of the JNDI setup for
you. By the time you need access to JNDI, it's already been configured.
The interesting crossover is that you can use ENV-ENTRY in the web.xml
(which is embedded in your webapp) to populate JNDI (which is, as I said, a
global resource). The fact that you can override the ENV-ENTRY elements in a
Tomcat Context, as was mentioned before, makes that a pretty powerful
technique, I think.
So, here's the Hard Work.
First, your inner function, a do-nothing class:
located in WEB-INF/classes/test/Util.class
--------------------------
package test;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class Util
{
public Util()
{
}
public String getResult()
{
String result;
try {
InitialContext ctx = new InitialContext();
result = (String)ctx.lookup("java:comp/env/db.url");
}
catch(NamingException ne) {
result = String.valueOf(ne); // Shows us the
exception if something goes wrong.
}
return result;
}
}
-----------------------------
Pay particular attention to the ctx.lookup line and the "db.url" part.
Next file: WEB-INF/web.xml
------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<env-entry>
<env-entry-name>db.url</env-entry-name>
<env-entry-value>your:jdbc:url</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>
</web-app>
-------------------------------
Braindead webapp, no servlets here. The key, again, is the <env-entry-name>
with db.url, and the value "your:jdbc:url".
Finally, a simple test jsp, located in the root of your webapp.
--------------------------------
<%@ page language="java" %>
<%@ page import="test.Util" %>
<html>
<title>This is a test</title>
<body>
<%
Util u = new Util();
String result = u.getResult();
%>
<br>The test result is '<%=result%>'<br>
</body>
</html>
---------------------------------
Note, how we're using the simple Util class, and asking it for information.
The Util class has NO KNOWLEDGE that it's even in a Servlet container.
Anyway, jar all of those files into a test.war file, and plop it into your
webapp directory in Tomcat, and you should see the "your:jdbc:url" appear on
the web page at http:/yourhost:8080/test/test.jsp
Now, the real magic here is even though the db.url is coded in the Webapp,
you can override it in the Context entry on the server.xml in Tomcat 4.
Voila (in $TOMCAT_HOME/conf/server.xml)
<Context path="/test" docBase="test">
<Environment name="db.url" type="java.lang.String"
value="tomcats:jdbc:url" override="false"/>
</Context>
Running test.jsp again and you'll see the "tomcats:jdbc:url". Magic.
Mind you this only works in Tomcat 4, as far as I can tell, not Tomcat 3.x
So, basically, using JNDI, and adding, what, two lines of code to your
method, you can get a configurable parameter in ANY class: JSP, Servlet,
Util class, and later in J2EE classes. So, you can use it for other
parameters as well. ENV-ENTRY only lets you use the simple types in Java,
but as you look deeper into JNDI you can have an initialization routine
populate the JNDI environment with pretty much anything you want. And this
doesn't even touch the larger scope for which JNDI was developed.
However, this is a simple use of JNDI and directly solves your problem.
Perhaps others will be able to able to take advantage of this technique as
well.
Also, it's not all my idea. I got all of this information from this thread,
and simply consolidated it into this more comprehensive post. It's all the
mailing lists fault, I had nothing to do with it.
Good Luck!
Best Regards,
Will Hartung
([EMAIL PROTECTED])
----- Original Message -----
From: "Christian J. Dechery" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Sent: Wednesday, July 10, 2002 6:33 AM
Subject: Re: Need Ideas... big problem! (long)
didn't work... I did a test here to see if this thing worked before
implementing the Connection Dispatcher...
the Servlet can't find the context in which the JSP that called it is...
here's what I did:
* created two classes TesteDispatcher and TesteCallDispatcher.
TesteDispatcher is the Servlet, and TesteCallDispatcher is just a dummy
class to make a call to this servlet...
* I then placed both classes in $tomcat_home\common\classes
* created a context called \teste1
<Context path="/teste1" docBase="teste1" debug="0" reloadable="true">
<Parameter name="url" value="URL do Contexto teste1" override="false"/>
</Context>
* created a JSP called teste.jsp
<%@page import="dispatch.TesteCallDispatcher"%>
<%
TesteCallDispatcher tcd = new TesteCallDispatcher();
out.println("A URL para esse contexto � \""+tcd.myContextURL()+"\".");
%>
when I execute it, nothing happens... there is a call in TesteDispatcher
like this:
ServletConfig sConf = getServletConfig(); <-- this is returning NULL
what did I do wrong? Or was it that I missunderstood ur solution, or even, u
missunderstood my problem. :)
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>